2 * (C) Copyright 2004 Nick Barker <nick.barker9@btinternet.com>
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
19 /* (C) Copyright 2005 Nick Barker <nick.barker@btinternet.com
20 brought into line with the current architecture of coreboot */
23 #include <device/device.h>
24 #include <device/pci.h>
25 #include <device/pci_ops.h>
26 #include <device/pci_ids.h>
27 #include <console/console.h>
28 #include <device/cardbus.h>
32 static int enable_cf_boot = 0;
33 static unsigned int cf_base;
35 static void udelay(int i)
41 static void rl5c476_init(device_t dev)
43 //unsigned char enables;
48 /* cardbus controller function 1 for CF Socket */
49 printk_debug("rl5c476 init\n");
51 printk_debug("CF Base = %0x\n",cf_base);
53 /* misc control register */
54 pci_write_config16(dev,0x82,0x00a0);
56 /* set up second slot as compact flash port if asked to do so */
57 if( enable_cf_boot && (PCI_FUNC(dev->path.pci.devfn) == 1)){
59 /* make sure isa interrupts are enabled */
60 pci_write_config16(dev,0x3e,0x0780);
62 /* pick up where 16 bit card control structure is (0x800 bytes into config structure) */
63 base = (unsigned char *)pci_read_config32(dev,0x10);
64 pc16 = (pc16reg_t *)(base + 0x800);
66 /* disable memory and io windows and turn off socket power */
69 /* disable irq lines */
72 /* disable memory and I/O windows */
75 /* reset card, configure for I/O and set IRQ line */
78 // set io window 0 for 1e0 - 1ef
79 /* note this now sets CF up on a contiguous I/O window of 16 bytes, 0x1e0 to 0x1ef
80 Be warned that this is not a standard IDE address as automatically detected by the likes
81 of Filo, and would need patching to recognise these addresses as an IDE drive */
82 /* an earlier version of this driver set up 2 io windows to emulate the expected addresses
83 for IDE2, however the pcmcia package within Linux then could not re-initiailse the
84 device as it tried to take control of it. So I belive it is easier to patch Filo or the like
85 to pick up this drive rather than playing silly games as the kernel tries to boot.
106 // set up CF config window
107 pc16->smpga0 = cf_base>>24;
108 pc16->smsth0 = (cf_base>>20)&0x0f;
109 pc16->smstl0 = (cf_base>>12)&0xff;
110 pc16->smsph0 = ((cf_base>>20)&0x0f) | 0x80;
111 pc16->smspl0 = (cf_base>>12)&0xff;
116 // set I/O width for Auto Data width
120 // enable I/O window 0 and 1
126 // apply power and enable outputs
130 // delay could be optimised, but this works
136 // 16 bit CF always have first config byte at 0x200 into Config structure,
137 // but CF+ May Not according to spec - should locate through reading tuple data,
138 // but this will do for now !!!
140 cptr = (unsigned char *)(cf_base + 0x200);
141 printk_debug("CF Config = %x\n",*cptr);
143 // set CF to decode 16 IO bytes on any 16 byte boundary - rely on the io
144 // windows of the bridge set up above to map those bytes into the
145 // addresses for ide controller 3 (0x1e8 - 0x1ef and 0x3ed - 0x3ee)
151 void rl5c476_read_resources(device_t dev)
154 struct resource *resource;
156 /* for cf socket we need an extra memory window for the control structure of the cf itself */
157 if( enable_cf_boot && (PCI_FUNC(dev->path.pci.devfn) == 1)){
158 resource = new_resource(dev,1); /* fake index as it isn't in pci config space */
159 resource->flags |= IORESOURCE_MEM ;
160 resource->size = 0x1000;
161 resource->align = resource->gran = 12;
162 resource->limit= 0xffff0000;
164 cardbus_read_resources(dev);
167 void rl5c476_set_resources(device_t dev)
169 struct resource *resource;
170 printk_debug("%s In set resources \n",dev_path(dev));
171 if( enable_cf_boot && (PCI_FUNC(dev->path.pci.devfn) == 1)){
172 resource = find_resource(dev,1);
173 if( !(resource->flags & IORESOURCE_STORED) ){
174 resource->flags |= IORESOURCE_STORED ;
175 printk_debug("%s 1 ==> %x\n",dev_path(dev),resource->base);
176 cf_base = resource->base;
180 pci_dev_set_resources(dev);
184 static struct device_operations ricoh_rl5c476_ops = {
185 .read_resources = rl5c476_read_resources,
186 .set_resources = rl5c476_set_resources,
187 .enable_resources = cardbus_enable_resources,
188 .init = rl5c476_init,
189 .scan_bus = cardbus_scan_bridge,
192 static const struct pci_driver ricoh_rl5c476_driver __pci_driver = {
193 .ops = &ricoh_rl5c476_ops,
194 .vendor = PCI_VENDOR_ID_RICOH,
195 .device = PCI_DEVICE_ID_RICOH_RL5C476,
198 void southbridge_init(device_t dev)
201 struct southbridge_ricoh_rl5c476_config *conf = dev->chip_info;
202 enable_cf_boot = conf->enable_cf;
206 struct chip_operations southbridge_ricoh_rl5c476_ops = {
207 CHIP_NAME("Ricoh RL5C476 CardBus Controller")
208 .enable_dev = southbridge_init,