summaryrefslogtreecommitdiffstats
path: root/drivers/ata/ahci.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-01-21 18:16:08 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-21 18:16:08 -0800
commitfbd918a2026d0464ce9c23f57b7de4bcfccdc2e6 (patch)
tree5450f3ae050870b48ad8612d0007eacf0b30d9c7 /drivers/ata/ahci.c
parentf075e0f6993f41c72dbb1d3e7a2d7740f14e89e2 (diff)
parentb7db4f2e15603c394da56a0536a33669f4c87c4f (diff)
Merge branch 'for-3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata
Pull libata updates from Tejun Heo: "Support for some new embedded controllers. A couple late (<= a week) fixes have stable cc'd and one patch ("SATA: MV: Add support for the optional PHYs") got committed yesterday because otherwise the resulting kernel would fail boot on an embedded board due to interdependent changes in its platform tree. Other than that, nothing too noteworthy" * 'for-3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata: SATA: MV: Add support for the optional PHYs sata-highbank: Remove unnecessary ahci_platform.h include libata: disable LPM for some WD SATA-I devices ARM: mvebu: update the SATA compatible string for Armada 370/XP ata: sata_mv: fix disk hotplug for Armada 370/XP SoCs ata: sata_mv: introduce compatible string "marvell, armada-370-sata" ata: pata_samsung_cf: Remove unused macros ata: pata_samsung_cf: Use devm_ioremap_resource() ata: pata_samsung_cf: Merge pata_samsung_cf.h into pata_samsung_cf.c ata: pata_samsung_cf: Move plat/regs-ata.h to drivers/ata drivers: ata: Mark the function as static in libahci.c drivers: ata: Mark the function ahci_init_interrupts() as static in ahci.c ahci: imx: fix the error handling in imx_ahci_probe() ahci: imx: ahci_imx_softreset() can be static ahci: imx: Add i.MX53 support ahci: imx: Pull out the clock enable/disable calls libata, dt: Document sata_rcar bindings sata_rcar: Add R-Car Gen2 SATA PHY support ahci: mcp89: enter AHCI mode under Apple BIOS emulation ata: libata-eh: Remove unnecessary snprintf arithmetic
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r--drivers/ata/ahci.c62
1 files changed, 52 insertions, 10 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index e3a92a6da39..74911c2cb1d 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -83,6 +83,8 @@ enum board_ids {
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
+static void ahci_mcp89_apple_enable(struct pci_dev *pdev);
+static bool is_mcp89_apple(struct pci_dev *pdev);
static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
#ifdef CONFIG_PM
@@ -664,6 +666,10 @@ static int ahci_pci_device_resume(struct pci_dev *pdev)
if (rc)
return rc;
+ /* Apple BIOS helpfully mangles the registers on resume */
+ if (is_mcp89_apple(pdev))
+ ahci_mcp89_apple_enable(pdev);
+
if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
rc = ahci_pci_reset_controller(host);
if (rc)
@@ -780,6 +786,48 @@ static void ahci_p5wdh_workaround(struct ata_host *host)
}
}
+/*
+ * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when
+ * booting in BIOS compatibility mode. We restore the registers but not ID.
+ */
+static void ahci_mcp89_apple_enable(struct pci_dev *pdev)
+{
+ u32 val;
+
+ printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n");
+
+ pci_read_config_dword(pdev, 0xf8, &val);
+ val |= 1 << 0x1b;
+ /* the following changes the device ID, but appears not to affect function */
+ /* val = (val & ~0xf0000000) | 0x80000000; */
+ pci_write_config_dword(pdev, 0xf8, val);
+
+ pci_read_config_dword(pdev, 0x54c, &val);
+ val |= 1 << 0xc;
+ pci_write_config_dword(pdev, 0x54c, val);
+
+ pci_read_config_dword(pdev, 0x4a4, &val);
+ val &= 0xff;
+ val |= 0x01060100;
+ pci_write_config_dword(pdev, 0x4a4, val);
+
+ pci_read_config_dword(pdev, 0x54c, &val);
+ val &= ~(1 << 0xc);
+ pci_write_config_dword(pdev, 0x54c, val);
+
+ pci_read_config_dword(pdev, 0xf8, &val);
+ val &= ~(1 << 0x1b);
+ pci_write_config_dword(pdev, 0xf8, val);
+}
+
+static bool is_mcp89_apple(struct pci_dev *pdev)
+{
+ return pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
+ pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
+ pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
+ pdev->subsystem_device == 0xcb89;
+}
+
/* only some SB600 ahci controllers can do 64bit DMA */
static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
{
@@ -1100,7 +1148,7 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
{}
#endif
-int ahci_init_interrupts(struct pci_dev *pdev, struct ahci_host_priv *hpriv)
+static int ahci_init_interrupts(struct pci_dev *pdev, struct ahci_host_priv *hpriv)
{
int rc;
unsigned int maxvec;
@@ -1212,15 +1260,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
return -ENODEV;
- /*
- * For some reason, MCP89 on MacBook 7,1 doesn't work with
- * ahci, use ata_generic instead.
- */
- if (pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
- pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
- pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
- pdev->subsystem_device == 0xcb89)
- return -ENODEV;
+ /* Apple BIOS on MCP89 prevents us using AHCI */
+ if (is_mcp89_apple(pdev))
+ ahci_mcp89_apple_enable(pdev);
/* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
* At the moment, we can only use the AHCI mode. Let the users know