Commit 2a0c61d4 authored by Marc Jones's avatar Marc Jones Committed by Tom Rini
Browse files

ahci: Support spin-up and link-up separately



Add HDD handling to the SSD-only AHCI driver, by separately dealing with
spin-up and link-up.
Signed-off-by: default avatarMarc Jones <marc.jones@chromium.org>
Signed-off-by: default avatarSimon Glass <sjg@chromium.org>
parent 57847660
...@@ -53,6 +53,7 @@ hd_driveid_t *ataid[AHCI_MAX_PORTS]; ...@@ -53,6 +53,7 @@ hd_driveid_t *ataid[AHCI_MAX_PORTS];
#endif #endif
/* Maximum timeouts for each event */ /* Maximum timeouts for each event */
#define WAIT_MS_SPINUP 10000
#define WAIT_MS_DATAIO 5000 #define WAIT_MS_DATAIO 5000
#define WAIT_MS_LINKUP 4 #define WAIT_MS_LINKUP 4
...@@ -129,7 +130,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) ...@@ -129,7 +130,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
unsigned short vendor; unsigned short vendor;
#endif #endif
volatile u8 *mmio = (volatile u8 *)probe_ent->mmio_base; volatile u8 *mmio = (volatile u8 *)probe_ent->mmio_base;
u32 tmp, cap_save; u32 tmp, cap_save, cmd;
int i, j; int i, j;
volatile u8 *port_mmio; volatile u8 *port_mmio;
...@@ -137,7 +138,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) ...@@ -137,7 +138,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
cap_save = readl(mmio + HOST_CAP); cap_save = readl(mmio + HOST_CAP);
cap_save &= ((1 << 28) | (1 << 17)); cap_save &= ((1 << 28) | (1 << 17));
cap_save |= (1 << 27); cap_save |= (1 << 27); /* Staggered Spin-up. Not needed. */
/* global controller reset */ /* global controller reset */
tmp = readl(mmio + HOST_CTL); tmp = readl(mmio + HOST_CTL);
...@@ -201,9 +202,18 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) ...@@ -201,9 +202,18 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
msleep(500); msleep(500);
} }
debug("Spinning up port %d... ", i); /* Add the spinup command to whatever mode bits may
writel(PORT_CMD_SPIN_UP, port_mmio + PORT_CMD); * already be on in the command register.
*/
cmd = readl(port_mmio + PORT_CMD);
cmd |= PORT_CMD_FIS_RX;
cmd |= PORT_CMD_SPIN_UP;
writel_with_flush(cmd, port_mmio + PORT_CMD);
/* Bring up SATA link.
* SATA link bringup time is usually less than 1 ms; only very
* rarely has it taken between 1-2 ms. Never seen it above 2 ms.
*/
j = 0; j = 0;
while (j < WAIT_MS_LINKUP) { while (j < WAIT_MS_LINKUP) {
tmp = readl(port_mmio + PORT_SCR_STAT); tmp = readl(port_mmio + PORT_SCR_STAT);
...@@ -212,7 +222,30 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) ...@@ -212,7 +222,30 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
udelay(1000); udelay(1000);
j++; j++;
} }
if (j == WAIT_MS_LINKUP) if (j == WAIT_MS_LINKUP) {
printf("SATA link %d timeout.\n", i);
continue;
} else {
debug("SATA link ok.\n");
}
/* Clear error status */
tmp = readl(port_mmio + PORT_SCR_ERR);
if (tmp)
writel(tmp, port_mmio + PORT_SCR_ERR);
debug("Spinning up device on SATA port %d... ", i);
j = 0;
while (j < WAIT_MS_SPINUP) {
tmp = readl(port_mmio + PORT_TFDATA);
if (!(tmp & (ATA_STAT_BUSY | ATA_STAT_DRQ)))
break;
udelay(1000);
j++;
}
printf("Target spinup took %d ms.\n", j);
if (j == WAIT_MS_SPINUP)
debug("timeout.\n"); debug("timeout.\n");
else else
debug("ok.\n"); debug("ok.\n");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment