[U-Boot] [PATCH 0/5] introduce sata stop

This series adds the sata stop command, which includes both cmd_sata code and driver support for resetting sata. A non-dummy reset_sata() is provided for dwc_ahsata, and a non-default sata_stop() is provided for cm_fx6. Finally, we use the new functionality to turn off sata on boot for mx6 devices.
Cc: Stefano Babic sbabic@denx.de Cc: Simon Glass sjg@chromium.org
Nikita Kiryanov (5): arm: mx6: introduce disable_sata_clock sata: implement reset_sata for dwc_ahsata cmd_sata: implement sata stop command arm: mx6: cm_fx6: implement board specific sata stop arm: imx: stop sata on boot
arch/arm/cpu/armv7/mx6/clock.c | 8 ++++++++ arch/arm/cpu/armv7/omap-common/sata.c | 5 +++++ arch/arm/imx-common/cpu.c | 8 ++++++-- arch/arm/include/asm/arch-mx6/clock.h | 1 + board/compulab/cm_fx6/cm_fx6.c | 12 +++++++++--- common/cmd_sata.c | 24 +++++++++++++++++++++++- drivers/block/ata_piix.c | 5 +++++ drivers/block/dwc_ahsata.c | 21 +++++++++++++++++++++ drivers/block/fsl_sata.c | 5 +++++ drivers/block/pata_bfin.c | 5 +++++ drivers/block/sata_dwc.c | 5 +++++ drivers/block/sata_sil.c | 5 +++++ drivers/block/sata_sil3114.c | 5 +++++ include/sata.h | 3 +++ 14 files changed, 106 insertions(+), 6 deletions(-)

Implement disable_sata_clock for mx6 SoCs.
Signed-off-by: Nikita Kiryanov nikita@compulab.co.il Cc: Stefano Babic sbabic@denx.de --- arch/arm/cpu/armv7/mx6/clock.c | 8 ++++++++ arch/arm/include/asm/arch-mx6/clock.h | 1 + 2 files changed, 9 insertions(+)
diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index 6c9c78c..3274a5e 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -596,6 +596,14 @@ int enable_sata_clock(void) ungate_sata_clock(); return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_SATA); } + +void disable_sata_clock(void) +{ + struct mxc_ccm_reg *const imx_ccm = + (struct mxc_ccm_reg *)CCM_BASE_ADDR; + + clrbits_le32(&imx_ccm->CCGR5, MXC_CCM_CCGR5_SATA_MASK); +} #endif
int enable_pcie_clock(void) diff --git a/arch/arm/include/asm/arch-mx6/clock.h b/arch/arm/include/asm/arch-mx6/clock.h index 3c58a0a..ff505ab 100644 --- a/arch/arm/include/asm/arch-mx6/clock.h +++ b/arch/arm/include/asm/arch-mx6/clock.h @@ -60,6 +60,7 @@ void enable_uart_clk(unsigned char enable); int enable_cspi_clock(unsigned char enable, unsigned spi_num); int enable_usdhc_clk(unsigned char enable, unsigned bus_num); int enable_sata_clock(void); +void disable_sata_clock(void); int enable_pcie_clock(void); int enable_i2c_clk(unsigned char enable, unsigned i2c_num); int enable_spi_clk(unsigned char enable, unsigned spi_num);

Add reset_sata() to the sata driver interface and implement it for dwc_ahsata. This function cleans up after sata_init(), and therefore accepts a device number like sata_init() does. A dummy implementation is provided for the rest of the drivers.
Signed-off-by: Nikita Kiryanov nikita@compulab.co.il Cc: Simon Glass sjg@chromium.org Cc: Stefano Babic sbabic@denx.de --- arch/arm/cpu/armv7/omap-common/sata.c | 5 +++++ drivers/block/ata_piix.c | 5 +++++ drivers/block/dwc_ahsata.c | 21 +++++++++++++++++++++ drivers/block/fsl_sata.c | 5 +++++ drivers/block/pata_bfin.c | 5 +++++ drivers/block/sata_dwc.c | 5 +++++ drivers/block/sata_sil.c | 5 +++++ drivers/block/sata_sil3114.c | 5 +++++ include/sata.h | 1 + 9 files changed, 57 insertions(+)
diff --git a/arch/arm/cpu/armv7/omap-common/sata.c b/arch/arm/cpu/armv7/omap-common/sata.c index 3b4dd3f..a24baa1 100644 --- a/arch/arm/cpu/armv7/omap-common/sata.c +++ b/arch/arm/cpu/armv7/omap-common/sata.c @@ -74,6 +74,11 @@ int init_sata(int dev) return ret; }
+int reset_sata(int dev) +{ + return 0; +} + /* On OMAP platforms SATA provides the SCSI subsystem */ void scsi_init(void) { diff --git a/drivers/block/ata_piix.c b/drivers/block/ata_piix.c index 5cf91ad..3042684 100644 --- a/drivers/block/ata_piix.c +++ b/drivers/block/ata_piix.c @@ -192,6 +192,11 @@ int init_sata(int dev) return 0; }
+int reset_sata(int dev) +{ + return 0; +} + static inline u8 sata_inb(unsigned long ioaddr) { return inb(ioaddr); diff --git a/drivers/block/dwc_ahsata.c b/drivers/block/dwc_ahsata.c index c68fd2f..9a2b547 100644 --- a/drivers/block/dwc_ahsata.c +++ b/drivers/block/dwc_ahsata.c @@ -592,6 +592,27 @@ int init_sata(int dev) return 0; }
+int reset_sata(int dev) +{ + struct ahci_probe_ent *probe_ent = + (struct ahci_probe_ent *)sata_dev_desc[dev].priv; + struct sata_host_regs *host_mmio = + (struct sata_host_regs *)probe_ent->mmio_base; + + if (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1)) { + printf("The sata index %d is out of ranges\n\r", dev); + return -1; + } + + setbits_le32(&host_mmio->ghc, SATA_HOST_GHC_HR); + while (readl(&host_mmio->ghc) & SATA_HOST_GHC_HR) + udelay(100); + + disable_sata_clock(); + + return 0; +} + static void dwc_ahsata_print_info(int dev) { block_dev_desc_t *pdev = &(sata_dev_desc[dev]); diff --git a/drivers/block/fsl_sata.c b/drivers/block/fsl_sata.c index ebd6261..71d7cec 100644 --- a/drivers/block/fsl_sata.c +++ b/drivers/block/fsl_sata.c @@ -255,6 +255,11 @@ int init_sata(int dev) return 0; }
+int reset_sata(int dev) +{ + return 0; +} + static void fsl_sata_dump_regs(fsl_sata_reg_t __iomem *reg) { printf("\n\rSATA: %08x\n\r", (u32)reg); diff --git a/drivers/block/pata_bfin.c b/drivers/block/pata_bfin.c index b7fd1cd..c2673bd 100644 --- a/drivers/block/pata_bfin.c +++ b/drivers/block/pata_bfin.c @@ -1009,6 +1009,11 @@ int init_sata(int dev) return res; }
+int reset_sata(int dev) +{ + return 0; +} + /* Read up to 255 sectors * * Returns sectors read diff --git a/drivers/block/sata_dwc.c b/drivers/block/sata_dwc.c index efca5ea..9e8b067 100644 --- a/drivers/block/sata_dwc.c +++ b/drivers/block/sata_dwc.c @@ -423,6 +423,11 @@ int init_sata(int dev) return rc; }
+int reset_sata(int dev) +{ + return 0; +} + static u8 ata_check_altstatus(struct ata_port *ap) { u8 val = 0; diff --git a/drivers/block/sata_sil.c b/drivers/block/sata_sil.c index 1f510cd..ea7d76a 100644 --- a/drivers/block/sata_sil.c +++ b/drivers/block/sata_sil.c @@ -571,6 +571,11 @@ int init_sata(int dev) return 0; }
+int reset_sata(int dev) +{ + return 0; +} + /* * SATA interface between low level driver and command layer */ diff --git a/drivers/block/sata_sil3114.c b/drivers/block/sata_sil3114.c index 3aa6fc9..61ffb66 100644 --- a/drivers/block/sata_sil3114.c +++ b/drivers/block/sata_sil3114.c @@ -702,6 +702,11 @@ int init_sata (int dev) return res; }
+int reset_sata(int dev) +{ + return 0; +} + /* Check if device is connected to port */ int sata_bus_probe (int portno) { diff --git a/include/sata.h b/include/sata.h index 38f4b4a..c2bbe1a 100644 --- a/include/sata.h +++ b/include/sata.h @@ -3,6 +3,7 @@ #include <part.h>
int init_sata(int dev); +int reset_sata(int dev); int scan_sata(int dev); ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer); ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer);

Implement sata stop command. This introduces the __sata_stop() weak function, which mirrors the weak __sata_initialize() function, giving users the option of undoing the custom steps performed in overrides of sata_initialize().
Signed-off-by: Nikita Kiryanov nikita@compulab.co.il Cc: Marek Vasut marex@denx.de Cc: Tom Rini trini@ti.com --- common/cmd_sata.c | 24 +++++++++++++++++++++++- include/sata.h | 2 ++ 2 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/common/cmd_sata.c b/common/cmd_sata.c index fc92131..51f6703 100644 --- a/common/cmd_sata.c +++ b/common/cmd_sata.c @@ -48,6 +48,20 @@ int __sata_initialize(void) } int sata_initialize(void) __attribute__((weak,alias("__sata_initialize")));
+__weak int __sata_stop(void) +{ + int i, err = 0; + + for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) + err |= reset_sata(i); + + if (err) + printf("Could not reset some SATA devices\n"); + + return err; +} +int sata_stop(void) __attribute__((weak, alias("__sata_stop"))); + #ifdef CONFIG_PARTITIONS block_dev_desc_t *sata_get_dev(int dev) { @@ -59,8 +73,15 @@ static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int rc = 0;
- if (argc == 2 && strcmp(argv[1], "init") == 0) + if (argc == 2 && strcmp(argv[1], "stop") == 0) + return sata_stop(); + + if (argc == 2 && strcmp(argv[1], "init") == 0) { + if (sata_curr_device != -1) + sata_stop(); + return sata_initialize(); + }
/* If the user has not yet run `sata init`, do it now */ if (sata_curr_device == -1) @@ -185,6 +206,7 @@ U_BOOT_CMD( sata, 5, 1, do_sata, "SATA sub system", "init - init SATA sub system\n" + "sata stop - disable SATA sub system\n" "sata info - show available SATA devices\n" "sata device [dev] - show or set current device\n" "sata part [dev] - print partition table\n" diff --git a/include/sata.h b/include/sata.h index c2bbe1a..fa61da8 100644 --- a/include/sata.h +++ b/include/sata.h @@ -10,6 +10,8 @@ ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer);
int sata_initialize(void); int __sata_initialize(void); +int sata_stop(void); +int __sata_stop(void); int sata_port_status(int dev, int port);
extern block_dev_desc_t sata_dev_desc[];

Provide board specific implementation for sata stop command for cm_fx6.
Signed-off-by: Nikita Kiryanov nikita@compulab.co.il Cc: Stefano Babic sbabic@denx.de --- board/compulab/cm_fx6/cm_fx6.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/board/compulab/cm_fx6/cm_fx6.c b/board/compulab/cm_fx6/cm_fx6.c index 0206ae8..09e285b 100644 --- a/board/compulab/cm_fx6/cm_fx6.c +++ b/board/compulab/cm_fx6/cm_fx6.c @@ -98,9 +98,6 @@ int sata_initialize(void) /* Make sure this gpio has logical 0 value */ gpio_direction_output(CM_FX6_SATA_PWLOSS_INT, 0); udelay(100); - - cm_fx6_sata_power(0); - mdelay(250); cm_fx6_sata_power(1);
for (i = 0; i < CM_FX6_SATA_INIT_RETRIES; i++) { @@ -125,6 +122,15 @@ int sata_initialize(void)
return err; } + +int sata_stop(void) +{ + __sata_stop(); + cm_fx6_sata_power(0); + mdelay(250); + + return 0; +} #else static int cm_fx6_setup_issd(void) { return 0; } #endif

Ideally, the Linux kernel should get the hardware in its most untouched state. For the most part, U-Boot does not reset the various subsystems it touches before boot, and usually Linux deals with it, but on some boards (cm_fx6) the Linux kernel fails to detect the ssd correctly if sata is used by U-Boot.
Power off sata on OS boot so that Linux will have a clean state to work with.
Signed-off-by: Nikita Kiryanov nikita@compulab.co.il Cc: Stefano Babic sbabic@denx.de --- arch/arm/imx-common/cpu.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/arch/arm/imx-common/cpu.c b/arch/arm/imx-common/cpu.c index 09fc227..794c307 100644 --- a/arch/arm/imx-common/cpu.c +++ b/arch/arm/imx-common/cpu.c @@ -17,6 +17,7 @@ #include <asm/arch/sys_proto.h> #include <asm/arch/crm_regs.h> #include <ipu_pixfmt.h> +#include <sata.h>
#ifdef CONFIG_FSL_ESDHC #include <fsl_esdhc.h> @@ -180,10 +181,13 @@ u32 get_ahb_clk(void) return get_periph_clk() / (ahb_podf + 1); }
-#if defined(CONFIG_VIDEO_IPUV3) void arch_preboot_os(void) { +#if defined(CONFIG_CMD_SATA) + sata_stop(); +#endif +#if defined(CONFIG_VIDEO_IPUV3) /* disable video before launching O/S */ ipuv3_fb_shutdown(); -} #endif +}

On 21/11/2014 11:47, Nikita Kiryanov wrote:
This series adds the sata stop command, which includes both cmd_sata code and driver support for resetting sata. A non-dummy reset_sata() is provided for dwc_ahsata, and a non-default sata_stop() is provided for cm_fx6. Finally, we use the new functionality to turn off sata on boot for mx6 devices.
Cc: Stefano Babic sbabic@denx.de Cc: Simon Glass sjg@chromium.org
Nikita Kiryanov (5): arm: mx6: introduce disable_sata_clock sata: implement reset_sata for dwc_ahsata cmd_sata: implement sata stop command arm: mx6: cm_fx6: implement board specific sata stop arm: imx: stop sata on boot
arch/arm/cpu/armv7/mx6/clock.c | 8 ++++++++ arch/arm/cpu/armv7/omap-common/sata.c | 5 +++++ arch/arm/imx-common/cpu.c | 8 ++++++-- arch/arm/include/asm/arch-mx6/clock.h | 1 + board/compulab/cm_fx6/cm_fx6.c | 12 +++++++++--- common/cmd_sata.c | 24 +++++++++++++++++++++++- drivers/block/ata_piix.c | 5 +++++ drivers/block/dwc_ahsata.c | 21 +++++++++++++++++++++ drivers/block/fsl_sata.c | 5 +++++ drivers/block/pata_bfin.c | 5 +++++ drivers/block/sata_dwc.c | 5 +++++ drivers/block/sata_sil.c | 5 +++++ drivers/block/sata_sil3114.c | 5 +++++ include/sata.h | 3 +++ 14 files changed, 106 insertions(+), 6 deletions(-)
Applied to u-boot-imx, thanks !
Best regards, Stefano Babic
participants (2)
-
Nikita Kiryanov
-
Stefano Babic