uboot/drivers/reset/reset-imx7.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2017, Impinj, Inc.
   4 */
   5
   6#include <log.h>
   7#include <malloc.h>
   8#include <asm/io.h>
   9#include <common.h>
  10#include <dm.h>
  11#include <dt-bindings/reset/imx7-reset.h>
  12#include <dt-bindings/reset/imx8mq-reset.h>
  13#include <reset-uclass.h>
  14#include <linux/bitops.h>
  15#include <linux/delay.h>
  16
  17struct imx7_reset_priv {
  18        void __iomem *base;
  19        struct reset_ops ops;
  20};
  21
  22struct imx7_src_signal {
  23        unsigned int offset, bit;
  24};
  25
  26enum imx7_src_registers {
  27        SRC_A7RCR0              = 0x0004,
  28        SRC_M4RCR               = 0x000c,
  29        SRC_ERCR                = 0x0014,
  30        SRC_HSICPHY_RCR         = 0x001c,
  31        SRC_USBOPHY1_RCR        = 0x0020,
  32        SRC_USBOPHY2_RCR        = 0x0024,
  33        SRC_MIPIPHY_RCR         = 0x0028,
  34        SRC_PCIEPHY_RCR         = 0x002c,
  35        SRC_DDRC_RCR            = 0x1000,
  36};
  37
  38static const struct imx7_src_signal imx7_src_signals[IMX7_RESET_NUM] = {
  39        [IMX7_RESET_A7_CORE_POR_RESET0] = { SRC_A7RCR0, BIT(0) },
  40        [IMX7_RESET_A7_CORE_POR_RESET1] = { SRC_A7RCR0, BIT(1) },
  41        [IMX7_RESET_A7_CORE_RESET0]     = { SRC_A7RCR0, BIT(4) },
  42        [IMX7_RESET_A7_CORE_RESET1]     = { SRC_A7RCR0, BIT(5) },
  43        [IMX7_RESET_A7_DBG_RESET0]      = { SRC_A7RCR0, BIT(8) },
  44        [IMX7_RESET_A7_DBG_RESET1]      = { SRC_A7RCR0, BIT(9) },
  45        [IMX7_RESET_A7_ETM_RESET0]      = { SRC_A7RCR0, BIT(12) },
  46        [IMX7_RESET_A7_ETM_RESET1]      = { SRC_A7RCR0, BIT(13) },
  47        [IMX7_RESET_A7_SOC_DBG_RESET]   = { SRC_A7RCR0, BIT(20) },
  48        [IMX7_RESET_A7_L2RESET]         = { SRC_A7RCR0, BIT(21) },
  49        [IMX7_RESET_SW_M4C_RST]         = { SRC_M4RCR, BIT(1) },
  50        [IMX7_RESET_SW_M4P_RST]         = { SRC_M4RCR, BIT(2) },
  51        [IMX7_RESET_EIM_RST]            = { SRC_ERCR, BIT(0) },
  52        [IMX7_RESET_HSICPHY_PORT_RST]   = { SRC_HSICPHY_RCR, BIT(1) },
  53        [IMX7_RESET_USBPHY1_POR]        = { SRC_USBOPHY1_RCR, BIT(0) },
  54        [IMX7_RESET_USBPHY1_PORT_RST]   = { SRC_USBOPHY1_RCR, BIT(1) },
  55        [IMX7_RESET_USBPHY2_POR]        = { SRC_USBOPHY2_RCR, BIT(0) },
  56        [IMX7_RESET_USBPHY2_PORT_RST]   = { SRC_USBOPHY2_RCR, BIT(1) },
  57        [IMX7_RESET_MIPI_PHY_MRST]      = { SRC_MIPIPHY_RCR, BIT(1) },
  58        [IMX7_RESET_MIPI_PHY_SRST]      = { SRC_MIPIPHY_RCR, BIT(2) },
  59        [IMX7_RESET_PCIEPHY]            = { SRC_PCIEPHY_RCR, BIT(2) | BIT(1) },
  60        [IMX7_RESET_PCIEPHY_PERST]      = { SRC_PCIEPHY_RCR, BIT(3) },
  61        [IMX7_RESET_PCIE_CTRL_APPS_EN]  = { SRC_PCIEPHY_RCR, BIT(6) },
  62        [IMX7_RESET_PCIE_CTRL_APPS_TURNOFF] = { SRC_PCIEPHY_RCR, BIT(11) },
  63        [IMX7_RESET_DDRC_PRST]          = { SRC_DDRC_RCR, BIT(0) },
  64        [IMX7_RESET_DDRC_CORE_RST]      = { SRC_DDRC_RCR, BIT(1) },
  65};
  66
  67static int imx7_reset_deassert_imx7(struct reset_ctl *rst)
  68{
  69        struct imx7_reset_priv *priv = dev_get_priv(rst->dev);
  70        const struct imx7_src_signal *sig = imx7_src_signals;
  71        u32 val;
  72
  73        if (rst->id >= IMX7_RESET_NUM)
  74                return -EINVAL;
  75
  76        if (rst->id == IMX7_RESET_PCIEPHY) {
  77                /*
  78                 * wait for more than 10us to release phy g_rst and
  79                 * btnrst
  80                 */
  81                udelay(10);
  82        }
  83
  84        val = readl(priv->base + sig[rst->id].offset);
  85        switch (rst->id) {
  86        case IMX7_RESET_PCIE_CTRL_APPS_EN:
  87                val |= sig[rst->id].bit;
  88                break;
  89        default:
  90                val &= ~sig[rst->id].bit;
  91                break;
  92        }
  93        writel(val, priv->base + sig[rst->id].offset);
  94
  95        return 0;
  96}
  97
  98static int imx7_reset_assert_imx7(struct reset_ctl *rst)
  99{
 100        struct imx7_reset_priv *priv = dev_get_priv(rst->dev);
 101        const struct imx7_src_signal *sig = imx7_src_signals;
 102        u32 val;
 103
 104        if (rst->id >= IMX7_RESET_NUM)
 105                return -EINVAL;
 106
 107        val = readl(priv->base + sig[rst->id].offset);
 108        switch (rst->id) {
 109        case IMX7_RESET_PCIE_CTRL_APPS_EN:
 110                val &= ~sig[rst->id].bit;
 111                break;
 112        default:
 113                val |= sig[rst->id].bit;
 114                break;
 115        }
 116        writel(val, priv->base + sig[rst->id].offset);
 117
 118        return 0;
 119}
 120
 121enum imx8mq_src_registers {
 122        SRC_A53RCR0             = 0x0004,
 123        SRC_HDMI_RCR            = 0x0030,
 124        SRC_DISP_RCR            = 0x0034,
 125        SRC_GPU_RCR             = 0x0040,
 126        SRC_VPU_RCR             = 0x0044,
 127        SRC_PCIE2_RCR           = 0x0048,
 128        SRC_MIPIPHY1_RCR        = 0x004c,
 129        SRC_MIPIPHY2_RCR        = 0x0050,
 130        SRC_DDRC2_RCR           = 0x1004,
 131};
 132
 133static const struct imx7_src_signal imx8mq_src_signals[IMX8MQ_RESET_NUM] = {
 134        [IMX8MQ_RESET_A53_CORE_POR_RESET0]      = { SRC_A53RCR0, BIT(0) },
 135        [IMX8MQ_RESET_A53_CORE_POR_RESET1]      = { SRC_A53RCR0, BIT(1) },
 136        [IMX8MQ_RESET_A53_CORE_POR_RESET2]      = { SRC_A53RCR0, BIT(2) },
 137        [IMX8MQ_RESET_A53_CORE_POR_RESET3]      = { SRC_A53RCR0, BIT(3) },
 138        [IMX8MQ_RESET_A53_CORE_RESET0]          = { SRC_A53RCR0, BIT(4) },
 139        [IMX8MQ_RESET_A53_CORE_RESET1]          = { SRC_A53RCR0, BIT(5) },
 140        [IMX8MQ_RESET_A53_CORE_RESET2]          = { SRC_A53RCR0, BIT(6) },
 141        [IMX8MQ_RESET_A53_CORE_RESET3]          = { SRC_A53RCR0, BIT(7) },
 142        [IMX8MQ_RESET_A53_DBG_RESET0]           = { SRC_A53RCR0, BIT(8) },
 143        [IMX8MQ_RESET_A53_DBG_RESET1]           = { SRC_A53RCR0, BIT(9) },
 144        [IMX8MQ_RESET_A53_DBG_RESET2]           = { SRC_A53RCR0, BIT(10) },
 145        [IMX8MQ_RESET_A53_DBG_RESET3]           = { SRC_A53RCR0, BIT(11) },
 146        [IMX8MQ_RESET_A53_ETM_RESET0]           = { SRC_A53RCR0, BIT(12) },
 147        [IMX8MQ_RESET_A53_ETM_RESET1]           = { SRC_A53RCR0, BIT(13) },
 148        [IMX8MQ_RESET_A53_ETM_RESET2]           = { SRC_A53RCR0, BIT(14) },
 149        [IMX8MQ_RESET_A53_ETM_RESET3]           = { SRC_A53RCR0, BIT(15) },
 150        [IMX8MQ_RESET_A53_SOC_DBG_RESET]        = { SRC_A53RCR0, BIT(20) },
 151        [IMX8MQ_RESET_A53_L2RESET]              = { SRC_A53RCR0, BIT(21) },
 152        [IMX8MQ_RESET_SW_NON_SCLR_M4C_RST]      = { SRC_M4RCR, BIT(0) },
 153        [IMX8MQ_RESET_OTG1_PHY_RESET]           = { SRC_USBOPHY1_RCR, BIT(0) },
 154        [IMX8MQ_RESET_OTG2_PHY_RESET]           = { SRC_USBOPHY2_RCR, BIT(0) },
 155        [IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N]    = { SRC_MIPIPHY_RCR, BIT(1) },
 156        [IMX8MQ_RESET_MIPI_DSI_RESET_N]         = { SRC_MIPIPHY_RCR, BIT(2) },
 157        [IMX8MQ_RESET_MIPI_DSI_DPI_RESET_N]     = { SRC_MIPIPHY_RCR, BIT(3) },
 158        [IMX8MQ_RESET_MIPI_DSI_ESC_RESET_N]     = { SRC_MIPIPHY_RCR, BIT(4) },
 159        [IMX8MQ_RESET_MIPI_DSI_PCLK_RESET_N]    = { SRC_MIPIPHY_RCR, BIT(5) },
 160        [IMX8MQ_RESET_PCIEPHY]                  = { SRC_PCIEPHY_RCR,
 161                                                    BIT(2) | BIT(1) },
 162        [IMX8MQ_RESET_PCIEPHY_PERST]            = { SRC_PCIEPHY_RCR, BIT(3) },
 163        [IMX8MQ_RESET_PCIE_CTRL_APPS_EN]        = { SRC_PCIEPHY_RCR, BIT(6) },
 164        [IMX8MQ_RESET_PCIE_CTRL_APPS_TURNOFF]   = { SRC_PCIEPHY_RCR, BIT(11) },
 165        [IMX8MQ_RESET_HDMI_PHY_APB_RESET]       = { SRC_HDMI_RCR, BIT(0) },
 166        [IMX8MQ_RESET_DISP_RESET]               = { SRC_DISP_RCR, BIT(0) },
 167        [IMX8MQ_RESET_GPU_RESET]                = { SRC_GPU_RCR, BIT(0) },
 168        [IMX8MQ_RESET_VPU_RESET]                = { SRC_VPU_RCR, BIT(0) },
 169        [IMX8MQ_RESET_PCIEPHY2]                 = { SRC_PCIE2_RCR,
 170                                                    BIT(2) | BIT(1) },
 171        [IMX8MQ_RESET_PCIEPHY2_PERST]           = { SRC_PCIE2_RCR, BIT(3) },
 172        [IMX8MQ_RESET_PCIE2_CTRL_APPS_EN]       = { SRC_PCIE2_RCR, BIT(6) },
 173        [IMX8MQ_RESET_PCIE2_CTRL_APPS_TURNOFF]  = { SRC_PCIE2_RCR, BIT(11) },
 174        [IMX8MQ_RESET_MIPI_CSI1_CORE_RESET]     = { SRC_MIPIPHY1_RCR, BIT(0) },
 175        [IMX8MQ_RESET_MIPI_CSI1_PHY_REF_RESET]  = { SRC_MIPIPHY1_RCR, BIT(1) },
 176        [IMX8MQ_RESET_MIPI_CSI1_ESC_RESET]      = { SRC_MIPIPHY1_RCR, BIT(2) },
 177        [IMX8MQ_RESET_MIPI_CSI2_CORE_RESET]     = { SRC_MIPIPHY2_RCR, BIT(0) },
 178        [IMX8MQ_RESET_MIPI_CSI2_PHY_REF_RESET]  = { SRC_MIPIPHY2_RCR, BIT(1) },
 179        [IMX8MQ_RESET_MIPI_CSI2_ESC_RESET]      = { SRC_MIPIPHY2_RCR, BIT(2) },
 180        [IMX8MQ_RESET_DDRC1_PRST]               = { SRC_DDRC_RCR, BIT(0) },
 181        [IMX8MQ_RESET_DDRC1_CORE_RESET]         = { SRC_DDRC_RCR, BIT(1) },
 182        [IMX8MQ_RESET_DDRC1_PHY_RESET]          = { SRC_DDRC_RCR, BIT(2) },
 183        [IMX8MQ_RESET_DDRC2_PHY_RESET]          = { SRC_DDRC2_RCR, BIT(0) },
 184        [IMX8MQ_RESET_DDRC2_CORE_RESET]         = { SRC_DDRC2_RCR, BIT(1) },
 185        [IMX8MQ_RESET_DDRC2_PRST]               = { SRC_DDRC2_RCR, BIT(2) },
 186};
 187
 188static int imx7_reset_deassert_imx8mq(struct reset_ctl *rst)
 189{
 190        struct imx7_reset_priv *priv = dev_get_priv(rst->dev);
 191        const struct imx7_src_signal *sig = imx8mq_src_signals;
 192        u32 val;
 193
 194        if (rst->id >= IMX8MQ_RESET_NUM)
 195                return -EINVAL;
 196
 197        if (rst->id == IMX8MQ_RESET_PCIEPHY ||
 198            rst->id == IMX8MQ_RESET_PCIEPHY2) {
 199                /*
 200                 * wait for more than 10us to release phy g_rst and
 201                 * btnrst
 202                 */
 203                udelay(10);
 204        }
 205
 206        val = readl(priv->base + sig[rst->id].offset);
 207        switch (rst->id) {
 208        case IMX8MQ_RESET_PCIE_CTRL_APPS_EN:
 209        case IMX8MQ_RESET_PCIE2_CTRL_APPS_EN:   /* fallthrough */
 210        case IMX8MQ_RESET_MIPI_DSI_PCLK_RESET_N:        /* fallthrough */
 211        case IMX8MQ_RESET_MIPI_DSI_ESC_RESET_N: /* fallthrough */
 212        case IMX8MQ_RESET_MIPI_DSI_DPI_RESET_N: /* fallthrough */
 213        case IMX8MQ_RESET_MIPI_DSI_RESET_N:     /* fallthrough */
 214        case IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N:        /* fallthrough */
 215                val |= sig[rst->id].bit;
 216                break;
 217        default:
 218                val &= ~sig[rst->id].bit;
 219                break;
 220        }
 221        writel(val, priv->base + sig[rst->id].offset);
 222
 223        return 0;
 224}
 225
 226static int imx7_reset_assert_imx8mq(struct reset_ctl *rst)
 227{
 228        struct imx7_reset_priv *priv = dev_get_priv(rst->dev);
 229        const struct imx7_src_signal *sig = imx8mq_src_signals;
 230        u32 val;
 231
 232        if (rst->id >= IMX8MQ_RESET_NUM)
 233                return -EINVAL;
 234
 235        val = readl(priv->base + sig[rst->id].offset);
 236        switch (rst->id) {
 237        case IMX8MQ_RESET_PCIE_CTRL_APPS_EN:
 238        case IMX8MQ_RESET_PCIE2_CTRL_APPS_EN:   /* fallthrough */
 239        case IMX8MQ_RESET_MIPI_DSI_PCLK_RESET_N:        /* fallthrough */
 240        case IMX8MQ_RESET_MIPI_DSI_ESC_RESET_N: /* fallthrough */
 241        case IMX8MQ_RESET_MIPI_DSI_DPI_RESET_N: /* fallthrough */
 242        case IMX8MQ_RESET_MIPI_DSI_RESET_N:     /* fallthrough */
 243        case IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N:        /* fallthrough */
 244                val &= ~sig[rst->id].bit;
 245                break;
 246        default:
 247                val |= sig[rst->id].bit;
 248                break;
 249        }
 250        writel(val, priv->base + sig[rst->id].offset);
 251
 252        return 0;
 253}
 254
 255static int imx7_reset_assert(struct reset_ctl *rst)
 256{
 257        struct imx7_reset_priv *priv = dev_get_priv(rst->dev);
 258        return priv->ops.rst_assert(rst);
 259}
 260
 261static int imx7_reset_deassert(struct reset_ctl *rst)
 262{
 263        struct imx7_reset_priv *priv = dev_get_priv(rst->dev);
 264        return priv->ops.rst_deassert(rst);
 265}
 266
 267static int imx7_reset_free(struct reset_ctl *rst)
 268{
 269        return 0;
 270}
 271
 272static int imx7_reset_request(struct reset_ctl *rst)
 273{
 274        return 0;
 275}
 276
 277static const struct reset_ops imx7_reset_reset_ops = {
 278        .request = imx7_reset_request,
 279        .rfree = imx7_reset_free,
 280        .rst_assert = imx7_reset_assert,
 281        .rst_deassert = imx7_reset_deassert,
 282};
 283
 284static const struct udevice_id imx7_reset_ids[] = {
 285        { .compatible = "fsl,imx7d-src" },
 286        { .compatible = "fsl,imx8mq-src" },
 287        { }
 288};
 289
 290static int imx7_reset_probe(struct udevice *dev)
 291{
 292        struct imx7_reset_priv *priv = dev_get_priv(dev);
 293
 294        priv->base = dev_remap_addr(dev);
 295        if (!priv->base)
 296                return -ENOMEM;
 297
 298        if (device_is_compatible(dev, "fsl,imx8mq-src")) {
 299                priv->ops.rst_assert = imx7_reset_assert_imx8mq;
 300                priv->ops.rst_deassert = imx7_reset_deassert_imx8mq;
 301        } else if (device_is_compatible(dev, "fsl,imx7d-src")) {
 302                priv->ops.rst_assert = imx7_reset_assert_imx7;
 303                priv->ops.rst_deassert = imx7_reset_deassert_imx7;
 304        }
 305
 306        return 0;
 307}
 308
 309U_BOOT_DRIVER(imx7_reset) = {
 310        .name = "imx7_reset",
 311        .id = UCLASS_RESET,
 312        .of_match = imx7_reset_ids,
 313        .ops = &imx7_reset_reset_ops,
 314        .probe = imx7_reset_probe,
 315        .priv_auto_alloc_size = sizeof(struct imx7_reset_priv),
 316};
 317