diff options
author | Marc Jones <marc.jones@chromium.org> | 2012-10-29 05:24:01 +0000 |
---|---|---|
committer | Tom Rini <trini@ti.com> | 2012-11-02 15:20:43 -0700 |
commit | 2a0c61d401732a2c21b0dc7fe6d1aeec79da8c05 (patch) | |
tree | e350c6aa8667d2477a1720d0e33a07b73de690be /drivers | |
parent | 57847660bb9ddba1d4bc9c1dc551730f71c097a7 (diff) | |
download | u-boot-imx-2a0c61d401732a2c21b0dc7fe6d1aeec79da8c05.zip u-boot-imx-2a0c61d401732a2c21b0dc7fe6d1aeec79da8c05.tar.gz u-boot-imx-2a0c61d401732a2c21b0dc7fe6d1aeec79da8c05.tar.bz2 |
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: Marc Jones <marc.jones@chromium.org>
Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/ahci.c | 45 |
1 files changed, 39 insertions, 6 deletions
diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c index 719574f..19c5f13 100644 --- a/drivers/block/ahci.c +++ b/drivers/block/ahci.c @@ -53,6 +53,7 @@ hd_driveid_t *ataid[AHCI_MAX_PORTS]; #endif /* Maximum timeouts for each event */ +#define WAIT_MS_SPINUP 10000 #define WAIT_MS_DATAIO 5000 #define WAIT_MS_LINKUP 4 @@ -129,7 +130,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) unsigned short vendor; #endif volatile u8 *mmio = (volatile u8 *)probe_ent->mmio_base; - u32 tmp, cap_save; + u32 tmp, cap_save, cmd; int i, j; volatile u8 *port_mmio; @@ -137,7 +138,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) cap_save = readl(mmio + HOST_CAP); cap_save &= ((1 << 28) | (1 << 17)); - cap_save |= (1 << 27); + cap_save |= (1 << 27); /* Staggered Spin-up. Not needed. */ /* global controller reset */ tmp = readl(mmio + HOST_CTL); @@ -201,9 +202,18 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) msleep(500); } - debug("Spinning up port %d... ", i); - writel(PORT_CMD_SPIN_UP, port_mmio + PORT_CMD); - + /* Add the spinup command to whatever mode bits may + * 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; while (j < WAIT_MS_LINKUP) { tmp = readl(port_mmio + PORT_SCR_STAT); @@ -212,7 +222,30 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) udelay(1000); 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"); else debug("ok.\n"); |