Ronald G. Minnich | 02fa3b2 | 2004-10-06 17:33:54 +0000 | [diff] [blame] | 1 | /* |
Uwe Hermann | c70e9fc | 2010-02-15 23:10:19 +0000 | [diff] [blame^] | 2 | * This file is part of the coreboot project. |
Ronald G. Minnich | 02fa3b2 | 2004-10-06 17:33:54 +0000 | [diff] [blame] | 3 | * |
Uwe Hermann | c70e9fc | 2010-02-15 23:10:19 +0000 | [diff] [blame^] | 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. |
Ronald G. Minnich | 02fa3b2 | 2004-10-06 17:33:54 +0000 | [diff] [blame] | 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 |
Uwe Hermann | c70e9fc | 2010-02-15 23:10:19 +0000 | [diff] [blame^] | 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
Ronald G. Minnich | 02fa3b2 | 2004-10-06 17:33:54 +0000 | [diff] [blame] | 19 | */ |
Ronald G. Minnich | 02fa3b2 | 2004-10-06 17:33:54 +0000 | [diff] [blame] | 20 | |
Ronald G. Minnich | 02fa3b2 | 2004-10-06 17:33:54 +0000 | [diff] [blame] | 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> |
Ronald G. Minnich | 02fa3b2 | 2004-10-06 17:33:54 +0000 | [diff] [blame] | 26 | #include <console/console.h> |
Ronald G. Minnich | 43225bc | 2005-11-22 00:07:02 +0000 | [diff] [blame] | 27 | #include <device/cardbus.h> |
Stefan Reinauer | aecf251 | 2009-07-21 22:01:21 +0000 | [diff] [blame] | 28 | #include <delay.h> |
Ronald G. Minnich | 02fa3b2 | 2004-10-06 17:33:54 +0000 | [diff] [blame] | 29 | #include "rl5c476.h" |
| 30 | #include "chip.h" |
| 31 | |
Ronald G. Minnich | 43225bc | 2005-11-22 00:07:02 +0000 | [diff] [blame] | 32 | static int enable_cf_boot = 0; |
| 33 | static unsigned int cf_base; |
| 34 | |
Eric Biederman | dbec2d4 | 2004-10-21 10:44:08 +0000 | [diff] [blame] | 35 | static void rl5c476_init(device_t dev) |
Ronald G. Minnich | 02fa3b2 | 2004-10-06 17:33:54 +0000 | [diff] [blame] | 36 | { |
Ronald G. Minnich | 02fa3b2 | 2004-10-06 17:33:54 +0000 | [diff] [blame] | 37 | pc16reg_t *pc16; |
Ronald G. Minnich | 43225bc | 2005-11-22 00:07:02 +0000 | [diff] [blame] | 38 | unsigned char *base; |
| 39 | |
Ronald G. Minnich | 02fa3b2 | 2004-10-06 17:33:54 +0000 | [diff] [blame] | 40 | /* cardbus controller function 1 for CF Socket */ |
Stefan Reinauer | 925b6c0 | 2009-07-21 20:27:00 +0000 | [diff] [blame] | 41 | printk_debug("Ricoh RL5c476: Initializing.\n"); |
Ronald G. Minnich | 02fa3b2 | 2004-10-06 17:33:54 +0000 | [diff] [blame] | 42 | |
Ronald G. Minnich | 43225bc | 2005-11-22 00:07:02 +0000 | [diff] [blame] | 43 | printk_debug("CF Base = %0x\n",cf_base); |
Ronald G. Minnich | 02fa3b2 | 2004-10-06 17:33:54 +0000 | [diff] [blame] | 44 | |
Ronald G. Minnich | 43225bc | 2005-11-22 00:07:02 +0000 | [diff] [blame] | 45 | /* misc control register */ |
Ronald G. Minnich | 02fa3b2 | 2004-10-06 17:33:54 +0000 | [diff] [blame] | 46 | pci_write_config16(dev,0x82,0x00a0); |
| 47 | |
Ronald G. Minnich | 43225bc | 2005-11-22 00:07:02 +0000 | [diff] [blame] | 48 | /* set up second slot as compact flash port if asked to do so */ |
Ronald G. Minnich | 43225bc | 2005-11-22 00:07:02 +0000 | [diff] [blame] | 49 | |
Stefan Reinauer | 925b6c0 | 2009-07-21 20:27:00 +0000 | [diff] [blame] | 50 | if (!enable_cf_boot) { |
| 51 | printk_debug("CF boot not enabled.\n"); |
| 52 | return; |
| 53 | } |
Ronald G. Minnich | 02fa3b2 | 2004-10-06 17:33:54 +0000 | [diff] [blame] | 54 | |
Stefan Reinauer | 925b6c0 | 2009-07-21 20:27:00 +0000 | [diff] [blame] | 55 | if (PCI_FUNC(dev->path.pci.devfn) != 1) { |
| 56 | // Only configure if second CF slot. |
| 57 | return; |
Ronald G. Minnich | 43225bc | 2005-11-22 00:07:02 +0000 | [diff] [blame] | 58 | } |
| 59 | |
Stefan Reinauer | 925b6c0 | 2009-07-21 20:27:00 +0000 | [diff] [blame] | 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; |
Ronald G. Minnich | 43225bc | 2005-11-22 00:07:02 +0000 | [diff] [blame] | 163 | } |
| 164 | |
| 165 | void rl5c476_read_resources(device_t dev) |
| 166 | { |
| 167 | |
| 168 | struct resource *resource; |
| 169 | |
Stefan Reinauer | 925b6c0 | 2009-07-21 20:27:00 +0000 | [diff] [blame] | 170 | /* For CF socket we need an extra memory window for |
| 171 | * the control structure of the CF itself |
| 172 | */ |
Stefan Reinauer | 2b34db8 | 2009-02-28 20:10:20 +0000 | [diff] [blame] | 173 | if( enable_cf_boot && (PCI_FUNC(dev->path.pci.devfn) == 1)){ |
Stefan Reinauer | 925b6c0 | 2009-07-21 20:27:00 +0000 | [diff] [blame] | 174 | /* fake index as it isn't in PCI config space */ |
| 175 | resource = new_resource(dev, 1); |
Stefan Reinauer | c8863a2 | 2009-10-22 17:02:44 +0000 | [diff] [blame] | 176 | resource->flags |= IORESOURCE_MEM; |
Ronald G. Minnich | 43225bc | 2005-11-22 00:07:02 +0000 | [diff] [blame] | 177 | resource->size = 0x1000; |
| 178 | resource->align = resource->gran = 12; |
| 179 | resource->limit= 0xffff0000; |
Ronald G. Minnich | 43225bc | 2005-11-22 00:07:02 +0000 | [diff] [blame] | 180 | } |
| 181 | cardbus_read_resources(dev); |
Ronald G. Minnich | 43225bc | 2005-11-22 00:07:02 +0000 | [diff] [blame] | 182 | } |
| 183 | |
| 184 | void rl5c476_set_resources(device_t dev) |
| 185 | { |
Ronald G. Minnich | 43225bc | 2005-11-22 00:07:02 +0000 | [diff] [blame] | 186 | struct resource *resource; |
| 187 | printk_debug("%s In set resources \n",dev_path(dev)); |
Stefan Reinauer | 2b34db8 | 2009-02-28 20:10:20 +0000 | [diff] [blame] | 188 | if( enable_cf_boot && (PCI_FUNC(dev->path.pci.devfn) == 1)){ |
Ronald G. Minnich | 43225bc | 2005-11-22 00:07:02 +0000 | [diff] [blame] | 189 | resource = find_resource(dev,1); |
| 190 | if( !(resource->flags & IORESOURCE_STORED) ){ |
| 191 | resource->flags |= IORESOURCE_STORED ; |
Stefan Reinauer | c8863a2 | 2009-10-22 17:02:44 +0000 | [diff] [blame] | 192 | printk_debug("%s 1 ==> %x\n", dev_path(dev), resource->base); |
Ronald G. Minnich | 43225bc | 2005-11-22 00:07:02 +0000 | [diff] [blame] | 193 | cf_base = resource->base; |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | pci_dev_set_resources(dev); |
Ronald G. Minnich | 02fa3b2 | 2004-10-06 17:33:54 +0000 | [diff] [blame] | 198 | |
| 199 | } |
| 200 | |
Eric Biederman | dbec2d4 | 2004-10-21 10:44:08 +0000 | [diff] [blame] | 201 | static struct device_operations ricoh_rl5c476_ops = { |
Ronald G. Minnich | 43225bc | 2005-11-22 00:07:02 +0000 | [diff] [blame] | 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, |
Eric Biederman | dbec2d4 | 2004-10-21 10:44:08 +0000 | [diff] [blame] | 207 | }; |
Ronald G. Minnich | 02fa3b2 | 2004-10-06 17:33:54 +0000 | [diff] [blame] | 208 | |
Stefan Reinauer | f1cf1f7 | 2007-10-24 09:08:58 +0000 | [diff] [blame] | 209 | static const struct pci_driver ricoh_rl5c476_driver __pci_driver = { |
Eric Biederman | dbec2d4 | 2004-10-21 10:44:08 +0000 | [diff] [blame] | 210 | .ops = &ricoh_rl5c476_ops, |
| 211 | .vendor = PCI_VENDOR_ID_RICOH, |
| 212 | .device = PCI_DEVICE_ID_RICOH_RL5C476, |
| 213 | }; |
Ronald G. Minnich | 02fa3b2 | 2004-10-06 17:33:54 +0000 | [diff] [blame] | 214 | |
Ronald G. Minnich | 43225bc | 2005-11-22 00:07:02 +0000 | [diff] [blame] | 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 = { |
Uwe Hermann | a7aa29b | 2006-11-05 18:50:49 +0000 | [diff] [blame] | 224 | CHIP_NAME("Ricoh RL5C476 CardBus Controller") |
Ronald G. Minnich | 43225bc | 2005-11-22 00:07:02 +0000 | [diff] [blame] | 225 | .enable_dev = southbridge_init, |
Ronald G. Minnich | 02fa3b2 | 2004-10-06 17:33:54 +0000 | [diff] [blame] | 226 | }; |