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 | |
| parent | 57847660bb9ddba1d4bc9c1dc551730f71c097a7 (diff) | |
| download | olio-uboot-2014.01-2a0c61d401732a2c21b0dc7fe6d1aeec79da8c05.tar.xz olio-uboot-2014.01-2a0c61d401732a2c21b0dc7fe6d1aeec79da8c05.zip | |
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>
| -rw-r--r-- | drivers/block/ahci.c | 43 | 
1 files changed, 38 insertions, 5 deletions
| diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c index 719574f22..19c5f137f 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"); |