blob: 0bcf9c5f93ac0bbb6822fdfbb6128057d50e0fa2 [file] [log] [blame]
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +00001/*
Uwe Hermannc70e9fc2010-02-15 23:10:19 +00002 * This file is part of the coreboot project.
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +00003 *
Uwe Hermannc70e9fc2010-02-15 23:10:19 +00004 * 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.
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000010 *
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.
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000015 */
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000016
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000017#include <device/device.h>
18#include <device/pci.h>
19#include <device/pci_ops.h>
20#include <device/pci_ids.h>
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000021#include <console/console.h>
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000022#include <device/cardbus.h>
Stefan Reinaueraecf2512009-07-21 22:01:21 +000023#include <delay.h>
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000024#include "rl5c476.h"
25#include "chip.h"
26
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000027static int enable_cf_boot = 0;
28static unsigned int cf_base;
29
Elyes HAOUAS8349cb52018-05-19 10:52:02 +020030static void rl5c476_init(struct device *dev)
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000031{
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000032 pc16reg_t *pc16;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000033 unsigned char *base;
34
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000035 /* cardbus controller function 1 for CF Socket */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000036 printk(BIOS_DEBUG, "Ricoh RL5c476: Initializing.\n");
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000037
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000038 printk(BIOS_DEBUG, "CF Base = %0x\n",cf_base);
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000039
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000040 /* misc control register */
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000041 pci_write_config16(dev,0x82,0x00a0);
42
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000043 /* set up second slot as compact flash port if asked to do so */
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000044
Stefan Reinauer925b6c02009-07-21 20:27:00 +000045 if (!enable_cf_boot) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000046 printk(BIOS_DEBUG, "CF boot not enabled.\n");
Stefan Reinauer925b6c02009-07-21 20:27:00 +000047 return;
48 }
Stefan Reinauer14e22772010-04-27 06:56:47 +000049
Stefan Reinauer925b6c02009-07-21 20:27:00 +000050 if (PCI_FUNC(dev->path.pci.devfn) != 1) {
51 // Only configure if second CF slot.
52 return;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000053 }
54
Stefan Reinauer925b6c02009-07-21 20:27:00 +000055 /* make sure isa interrupts are enabled */
56 pci_write_config16(dev,0x3e,0x0780);
57
58 /* pick up where 16 bit card control structure is
59 * (0x800 bytes into config structure)
60 */
61 base = (unsigned char *)pci_read_config32(dev,0x10);
62 pc16 = (pc16reg_t *)(base + 0x800);
63
64 /* disable memory and io windows and turn off socket power */
65 pc16->pwctrl = 0;
66
67 /* disable irq lines */
68 pc16->igctrl = 0;
69
70 /* disable memory and I/O windows */
71 pc16->awinen = 0;
72
73 /* reset card, configure for I/O and set IRQ line */
74 pc16->igctrl = 0x69;
75
76 /* set io window 0 for 1e0 - 1ef */
77 /* NOTE: This now sets CF up on a contiguous I/O window of
78 * 16 bytes, 0x1e0 to 0x1ef.
79 * Be warned that this is not a standard IDE address as
80 * automatically detected by the likes of FILO, and would need
Martin Rothb348bb52014-12-09 13:50:58 -070081 * patching to recognize these addresses as an IDE drive.
Stefan Reinauer925b6c02009-07-21 20:27:00 +000082 *
83 * An earlier version of this driver set up 2 I/O windows to
84 * emulate the expected addresses for IDE2, however the PCMCIA
85 * package within Linux then could not re-initialize the
86 * device as it tried to take control of it. So I believe it is
87 * easier to patch Filo or the like to pick up this drive
88 * rather than playing silly games as the kernel tries to
89 * boot.
90 *
91 * Nonetheless, FILO needs a special option enabled to boot
92 * from this configuration, and it needs to clean up
93 * afterwards. Please refer to FILO documentation and source
94 * code for more details.
95 */
96 pc16->iostl0 = 0xe0;
97 pc16->iosth0 = 1;
98
99 pc16->iospl0 = 0xef;
100 pc16->iosph0 = 1;
101
102 pc16->ioffl0 = 0;
103 pc16->ioffh0 = 0;
104
105 /* clear window 1 */
106 pc16->iostl1 = 0;
107 pc16->iosth1 = 0;
108
109 pc16->iospl1 = 0;
110 pc16->iosph1 = 0;
111
112 pc16->ioffl1 = 0x0;
113 pc16->ioffh1 = 0;
114
115 /* set up CF config window */
116 pc16->smpga0 = cf_base>>24;
117 pc16->smsth0 = (cf_base>>20)&0x0f;
118 pc16->smstl0 = (cf_base>>12)&0xff;
119 pc16->smsph0 = ((cf_base>>20)&0x0f) | 0x80;
120 pc16->smspl0 = (cf_base>>12)&0xff;
121 pc16->moffl0 = 0;
122 pc16->moffh0 = 0x40;
123
124
125 /* set I/O width for Auto Data width */
126 pc16->ioctrl = 0x22;
127
128
129 /* enable I/O window 0 and 1 */
130 pc16->awinen = 0xc1;
131
132 pc16->miscc1 = 1;
133
134 /* apply power and enable outputs */
135 pc16->pwctrl = 0xb0;
136
137 // delay could be optimised, but this works
138 udelay(100000);
139
140 pc16->igctrl = 0x69;
141
142
143 /* 16 bit CF always have first config byte at 0x200 into
144 * Config structure, but CF+ may not according to spec -
145 * should locate through reading tuple data, but this should
146 * do for now.
147 */
148 unsigned char *cptr;
149 cptr = (unsigned char *)(cf_base + 0x200);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000150 printk(BIOS_DEBUG, "CF Config = %x\n",*cptr);
Stefan Reinauer925b6c02009-07-21 20:27:00 +0000151
Stefan Reinauer14e22772010-04-27 06:56:47 +0000152 /* Set CF to decode 16 IO bytes on any 16 byte boundary -
153 * rely on the io windows of the bridge set up above to
Stefan Reinauer925b6c02009-07-21 20:27:00 +0000154 * map those bytes into the addresses for IDE controller 3
155 * (0x1e8 - 0x1ef and 0x3ed - 0x3ee)
156 */
157 *cptr = 0x41;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000158}
159
Elyes HAOUAS8349cb52018-05-19 10:52:02 +0200160static void rl5c476_read_resources(struct device *dev)
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000161{
162
163 struct resource *resource;
164
Elyes HAOUAS2220f0d2016-11-23 18:54:34 +0100165 /* For CF socket we need an extra memory window for
166 * the control structure of the CF itself
167 */
Elyes HAOUASa342f392018-10-17 10:56:26 +0200168 if (enable_cf_boot && (PCI_FUNC(dev->path.pci.devfn) == 1)) {
Stefan Reinauer925b6c02009-07-21 20:27:00 +0000169 /* fake index as it isn't in PCI config space */
170 resource = new_resource(dev, 1);
Stefan Reinauerc8863a22009-10-22 17:02:44 +0000171 resource->flags |= IORESOURCE_MEM;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000172 resource->size = 0x1000;
173 resource->align = resource->gran = 12;
174 resource->limit= 0xffff0000;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000175 }
176 cardbus_read_resources(dev);
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000177}
178
Elyes HAOUAS8349cb52018-05-19 10:52:02 +0200179static void rl5c476_set_resources(struct device *dev)
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000180{
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000181 struct resource *resource;
Paul Menzeld0cdcae2014-08-08 15:24:31 +0200182 printk(BIOS_DEBUG, "%s In set resources\n",dev_path(dev));
Elyes HAOUASa342f392018-10-17 10:56:26 +0200183 if (enable_cf_boot && (PCI_FUNC(dev->path.pci.devfn) == 1)) {
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000184 resource = find_resource(dev,1);
Elyes HAOUASa342f392018-10-17 10:56:26 +0200185 if (!(resource->flags & IORESOURCE_STORED)) {
Elyes HAOUAS9344bde2016-10-02 12:30:06 +0200186 resource->flags |= IORESOURCE_STORED;
Myles Watson08e0fb82010-03-22 16:33:25 +0000187 printk(BIOS_DEBUG, "%s 1 ==> %llx\n", dev_path(dev), resource->base);
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000188 cf_base = resource->base;
189 }
190 }
191
192 pci_dev_set_resources(dev);
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +0000193
194}
195
Martin Rothff744bf2019-10-23 21:46:03 -0600196static void rl5c476_set_subsystem(struct device *dev, unsigned int vendor,
197 unsigned int device)
Sven Schnelled175f442011-02-28 18:09:58 +0000198{
Elyes HAOUAS2220f0d2016-11-23 18:54:34 +0100199 u16 miscreg = pci_read_config16(dev, 0x82);
200 /* Enable subsystem id register writes */
201 pci_write_config16(dev, 0x82, miscreg | 0x40);
Sven Schnelled175f442011-02-28 18:09:58 +0000202
Subrata Banik15ccbf02019-03-20 15:09:44 +0530203 pci_dev_set_subsystem(dev, vendor, device);
204
Elyes HAOUAS2220f0d2016-11-23 18:54:34 +0100205 /* restore original contents */
206 pci_write_config16(dev, 0x82, miscreg);
Sven Schnelled175f442011-02-28 18:09:58 +0000207}
208
209static struct pci_operations rl5c476_pci_ops = {
Elyes HAOUAS2220f0d2016-11-23 18:54:34 +0100210 .set_subsystem = rl5c476_set_subsystem,
Sven Schnelled175f442011-02-28 18:09:58 +0000211};
212
Eric Biedermandbec2d42004-10-21 10:44:08 +0000213static struct device_operations ricoh_rl5c476_ops = {
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000214 .read_resources = rl5c476_read_resources,
215 .set_resources = rl5c476_set_resources,
216 .enable_resources = cardbus_enable_resources,
217 .init = rl5c476_init,
Myles Watson84e8e452010-06-07 17:12:57 +0000218 .scan_bus = pci_scan_bridge,
Sven Schnelled175f442011-02-28 18:09:58 +0000219 .ops_pci = &rl5c476_pci_ops,
Eric Biedermandbec2d42004-10-21 10:44:08 +0000220};
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +0000221
Stefan Reinauerf1cf1f72007-10-24 09:08:58 +0000222static const struct pci_driver ricoh_rl5c476_driver __pci_driver = {
Eric Biedermandbec2d42004-10-21 10:44:08 +0000223 .ops = &ricoh_rl5c476_ops,
224 .vendor = PCI_VENDOR_ID_RICOH,
225 .device = PCI_DEVICE_ID_RICOH_RL5C476,
226};
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +0000227
Elyes HAOUAS8349cb52018-05-19 10:52:02 +0200228static void southbridge_init(struct device *dev)
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000229{
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000230 struct southbridge_ricoh_rl5c476_config *conf = dev->chip_info;
231 enable_cf_boot = conf->enable_cf;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000232}
233
234struct chip_operations southbridge_ricoh_rl5c476_ops = {
Uwe Hermanna7aa29b2006-11-05 18:50:49 +0000235 CHIP_NAME("Ricoh RL5C476 CardBus Controller")
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000236 .enable_dev = southbridge_init,
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +0000237};