Skip to contentSkip to conversation

introduce sata stop

PATCH New Nikita Kiryanov 2 participants 7 messages Nov 21, 2014 – Nov 24, 2014

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover 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 <[email protected]>
Cc Simon Glass <[email protected]>

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(-)
Signature · 1 line
1.9.1
#1 lore raw

PATCH 1/5 arm: mx6: introduce disable_sata_clock

Implement disable_sata_clock for mx6 SoCs.

---
 arch/arm/cpu/armv7/mx6/clock.c        | 8 ++++++++
 arch/arm/include/asm/arch-mx6/clock.h | 1 +
 2 files changed, 9 insertions(+)
arch/arm/cpu/armv7/mx6/clock.c +8 -0
index 6c9c78c..3274a5e 100644
@@ -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)
arch/arm/include/asm/arch-mx6/clock.h +1 -0
index 3c58a0a..ff505ab 100644
@@ -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);
Signature · 1 line
1.9.1
#2 lore raw

PATCH 2/5 sata: implement reset_sata for dwc_ahsata

In reply to Nikita Kiryanov

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.

Cc Simon Glass <[email protected]>
Cc Stefano Babic <[email protected]>
---
 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(+)
arch/arm/cpu/armv7/omap-common/sata.c +5 -0
index 3b4dd3f..a24baa1 100644
@@ -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)
 {
drivers/block/ata_piix.c +5 -0
index 5cf91ad..3042684 100644
@@ -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);
drivers/block/dwc_ahsata.c +21 -0
index c68fd2f..9a2b547 100644
@@ -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]);
drivers/block/fsl_sata.c +5 -0
index ebd6261..71d7cec 100644
@@ -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);
drivers/block/pata_bfin.c +5 -0
index b7fd1cd..c2673bd 100644
@@ -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
drivers/block/sata_dwc.c +5 -0
index efca5ea..9e8b067 100644
@@ -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;
drivers/block/sata_sil.c +5 -0
index 1f510cd..ea7d76a 100644
@@ -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
  */
drivers/block/sata_sil3114.c +5 -0
index 3aa6fc9..61ffb66 100644
@@ -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)
 {
include/sata.h +1 -0
index 38f4b4a..c2bbe1a 100644
@@ -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);
Signature · 1 line
1.9.1
#3 lore raw

PATCH 3/5 cmd_sata: implement sata stop command

In reply to Nikita Kiryanov

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().

---
 common/cmd_sata.c | 24 +++++++++++++++++++++++-
 include/sata.h    |  2 ++
 2 files changed, 25 insertions(+), 1 deletion(-)
common/cmd_sata.c +23 -1
index fc92131..51f6703 100644
@@ -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"
include/sata.h +2 -0
index c2bbe1a..fa61da8 100644
@@ -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[];
Signature · 1 line
1.9.1
#4 lore raw

PATCH 4/5 arm: mx6: cm_fx6: implement board specific sata stop

In reply to Nikita Kiryanov

Provide board specific implementation for sata stop command for cm_fx6.

---
 board/compulab/cm_fx6/cm_fx6.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)
board/compulab/cm_fx6/cm_fx6.c +9 -3
index 0206ae8..09e285b 100644
@@ -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
Signature · 1 line
1.9.1
#5 lore raw

PATCH 5/5 arm: imx: stop sata on boot

In reply to Nikita Kiryanov

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.

---
 arch/arm/imx-common/cpu.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
arch/arm/imx-common/cpu.c +6 -2
index 09fc227..794c307 100644
@@ -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
+}
Signature · 1 line
1.9.1
#6 lore raw

cover introduce sata stop

In reply to Nikita Kiryanov
Quoted 16 lines · Nikita Kiryanov

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 <[email protected]>
Cc Simon Glass <[email protected]>

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

Quoted 16 lines
 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

Signature · 5 lines
=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================