| 137 | // ATI/AMD SB600/SB700 periodic list cache workaround |
| 138 | // Logic kindly borrowed from NetBSD PR 40056 |
| 139 | if (fPCIInfo->vendor_id == AMD_SBX00_VENDOR) { |
| 140 | bool applyWorkaround = false; |
| 141 | |
| 142 | if (fPCIInfo->device_id == AMD_SB600_EHCI_CONTROLLER) { |
| 143 | // always apply on SB600 |
| 144 | applyWorkaround = true; |
| 145 | } else if (fPCIInfo->device_id == AMD_SB700_SB800_EHCI_CONTROLLER) { |
| 146 | // only apply on certain chipsets, determined by SMBus revision |
| 147 | pci_info smbus; |
| 148 | int32 index = 0; |
| 149 | while (sPCIModule->get_nth_pci_info(index++, &smbus) >= B_OK) { |
| 150 | if (smbus.vendor_id == AMD_SBX00_VENDOR |
| 151 | && smbus.device_id == AMD_SBX00_SMBUS_CONTROLLER) { |
| 152 | |
| 153 | // Only applies to chipsets < SB710 (rev A14) |
| 154 | if (smbus.revision == 0x3a || smbus.revision == 0x3b) |
| 155 | applyWorkaround = true; |
| 156 | |
| 157 | break; |
| 158 | } |
| 159 | } |
| 160 | } |
| 161 | |
| 162 | if (applyWorkaround) { |
| 163 | // According to AMD errata of SB700 and SB600 register documentation |
| 164 | // this disables the Periodic List Cache on SB600 and the Advanced |
| 165 | // Periodic List Cache on early SB700. Both the BSDs and Linux use |
| 166 | // this workaround. |
| 167 | |
| 168 | TRACE_ALWAYS("disabling SB600/SB700 periodic list cache\n"); |
| 169 | uint32 workaround = sPCIModule->read_pci_config(fPCIInfo->bus, |
| 170 | fPCIInfo->device, fPCIInfo->function, |
| 171 | AMD_SBX00_EHCI_MISC_REGISTER, 4); |
| 172 | |
| 173 | sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device, |
| 174 | fPCIInfo->function, AMD_SBX00_EHCI_MISC_REGISTER, 4, |
| 175 | workaround | AMD_SBX00_EHCI_MISC_DISABLE_PERIODIC_LIST_CACHE); |
| 176 | } |
| 177 | } |
| 178 | |