blob: bdbcba70533a4489da208ca3c2357b44d92b05c8 [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 <arch/io.h>
18#include <device/device.h>
19#include <device/pci.h>
20#include <device/pci_ops.h>
21#include <device/pci_ids.h>
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000022#include <console/console.h>
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000023#include <device/cardbus.h>
Stefan Reinaueraecf2512009-07-21 22:01:21 +000024#include <delay.h>
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000025#include "rl5c476.h"
26#include "chip.h"
27
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000028static int enable_cf_boot = 0;
29static unsigned int cf_base;
30
Elyes HAOUAS8349cb52018-05-19 10:52:02 +020031static void rl5c476_init(struct device *dev)
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000032{
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000033 pc16reg_t *pc16;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000034 unsigned char *base;
35
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000036 /* cardbus controller function 1 for CF Socket */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000037 printk(BIOS_DEBUG, "Ricoh RL5c476: Initializing.\n");
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000038
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000039 printk(BIOS_DEBUG, "CF Base = %0x\n",cf_base);
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000040
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000041 /* misc control register */
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +000042 pci_write_config16(dev,0x82,0x00a0);
43
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000044 /* set up second slot as compact flash port if asked to do so */
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000045
Stefan Reinauer925b6c02009-07-21 20:27:00 +000046 if (!enable_cf_boot) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000047 printk(BIOS_DEBUG, "CF boot not enabled.\n");
Stefan Reinauer925b6c02009-07-21 20:27:00 +000048 return;
49 }
Stefan Reinauer14e22772010-04-27 06:56:47 +000050
Stefan Reinauer925b6c02009-07-21 20:27:00 +000051 if (PCI_FUNC(dev->path.pci.devfn) != 1) {
52 // Only configure if second CF slot.
53 return;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +000054 }
55
Stefan Reinauer925b6c02009-07-21 20:27:00 +000056 /* make sure isa interrupts are enabled */
57 pci_write_config16(dev,0x3e,0x0780);
58
59 /* pick up where 16 bit card control structure is
60 * (0x800 bytes into config structure)
61 */
62 base = (unsigned char *)pci_read_config32(dev,0x10);
63 pc16 = (pc16reg_t *)(base + 0x800);
64
65 /* disable memory and io windows and turn off socket power */
66 pc16->pwctrl = 0;
67
68 /* disable irq lines */
69 pc16->igctrl = 0;
70
71 /* disable memory and I/O windows */
72 pc16->awinen = 0;
73
74 /* reset card, configure for I/O and set IRQ line */
75 pc16->igctrl = 0x69;
76
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
Martin Rothb348bb52014-12-09 13:50:58 -070082 * patching to recognize these addresses as an IDE drive.
Stefan Reinauer925b6c02009-07-21 20:27:00 +000083 *
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
90 * boot.
91 *
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.
96 */
97 pc16->iostl0 = 0xe0;
98 pc16->iosth0 = 1;
99
100 pc16->iospl0 = 0xef;
101 pc16->iosph0 = 1;
102
103 pc16->ioffl0 = 0;
104 pc16->ioffh0 = 0;
105
106 /* clear window 1 */
107 pc16->iostl1 = 0;
108 pc16->iosth1 = 0;
109
110 pc16->iospl1 = 0;
111 pc16->iosph1 = 0;
112
113 pc16->ioffl1 = 0x0;
114 pc16->ioffh1 = 0;
115
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;
122 pc16->moffl0 = 0;
123 pc16->moffh0 = 0x40;
124
125
126 /* set I/O width for Auto Data width */
127 pc16->ioctrl = 0x22;
128
129
130 /* enable I/O window 0 and 1 */
131 pc16->awinen = 0xc1;
132
133 pc16->miscc1 = 1;
134
135 /* apply power and enable outputs */
136 pc16->pwctrl = 0xb0;
137
138 // delay could be optimised, but this works
139 udelay(100000);
140
141 pc16->igctrl = 0x69;
142
143
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
147 * do for now.
148 */
149 unsigned char *cptr;
150 cptr = (unsigned char *)(cf_base + 0x200);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000151 printk(BIOS_DEBUG, "CF Config = %x\n",*cptr);
Stefan Reinauer925b6c02009-07-21 20:27:00 +0000152
Stefan Reinauer14e22772010-04-27 06:56:47 +0000153 /* 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
Stefan Reinauer925b6c02009-07-21 20:27:00 +0000155 * map those bytes into the addresses for IDE controller 3
156 * (0x1e8 - 0x1ef and 0x3ed - 0x3ee)
157 */
158 *cptr = 0x41;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000159}
160
Elyes HAOUAS8349cb52018-05-19 10:52:02 +0200161static void rl5c476_read_resources(struct device *dev)
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000162{
163
164 struct resource *resource;
165
Elyes HAOUAS2220f0d2016-11-23 18:54:34 +0100166 /* For CF socket we need an extra memory window for
167 * the control structure of the CF itself
168 */
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200169 if ( enable_cf_boot && (PCI_FUNC(dev->path.pci.devfn) == 1)){
Stefan Reinauer925b6c02009-07-21 20:27:00 +0000170 /* fake index as it isn't in PCI config space */
171 resource = new_resource(dev, 1);
Stefan Reinauerc8863a22009-10-22 17:02:44 +0000172 resource->flags |= IORESOURCE_MEM;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000173 resource->size = 0x1000;
174 resource->align = resource->gran = 12;
175 resource->limit= 0xffff0000;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000176 }
177 cardbus_read_resources(dev);
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000178}
179
Elyes HAOUAS8349cb52018-05-19 10:52:02 +0200180static void rl5c476_set_resources(struct device *dev)
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000181{
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000182 struct resource *resource;
Paul Menzeld0cdcae2014-08-08 15:24:31 +0200183 printk(BIOS_DEBUG, "%s In set resources\n",dev_path(dev));
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200184 if ( enable_cf_boot && (PCI_FUNC(dev->path.pci.devfn) == 1)){
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000185 resource = find_resource(dev,1);
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200186 if ( !(resource->flags & IORESOURCE_STORED) ){
Elyes HAOUAS9344bde2016-10-02 12:30:06 +0200187 resource->flags |= IORESOURCE_STORED;
Myles Watson08e0fb82010-03-22 16:33:25 +0000188 printk(BIOS_DEBUG, "%s 1 ==> %llx\n", dev_path(dev), resource->base);
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000189 cf_base = resource->base;
190 }
191 }
192
193 pci_dev_set_resources(dev);
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +0000194
195}
196
Elyes HAOUAS8349cb52018-05-19 10:52:02 +0200197static void rl5c476_set_subsystem(struct device *dev, unsigned vendor,
198 unsigned device)
Sven Schnelled175f442011-02-28 18:09:58 +0000199{
Elyes HAOUAS2220f0d2016-11-23 18:54:34 +0100200 u16 miscreg = pci_read_config16(dev, 0x82);
201 /* Enable subsystem id register writes */
202 pci_write_config16(dev, 0x82, miscreg | 0x40);
Sven Schnelled175f442011-02-28 18:09:58 +0000203
Elyes HAOUAS2220f0d2016-11-23 18:54:34 +0100204 pci_write_config16(dev, 0x40, vendor);
205 pci_write_config16(dev, 0x42, device);
206 /* restore original contents */
207 pci_write_config16(dev, 0x82, miscreg);
Sven Schnelled175f442011-02-28 18:09:58 +0000208}
209
210static struct pci_operations rl5c476_pci_ops = {
Elyes HAOUAS2220f0d2016-11-23 18:54:34 +0100211 .set_subsystem = rl5c476_set_subsystem,
Sven Schnelled175f442011-02-28 18:09:58 +0000212};
213
Eric Biedermandbec2d42004-10-21 10:44:08 +0000214static struct device_operations ricoh_rl5c476_ops = {
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000215 .read_resources = rl5c476_read_resources,
216 .set_resources = rl5c476_set_resources,
217 .enable_resources = cardbus_enable_resources,
218 .init = rl5c476_init,
Myles Watson84e8e452010-06-07 17:12:57 +0000219 .scan_bus = pci_scan_bridge,
Sven Schnelled175f442011-02-28 18:09:58 +0000220 .ops_pci = &rl5c476_pci_ops,
Eric Biedermandbec2d42004-10-21 10:44:08 +0000221};
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +0000222
Stefan Reinauerf1cf1f72007-10-24 09:08:58 +0000223static const struct pci_driver ricoh_rl5c476_driver __pci_driver = {
Eric Biedermandbec2d42004-10-21 10:44:08 +0000224 .ops = &ricoh_rl5c476_ops,
225 .vendor = PCI_VENDOR_ID_RICOH,
226 .device = PCI_DEVICE_ID_RICOH_RL5C476,
227};
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +0000228
Elyes HAOUAS8349cb52018-05-19 10:52:02 +0200229static void southbridge_init(struct device *dev)
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000230{
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000231 struct southbridge_ricoh_rl5c476_config *conf = dev->chip_info;
232 enable_cf_boot = conf->enable_cf;
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000233}
234
235struct chip_operations southbridge_ricoh_rl5c476_ops = {
Uwe Hermanna7aa29b2006-11-05 18:50:49 +0000236 CHIP_NAME("Ricoh RL5C476 CardBus Controller")
Ronald G. Minnich43225bc2005-11-22 00:07:02 +0000237 .enable_dev = southbridge_init,
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +0000238};