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.
18 #include <device/device.h>
19 #include <device/pci.h>
20 #include <device/pci_ops.h>
21 #include <device/pci_ids.h>
22 #include <console/console.h>
23 #include <device/cardbus.h>
28 static int enable_cf_boot
= 0;
29 static unsigned int cf_base
;
31 static void rl5c476_init(device_t dev
)
36 /* cardbus controller function 1 for CF Socket */
37 printk(BIOS_DEBUG
, "Ricoh RL5c476: Initializing.\n");
39 printk(BIOS_DEBUG
, "CF Base = %0x\n",cf_base
);
41 /* misc control register */
42 pci_write_config16(dev
,0x82,0x00a0);
44 /* set up second slot as compact flash port if asked to do so */
46 if (!enable_cf_boot
) {
47 printk(BIOS_DEBUG
, "CF boot not enabled.\n");
51 if (PCI_FUNC(dev
->path
.pci
.devfn
) != 1) {
52 // Only configure if second CF slot.
56 /* make sure isa interrupts are enabled */
57 pci_write_config16(dev
,0x3e,0x0780);
59 /* pick up where 16 bit card control structure is
60 * (0x800 bytes into config structure)
62 base
= (unsigned char *)pci_read_config32(dev
,0x10);
63 pc16
= (pc16reg_t
*)(base
+ 0x800);
65 /* disable memory and io windows and turn off socket power */
68 /* disable irq lines */
71 /* disable memory and I/O windows */
74 /* reset card, configure for I/O and set IRQ line */
77 /* set io window 0 for 1e0 - 1ef */
78 /* NOTE: This now sets CF up on a contiguous I/O window of
79 * 16 bytes, 0x1e0 to 0x1ef.
80 * Be warned that this is not a standard IDE address as
81 * automatically detected by the likes of FILO, and would need
82 * patching to recognize these addresses as an IDE drive.
84 * An earlier version of this driver set up 2 I/O windows to
85 * emulate the expected addresses for IDE2, however the PCMCIA
86 * package within Linux then could not re-initialize the
87 * device as it tried to take control of it. So I believe it is
88 * easier to patch Filo or the like to pick up this drive
89 * rather than playing silly games as the kernel tries to
92 * Nonetheless, FILO needs a special option enabled to boot
93 * from this configuration, and it needs to clean up
94 * afterwards. Please refer to FILO documentation and source
95 * code for more details.
116 /* set up CF config window */
117 pc16
->smpga0
= cf_base
>>24;
118 pc16
->smsth0
= (cf_base
>>20)&0x0f;
119 pc16
->smstl0
= (cf_base
>>12)&0xff;
120 pc16
->smsph0
= ((cf_base
>>20)&0x0f) | 0x80;
121 pc16
->smspl0
= (cf_base
>>12)&0xff;
126 /* set I/O width for Auto Data width */
130 /* enable I/O window 0 and 1 */
135 /* apply power and enable outputs */
138 // delay could be optimised, but this works
144 /* 16 bit CF always have first config byte at 0x200 into
145 * Config structure, but CF+ may not according to spec -
146 * should locate through reading tuple data, but this should
150 cptr
= (unsigned char *)(cf_base
+ 0x200);
151 printk(BIOS_DEBUG
, "CF Config = %x\n",*cptr
);
153 /* Set CF to decode 16 IO bytes on any 16 byte boundary -
154 * rely on the io windows of the bridge set up above to
155 * map those bytes into the addresses for IDE controller 3
156 * (0x1e8 - 0x1ef and 0x3ed - 0x3ee)
161 static void rl5c476_read_resources(device_t dev
)
164 struct resource
*resource
;
166 /* For CF socket we need an extra memory window for
167 * the control structure of the CF itself
169 if( enable_cf_boot
&& (PCI_FUNC(dev
->path
.pci
.devfn
) == 1)){
170 /* fake index as it isn't in PCI config space */
171 resource
= new_resource(dev
, 1);
172 resource
->flags
|= IORESOURCE_MEM
;
173 resource
->size
= 0x1000;
174 resource
->align
= resource
->gran
= 12;
175 resource
->limit
= 0xffff0000;
177 cardbus_read_resources(dev
);
180 static void rl5c476_set_resources(device_t dev
)
182 struct resource
*resource
;
183 printk(BIOS_DEBUG
, "%s In set resources\n",dev_path(dev
));
184 if( enable_cf_boot
&& (PCI_FUNC(dev
->path
.pci
.devfn
) == 1)){
185 resource
= find_resource(dev
,1);
186 if( !(resource
->flags
& IORESOURCE_STORED
) ){
187 resource
->flags
|= IORESOURCE_STORED
;
188 printk(BIOS_DEBUG
, "%s 1 ==> %llx\n", dev_path(dev
), resource
->base
);
189 cf_base
= resource
->base
;
193 pci_dev_set_resources(dev
);
197 static void rl5c476_set_subsystem(device_t dev
, unsigned vendor
, unsigned device
)
199 u16 miscreg
= pci_read_config16(dev
, 0x82);
200 /* Enable subsystem id register writes */
201 pci_write_config16(dev
, 0x82, miscreg
| 0x40);
203 pci_write_config16(dev
, 0x40, vendor
);
204 pci_write_config16(dev
, 0x42, device
);
205 /* restore original contents */
206 pci_write_config16(dev
, 0x82, miscreg
);
209 static struct pci_operations rl5c476_pci_ops
= {
210 .set_subsystem
= rl5c476_set_subsystem
,
213 static struct device_operations ricoh_rl5c476_ops
= {
214 .read_resources
= rl5c476_read_resources
,
215 .set_resources
= rl5c476_set_resources
,
216 .enable_resources
= cardbus_enable_resources
,
217 .init
= rl5c476_init
,
218 .scan_bus
= pci_scan_bridge
,
219 .ops_pci
= &rl5c476_pci_ops
,
222 static const struct pci_driver ricoh_rl5c476_driver __pci_driver
= {
223 .ops
= &ricoh_rl5c476_ops
,
224 .vendor
= PCI_VENDOR_ID_RICOH
,
225 .device
= PCI_DEVICE_ID_RICOH_RL5C476
,
228 static void southbridge_init(device_t dev
)
230 struct southbridge_ricoh_rl5c476_config
*conf
= dev
->chip_info
;
231 enable_cf_boot
= conf
->enable_cf
;
234 struct chip_operations southbridge_ricoh_rl5c476_ops
= {
235 CHIP_NAME("Ricoh RL5C476 CardBus Controller")
236 .enable_dev
= southbridge_init
,