From a295bd86be24b929df1b7ac40b1fbec9f827a458 Mon Sep 17 00:00:00 2001 From: Sumit Garg Date: Thu, 21 Mar 2024 20:24:59 +0530 Subject: [PATCH] reset: imx: Add support for i.MX8MP reset controller Add support for i.MX8MP reset controller, it has same reset IP inside as the other iMX7 and iMX8M variants but with different module layout. Inspired from counterpart Linux kernel v6.8-rc3 driver: drivers/reset/reset-imx7.c. Use last Linux kernel driver reference commit bad8a8afe19f ("reset: Explicitly include correct DT includes"). Tested-by: Tim Harvey #imx8mp-venice* Tested-by: Adam Ford #imx8mp-beacon-kit Reviewed-by: Marek Vasut Signed-off-by: Sumit Garg --- drivers/reset/reset-imx7.c | 101 +++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/drivers/reset/reset-imx7.c b/drivers/reset/reset-imx7.c index ca703466605..a3b3132f2fa 100644 --- a/drivers/reset/reset-imx7.c +++ b/drivers/reset/reset-imx7.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -252,6 +253,102 @@ static int imx8mq_reset_assert(struct reset_ctl *rst) return 0; } +enum imx8mp_src_registers { + SRC_SUPERMIX_RCR = 0x0018, + SRC_AUDIOMIX_RCR = 0x001c, + SRC_MLMIX_RCR = 0x0028, + SRC_GPU2D_RCR = 0x0038, + SRC_GPU3D_RCR = 0x003c, + SRC_VPU_G1_RCR = 0x0048, + SRC_VPU_G2_RCR = 0x004c, + SRC_VPUVC8KE_RCR = 0x0050, + SRC_NOC_RCR = 0x0054, +}; + +static const struct imx7_src_signal imx8mp_src_signals[IMX8MP_RESET_NUM] = { + [IMX8MP_RESET_A53_CORE_POR_RESET0] = { SRC_A53RCR0, BIT(0) }, + [IMX8MP_RESET_A53_CORE_POR_RESET1] = { SRC_A53RCR0, BIT(1) }, + [IMX8MP_RESET_A53_CORE_POR_RESET2] = { SRC_A53RCR0, BIT(2) }, + [IMX8MP_RESET_A53_CORE_POR_RESET3] = { SRC_A53RCR0, BIT(3) }, + [IMX8MP_RESET_A53_CORE_RESET0] = { SRC_A53RCR0, BIT(4) }, + [IMX8MP_RESET_A53_CORE_RESET1] = { SRC_A53RCR0, BIT(5) }, + [IMX8MP_RESET_A53_CORE_RESET2] = { SRC_A53RCR0, BIT(6) }, + [IMX8MP_RESET_A53_CORE_RESET3] = { SRC_A53RCR0, BIT(7) }, + [IMX8MP_RESET_A53_DBG_RESET0] = { SRC_A53RCR0, BIT(8) }, + [IMX8MP_RESET_A53_DBG_RESET1] = { SRC_A53RCR0, BIT(9) }, + [IMX8MP_RESET_A53_DBG_RESET2] = { SRC_A53RCR0, BIT(10) }, + [IMX8MP_RESET_A53_DBG_RESET3] = { SRC_A53RCR0, BIT(11) }, + [IMX8MP_RESET_A53_ETM_RESET0] = { SRC_A53RCR0, BIT(12) }, + [IMX8MP_RESET_A53_ETM_RESET1] = { SRC_A53RCR0, BIT(13) }, + [IMX8MP_RESET_A53_ETM_RESET2] = { SRC_A53RCR0, BIT(14) }, + [IMX8MP_RESET_A53_ETM_RESET3] = { SRC_A53RCR0, BIT(15) }, + [IMX8MP_RESET_A53_SOC_DBG_RESET] = { SRC_A53RCR0, BIT(20) }, + [IMX8MP_RESET_A53_L2RESET] = { SRC_A53RCR0, BIT(21) }, + [IMX8MP_RESET_SW_NON_SCLR_M7C_RST] = { SRC_M4RCR, BIT(0) }, + [IMX8MP_RESET_OTG1_PHY_RESET] = { SRC_USBOPHY1_RCR, BIT(0) }, + [IMX8MP_RESET_OTG2_PHY_RESET] = { SRC_USBOPHY2_RCR, BIT(0) }, + [IMX8MP_RESET_SUPERMIX_RESET] = { SRC_SUPERMIX_RCR, BIT(0) }, + [IMX8MP_RESET_AUDIOMIX_RESET] = { SRC_AUDIOMIX_RCR, BIT(0) }, + [IMX8MP_RESET_MLMIX_RESET] = { SRC_MLMIX_RCR, BIT(0) }, + [IMX8MP_RESET_PCIEPHY] = { SRC_PCIEPHY_RCR, BIT(2) }, + [IMX8MP_RESET_PCIEPHY_PERST] = { SRC_PCIEPHY_RCR, BIT(3) }, + [IMX8MP_RESET_PCIE_CTRL_APPS_EN] = { SRC_PCIEPHY_RCR, BIT(6) }, + [IMX8MP_RESET_PCIE_CTRL_APPS_TURNOFF] = { SRC_PCIEPHY_RCR, BIT(11) }, + [IMX8MP_RESET_HDMI_PHY_APB_RESET] = { SRC_HDMI_RCR, BIT(0) }, + [IMX8MP_RESET_MEDIA_RESET] = { SRC_DISP_RCR, BIT(0) }, + [IMX8MP_RESET_GPU2D_RESET] = { SRC_GPU2D_RCR, BIT(0) }, + [IMX8MP_RESET_GPU3D_RESET] = { SRC_GPU3D_RCR, BIT(0) }, + [IMX8MP_RESET_GPU_RESET] = { SRC_GPU_RCR, BIT(0) }, + [IMX8MP_RESET_VPU_RESET] = { SRC_VPU_RCR, BIT(0) }, + [IMX8MP_RESET_VPU_G1_RESET] = { SRC_VPU_G1_RCR, BIT(0) }, + [IMX8MP_RESET_VPU_G2_RESET] = { SRC_VPU_G2_RCR, BIT(0) }, + [IMX8MP_RESET_VPUVC8KE_RESET] = { SRC_VPUVC8KE_RCR, BIT(0) }, + [IMX8MP_RESET_NOC_RESET] = { SRC_NOC_RCR, BIT(0) }, +}; + +static int imx8mp_reset_set(struct reset_ctl *rst, bool assert) +{ + struct imx_reset_priv *priv = dev_get_priv(rst->dev); + unsigned int bit, value; + + if (rst->id >= IMX8MP_RESET_NUM) + return -EINVAL; + + bit = imx8mp_src_signals[rst->id].bit; + value = assert ? bit : 0; + + switch (rst->id) { + case IMX8MP_RESET_PCIEPHY: + /* + * wait for more than 10us to release phy g_rst and + * btnrst + */ + if (!assert) + udelay(10); + break; + + case IMX8MP_RESET_PCIE_CTRL_APPS_EN: + case IMX8MP_RESET_PCIEPHY_PERST: + value = assert ? 0 : bit; + break; + } + + clrsetbits_le32(priv->base + imx8mp_src_signals[rst->id].offset, bit, + value); + + return 0; +} + +static int imx8mp_reset_assert(struct reset_ctl *rst) +{ + return imx8mp_reset_set(rst, true); +} + +static int imx8mp_reset_deassert(struct reset_ctl *rst) +{ + return imx8mp_reset_set(rst, false); +} + static int imx_reset_assert(struct reset_ctl *rst) { struct imx_reset_priv *priv = dev_get_priv(rst->dev); @@ -272,6 +369,7 @@ static const struct reset_ops imx7_reset_reset_ops = { static const struct udevice_id imx7_reset_ids[] = { { .compatible = "fsl,imx7d-src" }, { .compatible = "fsl,imx8mq-src" }, + { .compatible = "fsl,imx8mp-src" }, { } }; @@ -289,6 +387,9 @@ static int imx7_reset_probe(struct udevice *dev) } else if (device_is_compatible(dev, "fsl,imx7d-src")) { priv->ops.rst_assert = imx7_reset_assert; priv->ops.rst_deassert = imx7_reset_deassert; + } else if (device_is_compatible(dev, "fsl,imx8mp-src")) { + priv->ops.rst_assert = imx8mp_reset_assert; + priv->ops.rst_deassert = imx8mp_reset_deassert; } return 0;