diff options
author | James Laird <jhl@mafipulation.org> | 2013-11-18 19:06:38 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2013-11-23 08:34:34 -0500 |
commit | cb85696d7277592ddbd2897db9a29f3ec6e9fe11 (patch) | |
tree | 021656b05ff51ae177992f83ba8042c7596124a8 /drivers/ata/ahci.c | |
parent | 462098b090897fbcf00088b225eb7a3adc407e98 (diff) |
ahci: mcp89: enter AHCI mode under Apple BIOS emulation
Apple's BIOS emulation forcibly disables MCP89 AHCI, eg. on Macbook7,1.
We can re-enable it, replacing the previous workaround of using
ata_generic.
tj: whitespace adjustments, dropped inline from is_mcp89_apple()
Signed-off-by: James Laird <jhl@mafipulation.org>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r-- | drivers/ata/ahci.c | 60 |
1 files changed, 51 insertions, 9 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index e2903d03180e..c55e00562527 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -83,6 +83,8 @@ enum board_ids { | |||
83 | static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); | 83 | static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); |
84 | static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, | 84 | static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, |
85 | unsigned long deadline); | 85 | unsigned long deadline); |
86 | static void ahci_mcp89_apple_enable(struct pci_dev *pdev); | ||
87 | static bool is_mcp89_apple(struct pci_dev *pdev); | ||
86 | static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, | 88 | static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, |
87 | unsigned long deadline); | 89 | unsigned long deadline); |
88 | #ifdef CONFIG_PM | 90 | #ifdef CONFIG_PM |
@@ -659,6 +661,10 @@ static int ahci_pci_device_resume(struct pci_dev *pdev) | |||
659 | if (rc) | 661 | if (rc) |
660 | return rc; | 662 | return rc; |
661 | 663 | ||
664 | /* Apple BIOS helpfully mangles the registers on resume */ | ||
665 | if (is_mcp89_apple(pdev)) | ||
666 | ahci_mcp89_apple_enable(pdev); | ||
667 | |||
662 | if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { | 668 | if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { |
663 | rc = ahci_pci_reset_controller(host); | 669 | rc = ahci_pci_reset_controller(host); |
664 | if (rc) | 670 | if (rc) |
@@ -775,6 +781,48 @@ static void ahci_p5wdh_workaround(struct ata_host *host) | |||
775 | } | 781 | } |
776 | } | 782 | } |
777 | 783 | ||
784 | /* | ||
785 | * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when | ||
786 | * booting in BIOS compatibility mode. We restore the registers but not ID. | ||
787 | */ | ||
788 | static void ahci_mcp89_apple_enable(struct pci_dev *pdev) | ||
789 | { | ||
790 | u32 val; | ||
791 | |||
792 | printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n"); | ||
793 | |||
794 | pci_read_config_dword(pdev, 0xf8, &val); | ||
795 | val |= 1 << 0x1b; | ||
796 | /* the following changes the device ID, but appears not to affect function */ | ||
797 | /* val = (val & ~0xf0000000) | 0x80000000; */ | ||
798 | pci_write_config_dword(pdev, 0xf8, val); | ||
799 | |||
800 | pci_read_config_dword(pdev, 0x54c, &val); | ||
801 | val |= 1 << 0xc; | ||
802 | pci_write_config_dword(pdev, 0x54c, val); | ||
803 | |||
804 | pci_read_config_dword(pdev, 0x4a4, &val); | ||
805 | val &= 0xff; | ||
806 | val |= 0x01060100; | ||
807 | pci_write_config_dword(pdev, 0x4a4, val); | ||
808 | |||
809 | pci_read_config_dword(pdev, 0x54c, &val); | ||
810 | val &= ~(1 << 0xc); | ||
811 | pci_write_config_dword(pdev, 0x54c, val); | ||
812 | |||
813 | pci_read_config_dword(pdev, 0xf8, &val); | ||
814 | val &= ~(1 << 0x1b); | ||
815 | pci_write_config_dword(pdev, 0xf8, val); | ||
816 | } | ||
817 | |||
818 | static bool is_mcp89_apple(struct pci_dev *pdev) | ||
819 | { | ||
820 | return pdev->vendor == PCI_VENDOR_ID_NVIDIA && | ||
821 | pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && | ||
822 | pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && | ||
823 | pdev->subsystem_device == 0xcb89; | ||
824 | } | ||
825 | |||
778 | /* only some SB600 ahci controllers can do 64bit DMA */ | 826 | /* only some SB600 ahci controllers can do 64bit DMA */ |
779 | static bool ahci_sb600_enable_64bit(struct pci_dev *pdev) | 827 | static bool ahci_sb600_enable_64bit(struct pci_dev *pdev) |
780 | { | 828 | { |
@@ -1207,15 +1255,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1207 | if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) | 1255 | if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) |
1208 | return -ENODEV; | 1256 | return -ENODEV; |
1209 | 1257 | ||
1210 | /* | 1258 | /* Apple BIOS on MCP89 prevents us using AHCI */ |
1211 | * For some reason, MCP89 on MacBook 7,1 doesn't work with | 1259 | if (is_mcp89_apple(pdev)) |
1212 | * ahci, use ata_generic instead. | 1260 | ahci_mcp89_apple_enable(pdev); |
1213 | */ | ||
1214 | if (pdev->vendor == PCI_VENDOR_ID_NVIDIA && | ||
1215 | pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && | ||
1216 | pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && | ||
1217 | pdev->subsystem_device == 0xcb89) | ||
1218 | return -ENODEV; | ||
1219 | 1261 | ||
1220 | /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode. | 1262 | /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode. |
1221 | * At the moment, we can only use the AHCI mode. Let the users know | 1263 | * At the moment, we can only use the AHCI mode. Let the users know |