summary refs log tree commit diff
path: root/drivers/ata
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2008-01-05 23:11:57 +0900
committerJeff Garzik <jeff@garzik.org>2008-01-23 05:24:16 -0500
commitb710a1f4b34438b624e9c6c2dc8bcf54b0b0ba27 (patch)
treef8bb87bd4cbc2591da8c0b9bdaf01b426902800b /drivers/ata
parentc729072459446885c5c200137de1db32da5db4dc (diff)
downloadlinux-b710a1f4b34438b624e9c6c2dc8bcf54b0b0ba27.tar.gz
ahci: factor out AHCI enabling and enable AHCI before reading CAP
Factor out AHCI enabling into ahci_enable_ahci() and enabling AHCI
before reading CAP in ahci_save_initial_config() as the spec requires
enabling AHCI mode before accessing any other registers.

Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/ahci.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 49761bc12cf2..6f089b899a1a 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -597,6 +597,20 @@ static inline void __iomem *ahci_port_base(struct ata_port *ap)
 	return __ahci_port_base(ap->host, ap->port_no);
 }
 
+static void ahci_enable_ahci(void __iomem *mmio)
+{
+	u32 tmp;
+
+	/* turn on AHCI_EN */
+	tmp = readl(mmio + HOST_CTL);
+	if (!(tmp & HOST_AHCI_EN)) {
+		tmp |= HOST_AHCI_EN;
+		writel(tmp, mmio + HOST_CTL);
+		tmp = readl(mmio + HOST_CTL);	/* flush && sanity check */
+		WARN_ON(!(tmp & HOST_AHCI_EN));
+	}
+}
+
 /**
  *	ahci_save_initial_config - Save and fixup initial config values
  *	@pdev: target PCI device
@@ -619,6 +633,9 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
 	u32 cap, port_map;
 	int i;
 
+	/* make sure AHCI mode is enabled before accessing CAP */
+	ahci_enable_ahci(mmio);
+
 	/* Values prefixed with saved_ are written back to host after
 	 * reset.  Values without are used for driver operation.
 	 */
@@ -1043,13 +1060,10 @@ static int ahci_reset_controller(struct ata_host *host)
 	/* we must be in AHCI mode, before using anything
 	 * AHCI-specific, such as HOST_RESET.
 	 */
-	tmp = readl(mmio + HOST_CTL);
-	if (!(tmp & HOST_AHCI_EN)) {
-		tmp |= HOST_AHCI_EN;
-		writel(tmp, mmio + HOST_CTL);
-	}
+	ahci_enable_ahci(mmio);
 
 	/* global controller reset */
+	tmp = readl(mmio + HOST_CTL);
 	if ((tmp & HOST_RESET) == 0) {
 		writel(tmp | HOST_RESET, mmio + HOST_CTL);
 		readl(mmio + HOST_CTL); /* flush */
@@ -1068,8 +1082,7 @@ static int ahci_reset_controller(struct ata_host *host)
 	}
 
 	/* turn on AHCI mode */
-	writel(HOST_AHCI_EN, mmio + HOST_CTL);
-	(void) readl(mmio + HOST_CTL);	/* flush */
+	ahci_enable_ahci(mmio);
 
 	/* some registers might be cleared on reset.  restore initial values */
 	ahci_restore_initial_config(host);