blob: 799619775e27d5fbeb282e48771bead9f7e59305 [file] [log] [blame]
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +00001/*
Stefan Reinauer925b6c02009-07-21 20:27:00 +00002 * (C) Copyright 2004-2005 Nick Barker <nick.barker@btinternet.com>
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +00003 *
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +00004 * 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.
8 *
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.
13 *
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
Ronald G. Minnich94425912005-11-22 16:47:40 +000016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
17 * MA 02110-1301 USA
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000018 */
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000019
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000020#include <arch/io.h>
21#include <device/device.h>
22#include <device/pci.h>
23#include <device/pci_ops.h>
24#include <device/pci_ids.h>
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000025#include <console/console.h>
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000026#include <device/cardbus.h>
Stefan Reinaueraecf2512009-07-21 22:01:21 +000027#include <delay.h>
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000028#include "rl5c476.h"
29#include "chip.h"
30
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000031static int enable_cf_boot = 0;
32static unsigned int cf_base;
33
Eric Biedermandbec2d42004-10-21 10:44:08 +000034static void rl5c476_init(device_t dev)
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000035{
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000036 pc16reg_t *pc16;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000037 unsigned char *base;
38
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000039 /* cardbus controller function 1 for CF Socket */
Stefan Reinauer925b6c02009-07-21 20:27:00 +000040 printk_debug("Ricoh RL5c476: Initializing.\n");
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000041
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000042 printk_debug("CF Base = %0x\n",cf_base);
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000043
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000044 /* misc control register */
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000045 pci_write_config16(dev,0x82,0x00a0);
46
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000047 /* set up second slot as compact flash port if asked to do so */
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000048
Stefan Reinauer925b6c02009-07-21 20:27:00 +000049 if (!enable_cf_boot) {
50 printk_debug("CF boot not enabled.\n");
51 return;
52 }
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000053
Stefan Reinauer925b6c02009-07-21 20:27:00 +000054 if (PCI_FUNC(dev->path.pci.devfn) != 1) {
55 // Only configure if second CF slot.
56 return;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000057 }
58
Stefan Reinauer925b6c02009-07-21 20:27:00 +000059 /* make sure isa interrupts are enabled */
60 pci_write_config16(dev,0x3e,0x0780);
61
62 /* pick up where 16 bit card control structure is
63 * (0x800 bytes into config structure)
64 */
65 base = (unsigned char *)pci_read_config32(dev,0x10);
66 pc16 = (pc16reg_t *)(base + 0x800);
67
68 /* disable memory and io windows and turn off socket power */
69 pc16->pwctrl = 0;
70
71 /* disable irq lines */
72 pc16->igctrl = 0;
73
74 /* disable memory and I/O windows */
75 pc16->awinen = 0;
76
77 /* reset card, configure for I/O and set IRQ line */
78 pc16->igctrl = 0x69;
79
80 /* set io window 0 for 1e0 - 1ef */
81 /* NOTE: This now sets CF up on a contiguous I/O window of
82 * 16 bytes, 0x1e0 to 0x1ef.
83 * Be warned that this is not a standard IDE address as
84 * automatically detected by the likes of FILO, and would need
85 * patching to recognise these addresses as an IDE drive.
86 *
87 * An earlier version of this driver set up 2 I/O windows to
88 * emulate the expected addresses for IDE2, however the PCMCIA
89 * package within Linux then could not re-initialize the
90 * device as it tried to take control of it. So I believe it is
91 * easier to patch Filo or the like to pick up this drive
92 * rather than playing silly games as the kernel tries to
93 * boot.
94 *
95 * Nonetheless, FILO needs a special option enabled to boot
96 * from this configuration, and it needs to clean up
97 * afterwards. Please refer to FILO documentation and source
98 * code for more details.
99 */
100 pc16->iostl0 = 0xe0;
101 pc16->iosth0 = 1;
102
103 pc16->iospl0 = 0xef;
104 pc16->iosph0 = 1;
105
106 pc16->ioffl0 = 0;
107 pc16->ioffh0 = 0;
108
109 /* clear window 1 */
110 pc16->iostl1 = 0;
111 pc16->iosth1 = 0;
112
113 pc16->iospl1 = 0;
114 pc16->iosph1 = 0;
115
116 pc16->ioffl1 = 0x0;
117 pc16->ioffh1 = 0;
118
119 /* set up CF config window */
120 pc16->smpga0 = cf_base>>24;
121 pc16->smsth0 = (cf_base>>20)&0x0f;
122 pc16->smstl0 = (cf_base>>12)&0xff;
123 pc16->smsph0 = ((cf_base>>20)&0x0f) | 0x80;
124 pc16->smspl0 = (cf_base>>12)&0xff;
125 pc16->moffl0 = 0;
126 pc16->moffh0 = 0x40;
127
128
129 /* set I/O width for Auto Data width */
130 pc16->ioctrl = 0x22;
131
132
133 /* enable I/O window 0 and 1 */
134 pc16->awinen = 0xc1;
135
136 pc16->miscc1 = 1;
137
138 /* apply power and enable outputs */
139 pc16->pwctrl = 0xb0;
140
141 // delay could be optimised, but this works
142 udelay(100000);
143
144 pc16->igctrl = 0x69;
145
146
147 /* 16 bit CF always have first config byte at 0x200 into
148 * Config structure, but CF+ may not according to spec -
149 * should locate through reading tuple data, but this should
150 * do for now.
151 */
152 unsigned char *cptr;
153 cptr = (unsigned char *)(cf_base + 0x200);
154 printk_debug("CF Config = %x\n",*cptr);
155
156 /* Set CF to decode 16 IO bytes on any 16 byte boundary -
157 * rely on the io windows of the bridge set up above to
158 * map those bytes into the addresses for IDE controller 3
159 * (0x1e8 - 0x1ef and 0x3ed - 0x3ee)
160 */
161 *cptr = 0x41;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000162}
163
164void rl5c476_read_resources(device_t dev)
165{
166
167 struct resource *resource;
168
Stefan Reinauer925b6c02009-07-21 20:27:00 +0000169 /* For CF socket we need an extra memory window for
170 * the control structure of the CF itself
171 */
Stefan Reinauer2b34db82009-02-28 20:10:20 +0000172 if( enable_cf_boot && (PCI_FUNC(dev->path.pci.devfn) == 1)){
Stefan Reinauer925b6c02009-07-21 20:27:00 +0000173 /* fake index as it isn't in PCI config space */
174 resource = new_resource(dev, 1);
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000175 resource->flags |= IORESOURCE_MEM ;
176 resource->size = 0x1000;
177 resource->align = resource->gran = 12;
178 resource->limit= 0xffff0000;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000179 }
180 cardbus_read_resources(dev);
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000181}
182
183void rl5c476_set_resources(device_t dev)
184{
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000185 struct resource *resource;
186 printk_debug("%s In set resources \n",dev_path(dev));
Stefan Reinauer2b34db82009-02-28 20:10:20 +0000187 if( enable_cf_boot && (PCI_FUNC(dev->path.pci.devfn) == 1)){
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000188 resource = find_resource(dev,1);
189 if( !(resource->flags & IORESOURCE_STORED) ){
190 resource->flags |= IORESOURCE_STORED ;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000191 printk_debug("%s 1 ==> %x\n",dev_path(dev),resource->base);
192 cf_base = resource->base;
193 }
194 }
195
196 pci_dev_set_resources(dev);
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +0000197
198}
199
Eric Biedermandbec2d42004-10-21 10:44:08 +0000200static struct device_operations ricoh_rl5c476_ops = {
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000201 .read_resources = rl5c476_read_resources,
202 .set_resources = rl5c476_set_resources,
203 .enable_resources = cardbus_enable_resources,
204 .init = rl5c476_init,
205 .scan_bus = cardbus_scan_bridge,
Eric Biedermandbec2d42004-10-21 10:44:08 +0000206};
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +0000207
Stefan Reinauerf1cf1f72007-10-24 09:08:58 +0000208static const struct pci_driver ricoh_rl5c476_driver __pci_driver = {
Eric Biedermandbec2d42004-10-21 10:44:08 +0000209 .ops = &ricoh_rl5c476_ops,
210 .vendor = PCI_VENDOR_ID_RICOH,
211 .device = PCI_DEVICE_ID_RICOH_RL5C476,
212};
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +0000213
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000214void southbridge_init(device_t dev)
215{
216
217 struct southbridge_ricoh_rl5c476_config *conf = dev->chip_info;
218 enable_cf_boot = conf->enable_cf;
219
220}
221
222struct chip_operations southbridge_ricoh_rl5c476_ops = {
Uwe Hermanna7aa29b2006-11-05 18:50:49 +0000223 CHIP_NAME("Ricoh RL5C476 CardBus Controller")
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000224 .enable_dev = southbridge_init,
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +0000225};