Eric Biederman | 4086d16 | 2003-07-17 03:26:03 +0000 | [diff] [blame] | 1 | /* |
Eric Biederman | dbec2d4 | 2004-10-21 10:44:08 +0000 | [diff] [blame] | 2 | * (C) 2003-2004 Linux Networx |
Eric Biederman | 4086d16 | 2003-07-17 03:26:03 +0000 | [diff] [blame] | 3 | */ |
| 4 | #include <console/console.h> |
| 5 | #include <device/device.h> |
| 6 | #include <device/pci.h> |
| 7 | #include <device/pci_ids.h> |
| 8 | #include <device/pci_ops.h> |
Eric Biederman | 5cd8173 | 2004-03-11 15:01:31 +0000 | [diff] [blame] | 9 | #include <pc80/mc146818rtc.h> |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 10 | #include <device/pci_def.h> |
| 11 | #include <device/pcix.h> |
Eric Biederman | 5cd8173 | 2004-03-11 15:01:31 +0000 | [diff] [blame] | 12 | |
| 13 | #define NMI_OFF 0 |
Eric Biederman | 4086d16 | 2003-07-17 03:26:03 +0000 | [diff] [blame] | 14 | |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 15 | #define NPUML 0xD9 /* Non prefetchable upper memory limit */ |
| 16 | #define NPUMB 0xD8 /* Non prefetchable upper memory base */ |
| 17 | |
| 18 | static void amd8131_walk_children(struct bus *bus, |
| 19 | void (*visit)(device_t dev, void *ptr), void *ptr) |
| 20 | { |
| 21 | device_t child; |
| 22 | for(child = bus->children; child; child = child->sibling) |
| 23 | { |
| 24 | if (child->path.type != DEVICE_PATH_PCI) { |
| 25 | continue; |
| 26 | } |
| 27 | if (child->hdr_type == PCI_HEADER_TYPE_BRIDGE) { |
Myles Watson | 894a347 | 2010-06-09 22:41:35 +0000 | [diff] [blame] | 28 | amd8131_walk_children(child->link_list, visit, ptr); |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 29 | } |
| 30 | visit(child, ptr); |
| 31 | } |
| 32 | } |
| 33 | |
| 34 | struct amd8131_bus_info { |
| 35 | unsigned sstatus; |
| 36 | unsigned rev; |
| 37 | int errata_56; |
| 38 | int master_devices; |
| 39 | int max_func; |
| 40 | }; |
| 41 | |
| 42 | static void amd8131_count_dev(device_t dev, void *ptr) |
| 43 | { |
| 44 | struct amd8131_bus_info *info = ptr; |
| 45 | /* Don't count pci bridges */ |
| 46 | if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { |
| 47 | info->master_devices++; |
| 48 | } |
Stefan Reinauer | 2b34db8 | 2009-02-28 20:10:20 +0000 | [diff] [blame] | 49 | if (PCI_FUNC(dev->path.pci.devfn) > info->max_func) { |
| 50 | info->max_func = PCI_FUNC(dev->path.pci.devfn); |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 51 | } |
| 52 | } |
| 53 | |
| 54 | |
| 55 | static void amd8131_pcix_tune_dev(device_t dev, void *ptr) |
| 56 | { |
| 57 | struct amd8131_bus_info *info = ptr; |
| 58 | unsigned cap; |
| 59 | unsigned status, cmd, orig_cmd; |
| 60 | unsigned max_read, max_tran; |
| 61 | int sib_funcs, sibs; |
| 62 | device_t sib; |
| 63 | |
| 64 | if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL) { |
| 65 | return; |
| 66 | } |
| 67 | cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); |
| 68 | if (!cap) { |
| 69 | return; |
| 70 | } |
| 71 | /* How many siblings does this device have? */ |
| 72 | sibs = info->master_devices - 1; |
| 73 | /* Count how many sibling functions this device has */ |
| 74 | sib_funcs = 0; |
| 75 | for(sib = dev->bus->children; sib; sib = sib->sibling) { |
| 76 | if (sib == dev) { |
| 77 | continue; |
| 78 | } |
Stefan Reinauer | 2b34db8 | 2009-02-28 20:10:20 +0000 | [diff] [blame] | 79 | if (PCI_SLOT(sib->path.pci.devfn) != PCI_SLOT(dev->path.pci.devfn)) { |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 80 | continue; |
| 81 | } |
| 82 | sib_funcs++; |
| 83 | } |
| 84 | |
| 85 | |
Stefan Reinauer | c02b4fc | 2010-03-22 11:42:32 +0000 | [diff] [blame] | 86 | printk(BIOS_DEBUG, "%s AMD8131 PCI-X tuning\n", dev_path(dev)); |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 87 | status = pci_read_config32(dev, cap + PCI_X_STATUS); |
| 88 | orig_cmd = cmd = pci_read_config16(dev,cap + PCI_X_CMD); |
| 89 | |
| 90 | max_read = (status & PCI_X_STATUS_MAX_READ) >> 21; |
| 91 | max_tran = (status & PCI_X_STATUS_MAX_SPLIT) >> 23; |
| 92 | |
| 93 | /* Errata #49 don't allow 4K transactions */ |
| 94 | if (max_read >= 2) { |
| 95 | max_read = 2; |
| 96 | } |
| 97 | |
| 98 | /* Errata #37 Limit the number of split transactions to avoid starvation */ |
| 99 | if (sibs >= 2) { |
| 100 | /* At most 2 outstanding split transactions when we have |
| 101 | * 3 or more bus master devices on the bus. |
| 102 | */ |
| 103 | if (max_tran > 1) { |
| 104 | max_tran = 1; |
| 105 | } |
| 106 | } |
| 107 | else if (sibs == 1) { |
| 108 | /* At most 4 outstanding split transactions when we have |
| 109 | * 2 bus master devices on the bus. |
| 110 | */ |
| 111 | if (max_tran > 3) { |
| 112 | max_tran = 3; |
| 113 | } |
| 114 | } |
| 115 | else { |
| 116 | /* At most 8 outstanding split transactions when we have |
| 117 | * only one bus master device on the bus. |
| 118 | */ |
| 119 | if (max_tran > 4) { |
| 120 | max_tran = 4; |
| 121 | } |
| 122 | } |
| 123 | /* Errata #56 additional limits when the bus runs at 133Mhz */ |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 124 | if (info->errata_56 && |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 125 | (PCI_X_SSTATUS_MFREQ(info->sstatus) == PCI_X_SSTATUS_MODE1_133MHZ)) |
| 126 | { |
| 127 | unsigned limit_read; |
| 128 | /* Look at the number of siblings and compute the |
| 129 | * largest legal read size. |
| 130 | */ |
| 131 | if (sib_funcs == 0) { |
| 132 | /* 2k reads */ |
| 133 | limit_read = 2; |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 134 | } |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 135 | else if (sib_funcs <= 1) { |
| 136 | /* 1k reads */ |
| 137 | limit_read = 1; |
| 138 | } |
| 139 | else { |
| 140 | /* 512 byte reads */ |
| 141 | limit_read = 0; |
| 142 | } |
| 143 | if (max_read > limit_read) { |
| 144 | max_read = limit_read; |
| 145 | } |
Martin Roth | 55e31a9 | 2014-12-16 20:53:49 -0700 | [diff] [blame] | 146 | /* Look at the read size and the number of siblings |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 147 | * and compute how many outstanding transactions I can have. |
| 148 | */ |
| 149 | if (max_read == 2) { |
| 150 | /* 2K reads */ |
| 151 | if (max_tran > 0) { |
| 152 | /* Only 1 outstanding transaction allowed */ |
| 153 | max_tran = 0; |
| 154 | } |
| 155 | } |
| 156 | else if (max_read == 1) { |
| 157 | /* 1K reads */ |
| 158 | if (max_tran > (1 - sib_funcs)) { |
| 159 | /* At most 2 outstanding transactions */ |
| 160 | max_tran = 1 - sib_funcs; |
| 161 | } |
| 162 | } |
| 163 | else { |
| 164 | /* 512 byte reads */ |
| 165 | max_read = 0; |
| 166 | if (max_tran > (2 - sib_funcs)) { |
| 167 | /* At most 3 outstanding transactions */ |
| 168 | max_tran = 2 - sib_funcs; |
| 169 | } |
| 170 | } |
| 171 | } |
| 172 | #if 0 |
Stefan Reinauer | c02b4fc | 2010-03-22 11:42:32 +0000 | [diff] [blame] | 173 | printk(BIOS_DEBUG, "%s max_read: %d max_tran: %d sibs: %d sib_funcs: %d\n", |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 174 | dev_path(dev), max_read, max_tran, sibs, sib_funcs, sib_funcs); |
| 175 | #endif |
| 176 | if (max_read != ((cmd & PCI_X_CMD_MAX_READ) >> 2)) { |
| 177 | cmd &= ~PCI_X_CMD_MAX_READ; |
| 178 | cmd |= max_read << 2; |
| 179 | } |
| 180 | if (max_tran != ((cmd & PCI_X_CMD_MAX_SPLIT) >> 4)) { |
| 181 | cmd &= ~PCI_X_CMD_MAX_SPLIT; |
| 182 | cmd |= max_tran << 4; |
| 183 | } |
| 184 | |
| 185 | /* Don't attempt to handle PCI-X errors */ |
| 186 | cmd &= ~PCI_X_CMD_DPERR_E; |
| 187 | /* The 8131 does not work properly with relax ordering enabled. |
| 188 | * Errata #58 |
| 189 | */ |
| 190 | cmd &= ~PCI_X_CMD_ERO; |
| 191 | if (orig_cmd != cmd) { |
| 192 | pci_write_config16(dev, cap + PCI_X_CMD, cmd); |
| 193 | } |
| 194 | } |
Kyösti Mälkki | de271a8 | 2015-03-18 13:09:47 +0200 | [diff] [blame] | 195 | static void amd8131_scan_bus(struct bus *bus, |
| 196 | unsigned min_devfn, unsigned max_devfn) |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 197 | { |
| 198 | struct amd8131_bus_info info; |
| 199 | struct bus *pbus; |
| 200 | unsigned pos; |
| 201 | |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 202 | /* Find the children on the bus */ |
Kyösti Mälkki | de271a8 | 2015-03-18 13:09:47 +0200 | [diff] [blame] | 203 | pci_scan_bus(bus, min_devfn, max_devfn); |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 204 | |
| 205 | /* Find the revision of the 8131 */ |
| 206 | info.rev = pci_read_config8(bus->dev, PCI_CLASS_REVISION); |
| 207 | |
| 208 | /* See which errata apply */ |
| 209 | info.errata_56 = info.rev <= 0x12; |
| 210 | |
| 211 | /* Find the pcix capability and get the secondary bus status */ |
| 212 | pos = pci_find_capability(bus->dev, PCI_CAP_ID_PCIX); |
| 213 | info.sstatus = pci_read_config16(bus->dev, pos + PCI_X_SEC_STATUS); |
| 214 | |
| 215 | /* Print the PCI-X bus speed */ |
Stefan Reinauer | c02b4fc | 2010-03-22 11:42:32 +0000 | [diff] [blame] | 216 | printk(BIOS_DEBUG, "PCI: %02x: %s\n", bus->secondary, pcix_speed(info.sstatus)); |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 217 | |
| 218 | |
| 219 | /* Examine the bus and find out how loaded it is */ |
| 220 | info.max_func = 0; |
| 221 | info.master_devices = 0; |
| 222 | amd8131_walk_children(bus, amd8131_count_dev, &info); |
| 223 | |
| 224 | /* Disable the bus if there are no devices on it or |
| 225 | * we are running at 133Mhz and have a 4 function device. |
| 226 | * see errata #56 |
| 227 | */ |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 228 | if (!bus->children || |
| 229 | (info.errata_56 && |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 230 | (info.max_func >= 3) && |
| 231 | (PCI_X_SSTATUS_MFREQ(info.sstatus) == PCI_X_SSTATUS_MODE1_133MHZ))) |
| 232 | { |
| 233 | unsigned pcix_misc; |
| 234 | /* Disable all of my children */ |
| 235 | disable_children(bus); |
| 236 | |
| 237 | /* Remember the device is disabled */ |
| 238 | bus->dev->enabled = 0; |
| 239 | |
| 240 | /* Disable the PCI-X clocks */ |
| 241 | pcix_misc = pci_read_config32(bus->dev, 0x40); |
| 242 | pcix_misc &= ~(0x1f << 16); |
| 243 | pci_write_config32(bus->dev, 0x40, pcix_misc); |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 244 | |
Kyösti Mälkki | de271a8 | 2015-03-18 13:09:47 +0200 | [diff] [blame] | 245 | return; |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 246 | } |
| 247 | |
| 248 | /* If we are in conventional PCI mode nothing more is necessary. |
| 249 | */ |
| 250 | if (PCI_X_SSTATUS_MFREQ(info.sstatus) == PCI_X_SSTATUS_CONVENTIONAL_PCI) { |
Kyösti Mälkki | de271a8 | 2015-03-18 13:09:47 +0200 | [diff] [blame] | 251 | return; |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 252 | } |
| 253 | |
| 254 | |
| 255 | /* Tune the devices on the bus */ |
| 256 | amd8131_walk_children(bus, amd8131_pcix_tune_dev, &info); |
| 257 | |
| 258 | /* Don't allow the 8131 or any of it's parent busses to |
| 259 | * implement relaxed ordering. Errata #58 |
| 260 | */ |
| 261 | for(pbus = bus; !pbus->disable_relaxed_ordering; pbus = pbus->dev->bus) { |
Stefan Reinauer | c02b4fc | 2010-03-22 11:42:32 +0000 | [diff] [blame] | 262 | printk(BIOS_SPEW, "%s disabling relaxed ordering\n", |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 263 | bus_path(pbus)); |
| 264 | pbus->disable_relaxed_ordering = 1; |
| 265 | } |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 266 | } |
| 267 | |
Kyösti Mälkki | 580e722 | 2015-03-19 21:04:23 +0200 | [diff] [blame] | 268 | static void amd8131_scan_bridge(device_t dev) |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 269 | { |
Kyösti Mälkki | 580e722 | 2015-03-19 21:04:23 +0200 | [diff] [blame] | 270 | do_pci_scan_bridge(dev, amd8131_scan_bus); |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 271 | } |
| 272 | |
| 273 | |
| 274 | static void amd8131_pcix_init(device_t dev) |
Eric Biederman | 4086d16 | 2003-07-17 03:26:03 +0000 | [diff] [blame] | 275 | { |
Eric Biederman | 5cd8173 | 2004-03-11 15:01:31 +0000 | [diff] [blame] | 276 | uint32_t dword; |
Eric Biederman | 860ad37 | 2003-07-21 23:30:29 +0000 | [diff] [blame] | 277 | uint16_t word; |
| 278 | uint8_t byte; |
Luc Verhaegen | a9c5ea0 | 2009-06-03 14:19:33 +0000 | [diff] [blame] | 279 | int nmi_option; |
Eric Biederman | 860ad37 | 2003-07-21 23:30:29 +0000 | [diff] [blame] | 280 | |
Eric Biederman | 860ad37 | 2003-07-21 23:30:29 +0000 | [diff] [blame] | 281 | /* Enable memory write and invalidate ??? */ |
| 282 | byte = pci_read_config8(dev, 0x04); |
| 283 | byte |= 0x10; |
| 284 | pci_write_config8(dev, 0x04, byte); |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 285 | |
Eric Biederman | 860ad37 | 2003-07-21 23:30:29 +0000 | [diff] [blame] | 286 | /* Set drive strength */ |
| 287 | word = pci_read_config16(dev, 0xe0); |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 288 | word = 0x0404; |
Eric Biederman | 860ad37 | 2003-07-21 23:30:29 +0000 | [diff] [blame] | 289 | pci_write_config16(dev, 0xe0, word); |
| 290 | word = pci_read_config16(dev, 0xe4); |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 291 | word = 0x0404; |
Eric Biederman | 860ad37 | 2003-07-21 23:30:29 +0000 | [diff] [blame] | 292 | pci_write_config16(dev, 0xe4, word); |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 293 | |
Eric Biederman | 860ad37 | 2003-07-21 23:30:29 +0000 | [diff] [blame] | 294 | /* Set impedance */ |
| 295 | word = pci_read_config16(dev, 0xe8); |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 296 | word = 0x0404; |
Eric Biederman | 860ad37 | 2003-07-21 23:30:29 +0000 | [diff] [blame] | 297 | pci_write_config16(dev, 0xe8, word); |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 298 | |
| 299 | /* Set discard unrequested prefetch data */ |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 300 | /* Errata #51 */ |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 301 | word = pci_read_config16(dev, 0x4c); |
| 302 | word |= 1; |
| 303 | pci_write_config16(dev, 0x4c, word); |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 304 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 305 | /* Set split transaction limits */ |
| 306 | word = pci_read_config16(dev, 0xa8); |
| 307 | pci_write_config16(dev, 0xaa, word); |
| 308 | word = pci_read_config16(dev, 0xac); |
| 309 | pci_write_config16(dev, 0xae, word); |
Eric Biederman | 5cd8173 | 2004-03-11 15:01:31 +0000 | [diff] [blame] | 310 | |
| 311 | /* Set up error reporting, enable all */ |
| 312 | /* system error enable */ |
| 313 | dword = pci_read_config32(dev, 0x04); |
| 314 | dword |= (1<<8); |
| 315 | pci_write_config32(dev, 0x04, dword); |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 316 | |
Eric Biederman | 5cd8173 | 2004-03-11 15:01:31 +0000 | [diff] [blame] | 317 | /* system and error parity enable */ |
| 318 | dword = pci_read_config32(dev, 0x3c); |
| 319 | dword |= (3<<16); |
| 320 | pci_write_config32(dev, 0x3c, dword); |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 321 | |
Eric Biederman | 5cd8173 | 2004-03-11 15:01:31 +0000 | [diff] [blame] | 322 | /* NMI enable */ |
| 323 | nmi_option = NMI_OFF; |
Luc Verhaegen | a9c5ea0 | 2009-06-03 14:19:33 +0000 | [diff] [blame] | 324 | get_option(&nmi_option, "nmi"); |
Eric Biederman | 5cd8173 | 2004-03-11 15:01:31 +0000 | [diff] [blame] | 325 | if(nmi_option) { |
| 326 | dword = pci_read_config32(dev, 0x44); |
| 327 | dword |= (1<<0); |
| 328 | pci_write_config32(dev, 0x44, dword); |
| 329 | } |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 330 | |
Eric Biederman | 5cd8173 | 2004-03-11 15:01:31 +0000 | [diff] [blame] | 331 | /* Set up CRC flood enable */ |
| 332 | dword = pci_read_config32(dev, 0xc0); |
| 333 | if(dword) { /* do device A only */ |
| 334 | dword = pci_read_config32(dev, 0xc4); |
| 335 | dword |= (1<<1); |
| 336 | pci_write_config32(dev, 0xc4, dword); |
| 337 | dword = pci_read_config32(dev, 0xc8); |
| 338 | dword |= (1<<1); |
| 339 | pci_write_config32(dev, 0xc8, dword); |
| 340 | } |
Eric Biederman | 4086d16 | 2003-07-17 03:26:03 +0000 | [diff] [blame] | 341 | return; |
| 342 | } |
| 343 | |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 344 | #define BRIDGE_40_BIT_SUPPORT 0 |
| 345 | #if BRIDGE_40_BIT_SUPPORT |
| 346 | static void bridge_read_resources(struct device *dev) |
| 347 | { |
| 348 | struct resource *res; |
| 349 | pci_bus_read_resources(dev); |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 350 | res = find_resource(dev, PCI_MEMORY_BASE); |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 351 | if (res) { |
| 352 | res->limit = 0xffffffffffULL; |
| 353 | } |
| 354 | } |
| 355 | |
| 356 | static void bridge_set_resources(struct device *dev) |
| 357 | { |
| 358 | struct resource *res; |
| 359 | res = find_resource(dev, PCI_MEMORY_BASE); |
| 360 | if (res) { |
| 361 | resource_t base, end; |
| 362 | /* set the memory range */ |
| 363 | dev->command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; |
| 364 | res->flags |= IORESOURCE_STORED; |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 365 | base = res->base; |
| 366 | end = resource_end(res); |
| 367 | pci_write_config16(dev, PCI_MEMORY_BASE, base >> 16); |
| 368 | pci_write_config8(dev, NPUML, (base >> 32) & 0xff); |
| 369 | pci_write_config16(dev, PCI_MEMORY_LIMIT, end >> 16); |
| 370 | pci_write_config8(dev, NPUMB, (end >> 32) & 0xff); |
| 371 | |
| 372 | report_resource_stored(dev, res, ""); |
| 373 | } |
| 374 | pci_dev_set_resources(dev); |
| 375 | } |
| 376 | #endif /* BRIDGE_40_BIT_SUPPORT */ |
| 377 | |
Eric Biederman | 4086d16 | 2003-07-17 03:26:03 +0000 | [diff] [blame] | 378 | static struct device_operations pcix_ops = { |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 379 | #if BRIDGE_40_BIT_SUPPORT |
| 380 | .read_resources = bridge_read_resources, |
| 381 | .set_resources = bridge_set_resources, |
| 382 | #else |
Eric Biederman | e9a271e3 | 2003-09-02 03:36:25 +0000 | [diff] [blame] | 383 | .read_resources = pci_bus_read_resources, |
| 384 | .set_resources = pci_dev_set_resources, |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 385 | #endif |
Eric Biederman | e9a271e3 | 2003-09-02 03:36:25 +0000 | [diff] [blame] | 386 | .enable_resources = pci_bus_enable_resources, |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 387 | .init = amd8131_pcix_init, |
| 388 | .scan_bus = amd8131_scan_bridge, |
| 389 | .reset_bus = pci_bus_reset, |
Eric Biederman | 4086d16 | 2003-07-17 03:26:03 +0000 | [diff] [blame] | 390 | }; |
| 391 | |
Stefan Reinauer | f1cf1f7 | 2007-10-24 09:08:58 +0000 | [diff] [blame] | 392 | static const struct pci_driver pcix_driver __pci_driver = { |
Eric Biederman | 4086d16 | 2003-07-17 03:26:03 +0000 | [diff] [blame] | 393 | .ops = &pcix_ops, |
| 394 | .vendor = PCI_VENDOR_ID_AMD, |
| 395 | .device = 0x7450, |
| 396 | }; |
| 397 | |
| 398 | |
| 399 | static void ioapic_enable(device_t dev) |
| 400 | { |
| 401 | uint32_t value; |
Li-Ta Lo | 69c5a90 | 2004-04-29 20:08:54 +0000 | [diff] [blame] | 402 | |
Eric Biederman | 4086d16 | 2003-07-17 03:26:03 +0000 | [diff] [blame] | 403 | value = pci_read_config32(dev, 0x44); |
Li-Ta Lo | 69c5a90 | 2004-04-29 20:08:54 +0000 | [diff] [blame] | 404 | if (dev->enabled) { |
Eric Biederman | 4086d16 | 2003-07-17 03:26:03 +0000 | [diff] [blame] | 405 | value |= ((1 << 1) | (1 << 0)); |
| 406 | } else { |
| 407 | value &= ~((1 << 1) | (1 << 0)); |
| 408 | } |
| 409 | pci_write_config32(dev, 0x44, value); |
Eric Biederman | 4086d16 | 2003-07-17 03:26:03 +0000 | [diff] [blame] | 410 | } |
| 411 | |
Eric Biederman | dbec2d4 | 2004-10-21 10:44:08 +0000 | [diff] [blame] | 412 | static struct pci_operations pci_ops_pci_dev = { |
| 413 | .set_subsystem = pci_dev_set_subsystem, |
| 414 | }; |
Eric Biederman | 4086d16 | 2003-07-17 03:26:03 +0000 | [diff] [blame] | 415 | static struct device_operations ioapic_ops = { |
Eric Biederman | e9a271e3 | 2003-09-02 03:36:25 +0000 | [diff] [blame] | 416 | .read_resources = pci_dev_read_resources, |
| 417 | .set_resources = pci_dev_set_resources, |
| 418 | .enable_resources = pci_dev_enable_resources, |
Eric Biederman | dbec2d4 | 2004-10-21 10:44:08 +0000 | [diff] [blame] | 419 | .init = 0, |
| 420 | .scan_bus = 0, |
| 421 | .enable = ioapic_enable, |
| 422 | .ops_pci = &pci_ops_pci_dev, |
Eric Biederman | 4086d16 | 2003-07-17 03:26:03 +0000 | [diff] [blame] | 423 | }; |
| 424 | |
Stefan Reinauer | f1cf1f7 | 2007-10-24 09:08:58 +0000 | [diff] [blame] | 425 | static const struct pci_driver ioapic_driver __pci_driver = { |
Eric Biederman | 4086d16 | 2003-07-17 03:26:03 +0000 | [diff] [blame] | 426 | .ops = &ioapic_ops, |
| 427 | .vendor = PCI_VENDOR_ID_AMD, |
| 428 | .device = 0x7451, |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 429 | |
Eric Biederman | 4086d16 | 2003-07-17 03:26:03 +0000 | [diff] [blame] | 430 | }; |