Various license header consistency fixes (trivial).
[coreboot.git] / src / southbridge / ricoh / rl5c476 / rl5c476.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2004-2005 Nick Barker <nick.barker@btinternet.com>
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <arch/io.h>
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>
28 #include <delay.h>
29 #include "rl5c476.h"
30 #include "chip.h"
31
32 static int enable_cf_boot = 0;
33 static unsigned int cf_base;
34
35 static void rl5c476_init(device_t dev)
36 {
37         pc16reg_t *pc16;
38         unsigned char *base;
39
40         /* cardbus controller function 1 for CF Socket */
41         printk_debug("Ricoh RL5c476: Initializing.\n");
42
43         printk_debug("CF Base = %0x\n",cf_base);
44
45         /* misc control register */
46         pci_write_config16(dev,0x82,0x00a0);
47
48         /* set up second slot as compact flash port if asked to do so */
49
50         if (!enable_cf_boot) {
51                 printk_debug("CF boot not enabled.\n");
52                 return;
53         }
54         
55         if (PCI_FUNC(dev->path.pci.devfn) != 1) {
56                 // Only configure if second CF slot.
57                 return;
58         }
59
60         /* make sure isa interrupts are enabled */
61         pci_write_config16(dev,0x3e,0x0780);
62
63         /* pick up where 16 bit card control structure is
64          * (0x800 bytes into config structure)
65          */
66         base = (unsigned char *)pci_read_config32(dev,0x10);
67         pc16 = (pc16reg_t *)(base + 0x800);
68
69         /* disable memory and io windows and turn off socket power */
70         pc16->pwctrl = 0;
71
72         /* disable irq lines */
73         pc16->igctrl = 0;
74
75         /* disable memory and I/O windows */
76         pc16->awinen = 0;
77
78         /* reset card, configure for I/O and set IRQ line */
79         pc16->igctrl = 0x69;
80
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.
87          *
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
94          * boot.
95          *
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.
100          */
101         pc16->iostl0 = 0xe0;
102         pc16->iosth0 = 1;
103
104         pc16->iospl0 = 0xef;
105         pc16->iosph0 = 1;
106
107         pc16->ioffl0 = 0;
108         pc16->ioffh0 = 0;
109
110         /* clear window 1 */
111         pc16->iostl1 = 0;
112         pc16->iosth1 = 0;
113
114         pc16->iospl1 = 0;
115         pc16->iosph1 = 0;
116
117         pc16->ioffl1 = 0x0;
118         pc16->ioffh1 = 0;
119
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;
126         pc16->moffl0 = 0;
127         pc16->moffh0 = 0x40;
128
129
130         /* set I/O width for Auto Data width */
131         pc16->ioctrl = 0x22;
132
133
134         /* enable I/O window 0 and 1 */
135         pc16->awinen = 0xc1;
136
137         pc16->miscc1 = 1;
138
139         /* apply power and enable outputs */
140         pc16->pwctrl = 0xb0;
141
142         // delay could be optimised, but this works
143         udelay(100000);
144
145         pc16->igctrl = 0x69;
146
147
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
151          * do for now.
152          */
153         unsigned char *cptr;
154         cptr = (unsigned char *)(cf_base + 0x200);
155         printk_debug("CF Config = %x\n",*cptr);
156
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)
161          */
162         *cptr = 0x41;
163 }
164
165 void rl5c476_read_resources(device_t dev)
166 {
167
168         struct resource *resource;
169
170          /* For CF socket we need an extra memory window for 
171           * the control structure of the CF itself
172           */
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;
180         }
181         cardbus_read_resources(dev);
182 }
183
184 void rl5c476_set_resources(device_t dev)
185 {
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;
194                 }
195         }
196
197         pci_dev_set_resources(dev);
198
199 }
200
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,
207 };
208
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,
213 };
214
215 void southbridge_init(device_t dev)
216 {
217
218         struct southbridge_ricoh_rl5c476_config *conf = dev->chip_info;
219         enable_cf_boot = conf->enable_cf;
220
221 }
222
223 struct chip_operations southbridge_ricoh_rl5c476_ops = {
224         CHIP_NAME("Ricoh RL5C476 CardBus Controller")
225         .enable_dev    = southbridge_init,
226 };