|
2 | 2 | * Exceptions for specific devices. Usually work-arounds for fatal design flaws.
|
3 | 3 | */
|
4 | 4 |
|
| 5 | +#include <linux/delay.h> |
| 6 | +#include <linux/dmi.h> |
5 | 7 | #include <linux/pci.h>
|
6 | 8 | #include <linux/init.h>
|
7 | 9 | #include "pci.h"
|
@@ -384,3 +386,60 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev)
|
384 | 386 | }
|
385 | 387 | }
|
386 | 388 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
|
| 389 | + |
| 390 | +/* |
| 391 | + * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A. |
| 392 | + * |
| 393 | + * We pretend to bring them out of full D3 state, and restore the proper |
| 394 | + * IRQ, PCI cache line size, and BARs, otherwise the device won't function |
| 395 | + * properly. In some cases, the device will generate an interrupt on |
| 396 | + * the wrong IRQ line, causing any devices sharing the the line it's |
| 397 | + * *supposed* to use to be disabled by the kernel's IRQ debug code. |
| 398 | + */ |
| 399 | +static u16 toshiba_line_size; |
| 400 | + |
| 401 | +static struct dmi_system_id __devinit toshiba_ohci1394_dmi_table[] = { |
| 402 | + { |
| 403 | + .ident = "Toshiba PS5 based laptop", |
| 404 | + .matches = { |
| 405 | + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), |
| 406 | + DMI_MATCH(DMI_PRODUCT_VERSION, "PS5"), |
| 407 | + }, |
| 408 | + }, |
| 409 | + { |
| 410 | + .ident = "Toshiba PSM4 based laptop", |
| 411 | + .matches = { |
| 412 | + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), |
| 413 | + DMI_MATCH(DMI_PRODUCT_VERSION, "PSM4"), |
| 414 | + }, |
| 415 | + }, |
| 416 | + { } |
| 417 | +}; |
| 418 | + |
| 419 | +static void __devinit pci_pre_fixup_toshiba_ohci1394(struct pci_dev *dev) |
| 420 | +{ |
| 421 | + if (!dmi_check_system(toshiba_ohci1394_dmi_table)) |
| 422 | + return; /* only applies to certain Toshibas (so far) */ |
| 423 | + |
| 424 | + dev->current_state = PCI_D3cold; |
| 425 | + pci_read_config_word(dev, PCI_CACHE_LINE_SIZE, &toshiba_line_size); |
| 426 | +} |
| 427 | +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, 0x8032, |
| 428 | + pci_pre_fixup_toshiba_ohci1394); |
| 429 | + |
| 430 | +static void __devinit pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev) |
| 431 | +{ |
| 432 | + if (!dmi_check_system(toshiba_ohci1394_dmi_table)) |
| 433 | + return; /* only applies to certain Toshibas (so far) */ |
| 434 | + |
| 435 | + /* Restore config space on Toshiba laptops */ |
| 436 | + mdelay(10); |
| 437 | + pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, toshiba_line_size); |
| 438 | + pci_write_config_word(dev, PCI_INTERRUPT_LINE, dev->irq); |
| 439 | + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, |
| 440 | + pci_resource_start(dev, 0)); |
| 441 | + pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, |
| 442 | + pci_resource_start(dev, 1)); |
| 443 | +} |
| 444 | +DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032, |
| 445 | + pci_post_fixup_toshiba_ohci1394); |
0 commit comments