diff mbox series

[U-Boot,29/41] sata: Add i.MX8 SATA support

Message ID 20180528122526.20597-30-peng.fan@nxp.com
State Superseded
Delegated to: Stefano Babic
Headers show
Series imx: add i.MX8QXP support | expand

Commit Message

Peng Fan May 28, 2018, 12:25 p.m. UTC
From: Ye Li <ye.li@nxp.com>

- some delay is required between SATA_CTRL0 RST SET and CLR.
  Otherwise, sata phy link would be down.
- specific the ahci modification by imx8qm platform.

Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
Signed-off-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/ata/Kconfig    |  6 +++++
 drivers/ata/Makefile   |  1 +
 drivers/ata/ahci.c     | 25 ++++++++++++++++++++
 drivers/ata/sata_imx.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 96 insertions(+)
 create mode 100644 drivers/ata/sata_imx.c
diff mbox series

Patch

diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 86ec628104..30fa9a2f02 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -79,6 +79,12 @@  config MVSATA_IDE
 	  Enable this driver to support the SATA controller found in
 	  some Marvell SoCs, running in IDE compatibility mode using PIO.
 
+config SATA_IMX
+	bool "Enable SATA driver support for i.MX8QM"
+	select LIBATA
+	help
+	  Enable this driver to support the SATA controller found in i.MX8QM SoCs.
+
 config SATA_MV
 	bool "Enable Marvell SATA controller driver support"
 	select LIBATA
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 02f02c8e8d..da2634c3a4 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -13,6 +13,7 @@  obj-$(CONFIG_LIBATA) += libata.o
 obj-$(CONFIG_MVSATA_IDE) += mvsata_ide.o
 obj-$(CONFIG_SATA) += sata.o
 obj-$(CONFIG_SATA_CEVA) += sata_ceva.o
+obj-$(CONFIG_SATA_IMX) += sata_imx.o
 obj-$(CONFIG_SATA_MV) += sata_mv.o
 obj-$(CONFIG_SATA_SIL3114) += sata_sil3114.o
 obj-$(CONFIG_SATA_SIL) += sata_sil.o
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index c35912bd33..39ae494c34 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -26,6 +26,16 @@ 
 #include <dm/device-internal.h>
 #include <dm/lists.h>
 
+#ifdef CONFIG_SCSI_AHCI_PLAT
+#ifdef CONFIG_FSL_HSIO
+#define HW_PP2C		0xAC
+#define HW_PP3C		0xB0
+#define HW_PP4C		0xB4
+#define HW_PP5C		0xB8
+#define HW_PAXIC	0xC0
+#endif
+#endif
+
 static int ata_io_flush(struct ahci_uc_priv *uc_priv, u8 port);
 
 #ifndef CONFIG_DM_SCSI
@@ -191,6 +201,16 @@  static int ahci_host_init(struct ahci_uc_priv *uc_priv)
 
 	debug("ahci_host_init: start\n");
 
+#ifdef CONFIG_SCSI_AHCI_PLAT
+#ifdef CONFIG_FSL_HSIO
+	writel((1 << 28) | (1 << 24) | readl(mmio + HW_PAXIC), mmio + HW_PAXIC);
+	writel(0x2718461C, mmio + HW_PP2C);
+	writel(0x0D081907, mmio + HW_PP3C);
+	writel(0x06000815, mmio + HW_PP4C);
+	writel(0x800C96A4, mmio + HW_PP5C);
+#endif
+#endif
+
 	cap_save = readl(mmio + HOST_CAP);
 	cap_save &= ((1 << 28) | (1 << 17));
 	cap_save |= (1 << 27);  /* Staggered Spin-up. Not needed. */
@@ -270,6 +290,11 @@  static int ahci_host_init(struct ahci_uc_priv *uc_priv)
 		ret = ahci_link_up(uc_priv, i);
 		if (ret) {
 			printf("SATA link %d timeout.\n", i);
+#ifdef CONFIG_SCSI_AHCI_PLAT
+#ifdef CONFIG_FSL_HSIO
+			return -ENODEV;
+#endif
+#endif
 			continue;
 		} else {
 			debug("SATA link ok.\n");
diff --git a/drivers/ata/sata_imx.c b/drivers/ata/sata_imx.c
new file mode 100644
index 0000000000..90293a6e49
--- /dev/null
+++ b/drivers/ata/sata_imx.c
@@ -0,0 +1,64 @@ 
+/*
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/mach-imx/sci/sci.h>
+#include <ahci.h>
+#include <scsi.h>
+#include <imx8_hsio.h>
+
+int sata_init(void)
+{
+	int ret;
+	u32 val, i = 0;
+
+	printf("start sata init\n");
+	writel(0x22222222, GPR_LPCG_PHYX2APB_0_APB);
+	writel(0x22222222, GPR_LPCG_PHYX1_APB);
+
+	setbits_le32(0x5F130008, BIT(21));
+	setbits_le32(0x5F130008, BIT(23));
+
+	/* PHY_MODE to SATA100Mhz ref clk */
+	setbits_le32(HW_PHYX1_CTRL0_ADDR, BIT(19));
+
+	/*
+	 * bit 0 rx ena, bit 1 tx ena, bit 11 fast_init,
+	 * bit12 PHY_X1_EPCS_SEL 1.
+	 */
+	setbits_le32(HW_MISC_CTRL0_ADDR, HW_MISC_CTRL0_IOB_RXENA
+		     | HW_MISC_CTRL0_PHY_X1_EPCS_SEL);
+
+	clrbits_le32(HW_SATA_CTRL0_ADDR, HW_SATA_CTRL0_PHY_RESET);
+	setbits_le32(HW_SATA_CTRL0_ADDR, HW_SATA_CTRL0_PHY_RESET);
+	setbits_le32(HW_SATA_CTRL0_ADDR, HW_SATA_CTRL0_RESET);
+	udelay(1);
+	clrbits_le32(HW_SATA_CTRL0_ADDR, HW_SATA_CTRL0_RESET);
+	setbits_le32(HW_SATA_CTRL0_ADDR, HW_SATA_CTRL0_RESET);
+
+	setbits_le32(HW_PHYX1_CTRL0_ADDR, HW_PHYX1_CTRL0_APB_RSTN);
+
+	for (i = 0; i < 100; i++) {
+		val = readl(HW_PHYX1_STTS0_ADDR);
+		val &= HW_PHYX1_STTS0_LANE0_TX_PLL_LOCK;
+		if (val == HW_PHYX1_STTS0_LANE0_TX_PLL_LOCK)
+			break;
+		udelay(1);
+	}
+
+	if (val != HW_PHYX1_STTS0_LANE0_TX_PLL_LOCK) {
+		printf("TX PLL is not locked.\n");
+		return -ENODEV;
+	}
+
+	ret = ahci_init((void __iomem *)AHCI_BASE_ADDR);
+	if (ret)
+		return ret;
+	scsi_scan(1);
+
+	return 0;
+}