X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fblock%2Fmvsata_ide.c;h=e0e40975937f3b972c62e8fe14e00022992c939f;hb=909e9bf3ae6195ac6d52f9e453fba2be8e7e947f;hp=077b2789bb3c8d99df6c4a8e0b561434a6f5bb0b;hpb=39419ce589bb6b8c25819abe21eaa3c721dfb8b9;p=u-boot diff --git a/drivers/block/mvsata_ide.c b/drivers/block/mvsata_ide.c index 077b2789bb..e0e4097593 100644 --- a/drivers/block/mvsata_ide.c +++ b/drivers/block/mvsata_ide.c @@ -1,7 +1,7 @@ /* - * Copyright (C) 2010 Albert ARIBAUD + * Copyright (C) 2010 Albert ARIBAUD * - * Written-by: Albert ARIBAUD + * Written-by: Albert ARIBAUD * * See file CREDITS for list of people who contributed to this * project. @@ -90,6 +90,18 @@ struct mvsata_port_registers { #define MVSATA_SSTATUS_DET_MASK 0x0000000F #define MVSATA_SSTATUS_DET_DEVCOMM 0x00000003 +/* + * Status codes to return to client callers. Currently, callers ignore + * exact value and only care for zero or nonzero, so no need to make this + * public, it is only #define'd for clarity. + * If/when standard negative codes are implemented in U-boot, then these + * #defines should be moved to, or replaced by ones from, the common list + * of status codes. + */ + +#define MVSATA_STATUS_OK 0 +#define MVSATA_STATUS_TIMEOUT -1 + /* * Initialize one MVSATAHC port: set SControl's IPM to "always active" * and DET to "reset", then wait for SStatus's DET to become "device and @@ -97,23 +109,30 @@ struct mvsata_port_registers { * DET back to "no action". */ -static void mvsata_ide_initialize_port(struct mvsata_port_registers *port) +static int mvsata_ide_initialize_port(struct mvsata_port_registers *port) { u32 control; u32 status; - u32 tout = 50; /* wait at most 50 us for SATA reset to complete */ + u32 timeleft = 10000; /* wait at most 10 ms for SATA reset to complete */ + /* Set control IPM to 3 (no low power) and DET to 1 (initialize) */ control = readl(&port->scontrol); control = (control & ~MVSATA_SCONTROL_MASK) | MVSATA_PORT_INIT; writel(control, &port->scontrol); - while (--tout) { + /* Toggle control DET back to 0 (normal operation) */ + control = (control & ~MVSATA_SCONTROL_MASK) | MVSATA_PORT_USE; + writel(control, &port->scontrol); + /* wait for status DET to become 3 (device and communication OK) */ + while (--timeleft) { status = readl(&port->sstatus) & MVSATA_SSTATUS_DET_MASK; if (status == MVSATA_SSTATUS_DET_DEVCOMM) break; udelay(1); } - control = (control & ~MVSATA_SCONTROL_MASK) | MVSATA_PORT_USE; - writel(control, &port->scontrol); + /* return success or time-out error depending on time left */ + if (!timeleft) + return MVSATA_STATUS_TIMEOUT; + return MVSATA_STATUS_OK; } /* @@ -123,18 +142,23 @@ static void mvsata_ide_initialize_port(struct mvsata_port_registers *port) int ide_preinit(void) { + int status; /* Enable ATA port 0 (could be SATA port 0 or 1) if declared */ #if defined(CONFIG_SYS_ATA_IDE0_OFFSET) - mvsata_ide_initialize_port( + status = mvsata_ide_initialize_port( (struct mvsata_port_registers *) (CONFIG_SYS_ATA_BASE_ADDR + CONFIG_SYS_ATA_IDE0_OFFSET)); + if (status) + return status; #endif /* Enable ATA port 1 (could be SATA port 0 or 1) if declared */ #if defined(CONFIG_SYS_ATA_IDE1_OFFSET) - mvsata_ide_initialize_port( + status = mvsata_ide_initialize_port( (struct mvsata_port_registers *) (CONFIG_SYS_ATA_BASE_ADDR + CONFIG_SYS_ATA_IDE1_OFFSET)); + if (status) + return status; #endif - /* return 0 as we always succeed */ - return 0; + /* return success if all ports initializations succeeded */ + return MVSATA_STATUS_OK; }