
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 --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; +}