2 * This file is part of the coreboot project.
4 * Copyright (C) 2004-2005 Nick Barker <nick.barker@btinternet.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include <device/device.h>
23 #include <device/pci.h>
24 #include <device/pci_ops.h>
25 #include <device/pci_ids.h>
26 #include <console/console.h>
27 #include <device/cardbus.h>
32 static int enable_cf_boot = 0;
33 static unsigned int cf_base;
35 static void rl5c476_init(device_t dev)
40 /* cardbus controller function 1 for CF Socket */
41 printk_debug("Ricoh RL5c476: Initializing.\n");
43 printk_debug("CF Base = %0x\n",cf_base);
45 /* misc control register */
46 pci_write_config16(dev,0x82,0x00a0);
48 /* set up second slot as compact flash port if asked to do so */
50 if (!enable_cf_boot) {
51 printk_debug("CF boot not enabled.\n");
55 if (PCI_FUNC(dev->path.pci.devfn) != 1) {
56 // Only configure if second CF slot.
60 /* make sure isa interrupts are enabled */
61 pci_write_config16(dev,0x3e,0x0780);
63 /* pick up where 16 bit card control structure is
64 * (0x800 bytes into config structure)
66 base = (unsigned char *)pci_read_config32(dev,0x10);
67 pc16 = (pc16reg_t *)(base + 0x800);
69 /* disable memory and io windows and turn off socket power */
72 /* disable irq lines */
75 /* disable memory and I/O windows */
78 /* reset card, configure for I/O and set IRQ line */
81 /* set io window 0 for 1e0 - 1ef */
82 /* NOTE: This now sets CF up on a contiguous I/O window of
83 * 16 bytes, 0x1e0 to 0x1ef.
84 * Be warned that this is not a standard IDE address as
85 * automatically detected by the likes of FILO, and would need
86 * patching to recognise these addresses as an IDE drive.
88 * An earlier version of this driver set up 2 I/O windows to
89 * emulate the expected addresses for IDE2, however the PCMCIA
90 * package within Linux then could not re-initialize the
91 * device as it tried to take control of it. So I believe it is
92 * easier to patch Filo or the like to pick up this drive
93 * rather than playing silly games as the kernel tries to
96 * Nonetheless, FILO needs a special option enabled to boot
97 * from this configuration, and it needs to clean up
98 * afterwards. Please refer to FILO documentation and source
99 * code for more details.
120 /* set up CF config window */
121 pc16->smpga0 = cf_base>>24;
122 pc16->smsth0 = (cf_base>>20)&0x0f;
123 pc16->smstl0 = (cf_base>>12)&0xff;
124 pc16->smsph0 = ((cf_base>>20)&0x0f) | 0x80;
125 pc16->smspl0 = (cf_base>>12)&0xff;
130 /* set I/O width for Auto Data width */
134 /* enable I/O window 0 and 1 */
139 /* apply power and enable outputs */
142 // delay could be optimised, but this works
148 /* 16 bit CF always have first config byte at 0x200 into
149 * Config structure, but CF+ may not according to spec -
150 * should locate through reading tuple data, but this should
154 cptr = (unsigned char *)(cf_base + 0x200);
155 printk_debug("CF Config = %x\n",*cptr);
157 /* Set CF to decode 16 IO bytes on any 16 byte boundary -
158 * rely on the io windows of the bridge set up above to
159 * map those bytes into the addresses for IDE controller 3
160 * (0x1e8 - 0x1ef and 0x3ed - 0x3ee)
165 void rl5c476_read_resources(device_t dev)
168 struct resource *resource;
170 /* For CF socket we need an extra memory window for
171 * the control structure of the CF itself
173 if( enable_cf_boot && (PCI_FUNC(dev->path.pci.devfn) == 1)){
174 /* fake index as it isn't in PCI config space */
175 resource = new_resource(dev, 1);
176 resource->flags |= IORESOURCE_MEM;
177 resource->size = 0x1000;
178 resource->align = resource->gran = 12;
179 resource->limit= 0xffff0000;
181 cardbus_read_resources(dev);
184 void rl5c476_set_resources(device_t dev)
186 struct resource *resource;
187 printk_debug("%s In set resources \n",dev_path(dev));
188 if( enable_cf_boot && (PCI_FUNC(dev->path.pci.devfn) == 1)){
189 resource = find_resource(dev,1);
190 if( !(resource->flags & IORESOURCE_STORED) ){
191 resource->flags |= IORESOURCE_STORED ;
192 printk_debug("%s 1 ==> %x\n", dev_path(dev), resource->base);
193 cf_base = resource->base;
197 pci_dev_set_resources(dev);
201 static struct device_operations ricoh_rl5c476_ops = {
202 .read_resources = rl5c476_read_resources,
203 .set_resources = rl5c476_set_resources,
204 .enable_resources = cardbus_enable_resources,
205 .init = rl5c476_init,
206 .scan_bus = cardbus_scan_bridge,
209 static const struct pci_driver ricoh_rl5c476_driver __pci_driver = {
210 .ops = &ricoh_rl5c476_ops,
211 .vendor = PCI_VENDOR_ID_RICOH,
212 .device = PCI_DEVICE_ID_RICOH_RL5C476,
215 void southbridge_init(device_t dev)
218 struct southbridge_ricoh_rl5c476_config *conf = dev->chip_info;
219 enable_cf_boot = conf->enable_cf;
223 struct chip_operations southbridge_ricoh_rl5c476_ops = {
224 CHIP_NAME("Ricoh RL5C476 CardBus Controller")
225 .enable_dev = southbridge_init,