blob: f78f816cfceb96c9e7c9dd6d4a6fb6bf14564f43 [file] [log] [blame]
Patrick Georgiac959032020-05-05 22:49:26 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +00002
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +00003#include <device/device.h>
4#include <device/pci.h>
5#include <device/pci_ops.h>
6#include <device/pci_ids.h>
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +00007#include <console/console.h>
Ronald G. Minnich43225bc2005-11-22 00:07:02 +00008#include <device/cardbus.h>
Stefan Reinaueraecf2512009-07-21 22:01:21 +00009#include <delay.h>
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000010#include "rl5c476.h"
11#include "chip.h"
12
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000013static int enable_cf_boot = 0;
14static unsigned int cf_base;
15
Elyes HAOUAS8349cb52018-05-19 10:52:02 +020016static void rl5c476_init(struct device *dev)
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000017{
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000018 pc16reg_t *pc16;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000019 unsigned char *base;
20
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000021 /* cardbus controller function 1 for CF Socket */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000022 printk(BIOS_DEBUG, "Ricoh RL5c476: Initializing.\n");
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000023
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000024 printk(BIOS_DEBUG, "CF Base = %0x\n",cf_base);
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000025
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000026 /* misc control register */
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000027 pci_write_config16(dev,0x82,0x00a0);
28
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000029 /* set up second slot as compact flash port if asked to do so */
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000030
Stefan Reinauer925b6c02009-07-21 20:27:00 +000031 if (!enable_cf_boot) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000032 printk(BIOS_DEBUG, "CF boot not enabled.\n");
Stefan Reinauer925b6c02009-07-21 20:27:00 +000033 return;
34 }
Stefan Reinauer14e22772010-04-27 06:56:47 +000035
Stefan Reinauer925b6c02009-07-21 20:27:00 +000036 if (PCI_FUNC(dev->path.pci.devfn) != 1) {
37 // Only configure if second CF slot.
38 return;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000039 }
40
Stefan Reinauer925b6c02009-07-21 20:27:00 +000041 /* make sure isa interrupts are enabled */
42 pci_write_config16(dev,0x3e,0x0780);
43
44 /* pick up where 16 bit card control structure is
45 * (0x800 bytes into config structure)
46 */
47 base = (unsigned char *)pci_read_config32(dev,0x10);
48 pc16 = (pc16reg_t *)(base + 0x800);
49
50 /* disable memory and io windows and turn off socket power */
51 pc16->pwctrl = 0;
52
53 /* disable irq lines */
54 pc16->igctrl = 0;
55
56 /* disable memory and I/O windows */
57 pc16->awinen = 0;
58
59 /* reset card, configure for I/O and set IRQ line */
60 pc16->igctrl = 0x69;
61
62 /* set io window 0 for 1e0 - 1ef */
63 /* NOTE: This now sets CF up on a contiguous I/O window of
64 * 16 bytes, 0x1e0 to 0x1ef.
65 * Be warned that this is not a standard IDE address as
66 * automatically detected by the likes of FILO, and would need
Martin Rothb348bb52014-12-09 13:50:58 -070067 * patching to recognize these addresses as an IDE drive.
Stefan Reinauer925b6c02009-07-21 20:27:00 +000068 *
69 * An earlier version of this driver set up 2 I/O windows to
70 * emulate the expected addresses for IDE2, however the PCMCIA
71 * package within Linux then could not re-initialize the
72 * device as it tried to take control of it. So I believe it is
73 * easier to patch Filo or the like to pick up this drive
74 * rather than playing silly games as the kernel tries to
75 * boot.
76 *
77 * Nonetheless, FILO needs a special option enabled to boot
78 * from this configuration, and it needs to clean up
79 * afterwards. Please refer to FILO documentation and source
80 * code for more details.
81 */
82 pc16->iostl0 = 0xe0;
83 pc16->iosth0 = 1;
84
85 pc16->iospl0 = 0xef;
86 pc16->iosph0 = 1;
87
88 pc16->ioffl0 = 0;
89 pc16->ioffh0 = 0;
90
91 /* clear window 1 */
92 pc16->iostl1 = 0;
93 pc16->iosth1 = 0;
94
95 pc16->iospl1 = 0;
96 pc16->iosph1 = 0;
97
98 pc16->ioffl1 = 0x0;
99 pc16->ioffh1 = 0;
100
101 /* set up CF config window */
102 pc16->smpga0 = cf_base>>24;
103 pc16->smsth0 = (cf_base>>20)&0x0f;
104 pc16->smstl0 = (cf_base>>12)&0xff;
105 pc16->smsph0 = ((cf_base>>20)&0x0f) | 0x80;
106 pc16->smspl0 = (cf_base>>12)&0xff;
107 pc16->moffl0 = 0;
108 pc16->moffh0 = 0x40;
109
Stefan Reinauer925b6c02009-07-21 20:27:00 +0000110 /* set I/O width for Auto Data width */
111 pc16->ioctrl = 0x22;
112
Stefan Reinauer925b6c02009-07-21 20:27:00 +0000113 /* enable I/O window 0 and 1 */
114 pc16->awinen = 0xc1;
115
116 pc16->miscc1 = 1;
117
118 /* apply power and enable outputs */
119 pc16->pwctrl = 0xb0;
120
121 // delay could be optimised, but this works
122 udelay(100000);
123
124 pc16->igctrl = 0x69;
125
Stefan Reinauer925b6c02009-07-21 20:27:00 +0000126 /* 16 bit CF always have first config byte at 0x200 into
127 * Config structure, but CF+ may not according to spec -
128 * should locate through reading tuple data, but this should
129 * do for now.
130 */
131 unsigned char *cptr;
132 cptr = (unsigned char *)(cf_base + 0x200);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000133 printk(BIOS_DEBUG, "CF Config = %x\n",*cptr);
Stefan Reinauer925b6c02009-07-21 20:27:00 +0000134
Stefan Reinauer14e22772010-04-27 06:56:47 +0000135 /* Set CF to decode 16 IO bytes on any 16 byte boundary -
136 * rely on the io windows of the bridge set up above to
Stefan Reinauer925b6c02009-07-21 20:27:00 +0000137 * map those bytes into the addresses for IDE controller 3
138 * (0x1e8 - 0x1ef and 0x3ed - 0x3ee)
139 */
140 *cptr = 0x41;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000141}
142
Elyes HAOUAS8349cb52018-05-19 10:52:02 +0200143static void rl5c476_read_resources(struct device *dev)
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000144{
145
146 struct resource *resource;
147
Elyes HAOUAS2220f0d2016-11-23 18:54:34 +0100148 /* For CF socket we need an extra memory window for
149 * the control structure of the CF itself
150 */
Elyes HAOUASa342f392018-10-17 10:56:26 +0200151 if (enable_cf_boot && (PCI_FUNC(dev->path.pci.devfn) == 1)) {
Stefan Reinauer925b6c02009-07-21 20:27:00 +0000152 /* fake index as it isn't in PCI config space */
153 resource = new_resource(dev, 1);
Stefan Reinauerc8863a22009-10-22 17:02:44 +0000154 resource->flags |= IORESOURCE_MEM;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000155 resource->size = 0x1000;
156 resource->align = resource->gran = 12;
157 resource->limit= 0xffff0000;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000158 }
159 cardbus_read_resources(dev);
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000160}
161
Elyes HAOUAS8349cb52018-05-19 10:52:02 +0200162static void rl5c476_set_resources(struct device *dev)
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000163{
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000164 struct resource *resource;
Paul Menzeld0cdcae2014-08-08 15:24:31 +0200165 printk(BIOS_DEBUG, "%s In set resources\n",dev_path(dev));
Elyes HAOUASa342f392018-10-17 10:56:26 +0200166 if (enable_cf_boot && (PCI_FUNC(dev->path.pci.devfn) == 1)) {
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000167 resource = find_resource(dev,1);
Elyes HAOUASa342f392018-10-17 10:56:26 +0200168 if (!(resource->flags & IORESOURCE_STORED)) {
Elyes HAOUAS9344bde2016-10-02 12:30:06 +0200169 resource->flags |= IORESOURCE_STORED;
Myles Watson08e0fb82010-03-22 16:33:25 +0000170 printk(BIOS_DEBUG, "%s 1 ==> %llx\n", dev_path(dev), resource->base);
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000171 cf_base = resource->base;
172 }
173 }
174
175 pci_dev_set_resources(dev);
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +0000176
177}
178
Martin Rothff744bf2019-10-23 21:46:03 -0600179static void rl5c476_set_subsystem(struct device *dev, unsigned int vendor,
180 unsigned int device)
Sven Schnelled175f442011-02-28 18:09:58 +0000181{
Elyes HAOUAS2220f0d2016-11-23 18:54:34 +0100182 u16 miscreg = pci_read_config16(dev, 0x82);
183 /* Enable subsystem id register writes */
184 pci_write_config16(dev, 0x82, miscreg | 0x40);
Sven Schnelled175f442011-02-28 18:09:58 +0000185
Subrata Banik15ccbf02019-03-20 15:09:44 +0530186 pci_dev_set_subsystem(dev, vendor, device);
187
Elyes HAOUAS2220f0d2016-11-23 18:54:34 +0100188 /* restore original contents */
189 pci_write_config16(dev, 0x82, miscreg);
Sven Schnelled175f442011-02-28 18:09:58 +0000190}
191
192static struct pci_operations rl5c476_pci_ops = {
Elyes HAOUAS2220f0d2016-11-23 18:54:34 +0100193 .set_subsystem = rl5c476_set_subsystem,
Sven Schnelled175f442011-02-28 18:09:58 +0000194};
195
Eric Biedermandbec2d42004-10-21 10:44:08 +0000196static struct device_operations ricoh_rl5c476_ops = {
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000197 .read_resources = rl5c476_read_resources,
198 .set_resources = rl5c476_set_resources,
199 .enable_resources = cardbus_enable_resources,
200 .init = rl5c476_init,
Myles Watson84e8e452010-06-07 17:12:57 +0000201 .scan_bus = pci_scan_bridge,
Sven Schnelled175f442011-02-28 18:09:58 +0000202 .ops_pci = &rl5c476_pci_ops,
Eric Biedermandbec2d42004-10-21 10:44:08 +0000203};
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +0000204
Stefan Reinauerf1cf1f72007-10-24 09:08:58 +0000205static const struct pci_driver ricoh_rl5c476_driver __pci_driver = {
Eric Biedermandbec2d42004-10-21 10:44:08 +0000206 .ops = &ricoh_rl5c476_ops,
Felix Singer43b7f412022-03-07 04:34:52 +0100207 .vendor = PCI_VID_RICOH,
208 .device = PCI_DID_RICOH_RL5C476,
Eric Biedermandbec2d42004-10-21 10:44:08 +0000209};
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +0000210
Elyes HAOUAS8349cb52018-05-19 10:52:02 +0200211static void southbridge_init(struct device *dev)
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000212{
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000213 struct southbridge_ricoh_rl5c476_config *conf = dev->chip_info;
214 enable_cf_boot = conf->enable_cf;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000215}
216
217struct chip_operations southbridge_ricoh_rl5c476_ops = {
Nicholas Sudsgaardbfb11be2024-01-30 09:53:46 +0900218 .name = "Ricoh RL5C476 CardBus Controller",
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000219 .enable_dev = southbridge_init,
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +0000220};