X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fblock%2Fmvsata_ide.c;h=e54d564bf764d0a6015bf84fc1c6cfd3999eeacd;hb=372d7decfe972966c49b337f3d2888e09004dbe4;hp=077b2789bb3c8d99df6c4a8e0b561434a6f5bb0b;hpb=b77f380115028ef4b6cc59fc5ba332a6e31b4326;p=oweals%2Fu-boot.git diff --git a/drivers/block/mvsata_ide.c b/drivers/block/mvsata_ide.c index 077b2789bb..e54d564bf7 100644 --- a/drivers/block/mvsata_ide.c +++ b/drivers/block/mvsata_ide.c @@ -1,25 +1,9 @@ /* - * 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. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA + * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -28,12 +12,14 @@ #if defined(CONFIG_ORION5X) #include #elif defined(CONFIG_KIRKWOOD) -#include +#include #endif /* SATA port registers */ struct mvsata_port_registers { - u32 reserved1[192]; + u32 reserved0[10]; + u32 edma_cmd; + u32 reserved1[181]; /* offset 0x300 : ATA Interface registers */ u32 sstatus; u32 serror; @@ -54,8 +40,8 @@ struct mvsata_port_registers { * Sanity checks: * - to compile at all, we need CONFIG_SYS_ATA_BASE_ADDR. * - for ide_preinit to make sense, we need at least one of - * CONFIG_SYS_ATA_IDE0_OFFSET or CONFIG_SYS_ATA_IDE0_OFFSET; - * - for inde_preinit to be called, we need CONFIG_IDE_PREINIT. + * CONFIG_SYS_ATA_IDE0_OFFSET or CONFIG_SYS_ATA_IDE1_OFFSET; + * - for ide_preinit to be called, we need CONFIG_IDE_PREINIT. * Fail with an explanation message if these conditions are not met. * This is particularly important for CONFIG_IDE_PREINIT, because * its lack would not cause a build error. @@ -76,6 +62,7 @@ struct mvsata_port_registers { * and for SStatus DETection. */ +#define MVSATA_EDMA_CMD_ATA_RST 0x00000004 #define MVSATA_SCONTROL_DET_MASK 0x0000000F #define MVSATA_SCONTROL_DET_NONE 0x00000000 #define MVSATA_SCONTROL_DET_INIT 0x00000001 @@ -90,6 +77,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 +96,35 @@ 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 */ + /* Hard reset */ + writel(MVSATA_EDMA_CMD_ATA_RST, &port->edma_cmd); + udelay(25); /* taken from original marvell port */ + writel(0, &port->edma_cmd); + + /* 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 +134,25 @@ static void mvsata_ide_initialize_port(struct mvsata_port_registers *port) int ide_preinit(void) { + int ret = MVSATA_STATUS_TIMEOUT; + 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 == MVSATA_STATUS_OK) + ret = MVSATA_STATUS_OK; #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 == MVSATA_STATUS_OK) + ret = MVSATA_STATUS_OK; #endif - /* return 0 as we always succeed */ - return 0; + /* Return success if at least one port initialization succeeded */ + return ret; }