1
0
Fork 0

ahci: imx: add the imx6qp ahci sata support

- Regarding to imx6q ahci sata, imx6qp ahci sata
has the reset mechanism. Add the imx6qp ahci sata
support in this commit.
- Use the specific reset callback for imx53 sata,
and use the default ahci_ops.softreset for the others.

Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
hifive-unleashed-5.1
Richard Zhu 2018-03-19 10:02:18 +08:00 committed by Tejun Heo
parent 34d232eb2d
commit e5878732a5
3 changed files with 35 additions and 4 deletions

View File

@ -7,6 +7,7 @@ Required properties:
- compatible : should be one of the following: - compatible : should be one of the following:
- "fsl,imx53-ahci" for i.MX53 SATA controller - "fsl,imx53-ahci" for i.MX53 SATA controller
- "fsl,imx6q-ahci" for i.MX6Q SATA controller - "fsl,imx6q-ahci" for i.MX6Q SATA controller
- "fsl,imx6qp-ahci" for i.MX6QP SATA controller
- interrupts : interrupt mapping for SATA IRQ - interrupts : interrupt mapping for SATA IRQ
- reg : registers mapping - reg : registers mapping
- clocks : list of clock specifiers, must contain an entry for each - clocks : list of clock specifiers, must contain an entry for each

View File

@ -58,6 +58,7 @@ enum {
enum ahci_imx_type { enum ahci_imx_type {
AHCI_IMX53, AHCI_IMX53,
AHCI_IMX6Q, AHCI_IMX6Q,
AHCI_IMX6QP,
}; };
struct imx_ahci_priv { struct imx_ahci_priv {
@ -188,11 +189,26 @@ static int imx_phy_reg_read(u16 *val, void __iomem *mmio)
static int imx_sata_phy_reset(struct ahci_host_priv *hpriv) static int imx_sata_phy_reset(struct ahci_host_priv *hpriv)
{ {
struct imx_ahci_priv *imxpriv = hpriv->plat_data;
void __iomem *mmio = hpriv->mmio; void __iomem *mmio = hpriv->mmio;
int timeout = 10; int timeout = 10;
u16 val; u16 val;
int ret; int ret;
if (imxpriv->type == AHCI_IMX6QP) {
/* 6qp adds the sata reset mechanism, use it for 6qp sata */
regmap_update_bits(imxpriv->gpr, IOMUXC_GPR5,
IMX6Q_GPR5_SATA_SW_PD, 0);
regmap_update_bits(imxpriv->gpr, IOMUXC_GPR5,
IMX6Q_GPR5_SATA_SW_RST, 0);
udelay(50);
regmap_update_bits(imxpriv->gpr, IOMUXC_GPR5,
IMX6Q_GPR5_SATA_SW_RST,
IMX6Q_GPR5_SATA_SW_RST);
return 0;
}
/* Reset SATA PHY by setting RESET bit of PHY register CLOCK_RESET */ /* Reset SATA PHY by setting RESET bit of PHY register CLOCK_RESET */
ret = imx_phy_reg_addressing(IMX_CLOCK_RESET, mmio); ret = imx_phy_reg_addressing(IMX_CLOCK_RESET, mmio);
if (ret) if (ret)
@ -408,7 +424,7 @@ static int imx_sata_enable(struct ahci_host_priv *hpriv)
if (ret < 0) if (ret < 0)
goto disable_regulator; goto disable_regulator;
if (imxpriv->type == AHCI_IMX6Q) { if (imxpriv->type == AHCI_IMX6Q || imxpriv->type == AHCI_IMX6QP) {
/* /*
* set PHY Paremeters, two steps to configure the GPR13, * set PHY Paremeters, two steps to configure the GPR13,
* one write for rest of parameters, mask of first write * one write for rest of parameters, mask of first write
@ -459,10 +475,21 @@ static void imx_sata_disable(struct ahci_host_priv *hpriv)
if (imxpriv->no_device) if (imxpriv->no_device)
return; return;
if (imxpriv->type == AHCI_IMX6Q) { switch (imxpriv->type) {
case AHCI_IMX6QP:
regmap_update_bits(imxpriv->gpr, IOMUXC_GPR5,
IMX6Q_GPR5_SATA_SW_PD,
IMX6Q_GPR5_SATA_SW_PD);
regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
IMX6Q_GPR13_SATA_MPLL_CLK_EN, IMX6Q_GPR13_SATA_MPLL_CLK_EN,
!IMX6Q_GPR13_SATA_MPLL_CLK_EN); !IMX6Q_GPR13_SATA_MPLL_CLK_EN);
break;
case AHCI_IMX6Q:
regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
IMX6Q_GPR13_SATA_MPLL_CLK_EN,
!IMX6Q_GPR13_SATA_MPLL_CLK_EN);
break;
} }
clk_disable_unprepare(imxpriv->sata_ref_clk); clk_disable_unprepare(imxpriv->sata_ref_clk);
@ -513,7 +540,7 @@ static int ahci_imx_softreset(struct ata_link *link, unsigned int *class,
if (imxpriv->type == AHCI_IMX53) if (imxpriv->type == AHCI_IMX53)
ret = ahci_pmp_retry_srst_ops.softreset(link, class, deadline); ret = ahci_pmp_retry_srst_ops.softreset(link, class, deadline);
else if (imxpriv->type == AHCI_IMX6Q) else
ret = ahci_ops.softreset(link, class, deadline); ret = ahci_ops.softreset(link, class, deadline);
return ret; return ret;
@ -536,6 +563,7 @@ static const struct ata_port_info ahci_imx_port_info = {
static const struct of_device_id imx_ahci_of_match[] = { static const struct of_device_id imx_ahci_of_match[] = {
{ .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 }, { .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 },
{ .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q }, { .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q },
{ .compatible = "fsl,imx6qp-ahci", .data = (void *)AHCI_IMX6QP },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, imx_ahci_of_match); MODULE_DEVICE_TABLE(of, imx_ahci_of_match);
@ -743,7 +771,7 @@ static int imx_ahci_probe(struct platform_device *pdev)
return PTR_ERR(imxpriv->ahb_clk); return PTR_ERR(imxpriv->ahb_clk);
} }
if (imxpriv->type == AHCI_IMX6Q) { if (imxpriv->type == AHCI_IMX6Q || imxpriv->type == AHCI_IMX6QP) {
u32 reg_value; u32 reg_value;
imxpriv->gpr = syscon_regmap_lookup_by_compatible( imxpriv->gpr = syscon_regmap_lookup_by_compatible(

View File

@ -243,6 +243,8 @@
#define IMX6Q_GPR4_IPU_RD_CACHE_CTL BIT(0) #define IMX6Q_GPR4_IPU_RD_CACHE_CTL BIT(0)
#define IMX6Q_GPR5_L2_CLK_STOP BIT(8) #define IMX6Q_GPR5_L2_CLK_STOP BIT(8)
#define IMX6Q_GPR5_SATA_SW_PD BIT(10)
#define IMX6Q_GPR5_SATA_SW_RST BIT(11)
#define IMX6Q_GPR6_IPU1_ID00_WR_QOS_MASK (0xf << 0) #define IMX6Q_GPR6_IPU1_ID00_WR_QOS_MASK (0xf << 0)
#define IMX6Q_GPR6_IPU1_ID01_WR_QOS_MASK (0xf << 4) #define IMX6Q_GPR6_IPU1_ID01_WR_QOS_MASK (0xf << 4)