Commit 4fb96c48c183128c00b21c7858bb05897a1b80de

Authored by Masahiro Yamada
1 parent d9f5d99245

reset: uniphier: add reset controller driver for UniPhier SoCs

This is the initial commit for UniPhier reset controller driver.
Most code was ported from Linux.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>

Showing 4 changed files with 387 additions and 0 deletions Side-by-side Diff

... ... @@ -817,6 +817,7 @@
817 817 select DM_GPIO
818 818 select DM_I2C
819 819 select DM_MMC
  820 + select DM_RESET
820 821 select DM_SERIAL
821 822 select DM_USB
822 823 select OF_CONTROL
drivers/reset/Kconfig
... ... @@ -34,5 +34,14 @@
34 34 Enable support for manipulating Tegra's on-SoC reset signals via IPC
35 35 requests to the BPMP (Boot and Power Management Processor).
36 36  
  37 +config RESET_UNIPHIER
  38 + bool "Reset controller driver for UniPhier SoCs"
  39 + depends on ARCH_UNIPHIER
  40 + default y
  41 + help
  42 + Support for reset controllers on UniPhier SoCs.
  43 + Say Y if you want to control reset signals provided by System Control
  44 + block, Media I/O block, Peripheral Block.
  45 +
37 46 endmenu
drivers/reset/Makefile
... ... @@ -7,4 +7,5 @@
7 7 obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset-test.o
8 8 obj-$(CONFIG_TEGRA_CAR_RESET) += tegra-car-reset.o
9 9 obj-$(CONFIG_TEGRA186_RESET) += tegra186-reset.o
  10 +obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
drivers/reset/reset-uniphier.c
  1 +/*
  2 + * Copyright (C) 2016 Socionext Inc.
  3 + * Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  4 + *
  5 + * SPDX-License-Identifier: GPL-2.0+
  6 + */
  7 +
  8 +#include <common.h>
  9 +#include <reset-uclass.h>
  10 +#include <dm/device.h>
  11 +#include <linux/bitops.h>
  12 +#include <linux/io.h>
  13 +#include <linux/sizes.h>
  14 +
  15 +struct uniphier_reset_data {
  16 + unsigned int id;
  17 + unsigned int reg;
  18 + unsigned int bit;
  19 + unsigned int flags;
  20 +#define UNIPHIER_RESET_ACTIVE_LOW BIT(0)
  21 +};
  22 +
  23 +#define UNIPHIER_RESET_ID_END (unsigned int)(-1)
  24 +
  25 +#define UNIPHIER_RESET_END \
  26 + { .id = UNIPHIER_RESET_ID_END }
  27 +
  28 +#define UNIPHIER_RESET(_id, _reg, _bit) \
  29 + { \
  30 + .id = (_id), \
  31 + .reg = (_reg), \
  32 + .bit = (_bit), \
  33 + }
  34 +
  35 +#define UNIPHIER_RESETX(_id, _reg, _bit) \
  36 + { \
  37 + .id = (_id), \
  38 + .reg = (_reg), \
  39 + .bit = (_bit), \
  40 + .flags = UNIPHIER_RESET_ACTIVE_LOW, \
  41 + }
  42 +
  43 +/* System reset data */
  44 +#define UNIPHIER_SLD3_SYS_RESET_STDMAC(id) \
  45 + UNIPHIER_RESETX((id), 0x2000, 10)
  46 +
  47 +#define UNIPHIER_LD11_SYS_RESET_STDMAC(id) \
  48 + UNIPHIER_RESETX((id), 0x200c, 8)
  49 +
  50 +#define UNIPHIER_PRO4_SYS_RESET_GIO(id) \
  51 + UNIPHIER_RESETX((id), 0x2000, 6)
  52 +
  53 +#define UNIPHIER_LD20_SYS_RESET_GIO(id) \
  54 + UNIPHIER_RESETX((id), 0x200c, 5)
  55 +
  56 +#define UNIPHIER_PRO4_SYS_RESET_USB3(id, ch) \
  57 + UNIPHIER_RESETX((id), 0x2000 + 0x4 * (ch), 17)
  58 +
  59 +const struct uniphier_reset_data uniphier_sld3_sys_reset_data[] = {
  60 + UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* Ether, HSC, MIO */
  61 + UNIPHIER_RESET_END,
  62 +};
  63 +
  64 +const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
  65 + UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, MIO, RLE */
  66 + UNIPHIER_PRO4_SYS_RESET_GIO(12), /* Ether, SATA, USB3 */
  67 + UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
  68 + UNIPHIER_PRO4_SYS_RESET_USB3(15, 1),
  69 + UNIPHIER_RESET_END,
  70 +};
  71 +
  72 +const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = {
  73 + UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC */
  74 + UNIPHIER_PRO4_SYS_RESET_GIO(12), /* PCIe, USB3 */
  75 + UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
  76 + UNIPHIER_PRO4_SYS_RESET_USB3(15, 1),
  77 + UNIPHIER_RESET_END,
  78 +};
  79 +
  80 +const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
  81 + UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, RLE */
  82 + UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
  83 + UNIPHIER_PRO4_SYS_RESET_USB3(15, 1),
  84 + UNIPHIER_RESETX(16, 0x2014, 4), /* USB30-PHY0 */
  85 + UNIPHIER_RESETX(17, 0x2014, 0), /* USB30-PHY1 */
  86 + UNIPHIER_RESETX(18, 0x2014, 2), /* USB30-PHY2 */
  87 + UNIPHIER_RESETX(20, 0x2014, 5), /* USB31-PHY0 */
  88 + UNIPHIER_RESETX(21, 0x2014, 1), /* USB31-PHY1 */
  89 + UNIPHIER_RESETX(28, 0x2014, 12), /* SATA */
  90 + UNIPHIER_RESET(29, 0x2014, 8), /* SATA-PHY (active high) */
  91 + UNIPHIER_RESET_END,
  92 +};
  93 +
  94 +const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = {
  95 + UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC, MIO */
  96 + UNIPHIER_RESET_END,
  97 +};
  98 +
  99 +const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
  100 + UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC */
  101 + UNIPHIER_LD20_SYS_RESET_GIO(12), /* PCIe, USB3 */
  102 + UNIPHIER_RESETX(16, 0x200c, 12), /* USB30-PHY0 */
  103 + UNIPHIER_RESETX(17, 0x200c, 13), /* USB30-PHY1 */
  104 + UNIPHIER_RESETX(18, 0x200c, 14), /* USB30-PHY2 */
  105 + UNIPHIER_RESETX(19, 0x200c, 15), /* USB30-PHY3 */
  106 + UNIPHIER_RESET_END,
  107 +};
  108 +
  109 +/* Media I/O reset data */
  110 +#define UNIPHIER_MIO_RESET_SD(id, ch) \
  111 + UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 0)
  112 +
  113 +#define UNIPHIER_MIO_RESET_SD_BRIDGE(id, ch) \
  114 + UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 26)
  115 +
  116 +#define UNIPHIER_MIO_RESET_EMMC_HW_RESET(id, ch) \
  117 + UNIPHIER_RESETX((id), 0x80 + 0x200 * (ch), 0)
  118 +
  119 +#define UNIPHIER_MIO_RESET_USB2(id, ch) \
  120 + UNIPHIER_RESETX((id), 0x114 + 0x200 * (ch), 0)
  121 +
  122 +#define UNIPHIER_MIO_RESET_USB2_BRIDGE(id, ch) \
  123 + UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 24)
  124 +
  125 +#define UNIPHIER_MIO_RESET_DMAC(id) \
  126 + UNIPHIER_RESETX((id), 0x110, 17)
  127 +
  128 +const struct uniphier_reset_data uniphier_mio_reset_data[] = {
  129 + UNIPHIER_MIO_RESET_SD(0, 0),
  130 + UNIPHIER_MIO_RESET_SD(1, 1),
  131 + UNIPHIER_MIO_RESET_SD(2, 2),
  132 + UNIPHIER_MIO_RESET_SD_BRIDGE(3, 0),
  133 + UNIPHIER_MIO_RESET_SD_BRIDGE(4, 1),
  134 + UNIPHIER_MIO_RESET_SD_BRIDGE(5, 2),
  135 + UNIPHIER_MIO_RESET_EMMC_HW_RESET(6, 1),
  136 + UNIPHIER_MIO_RESET_DMAC(7),
  137 + UNIPHIER_MIO_RESET_USB2(8, 0),
  138 + UNIPHIER_MIO_RESET_USB2(9, 1),
  139 + UNIPHIER_MIO_RESET_USB2(10, 2),
  140 + UNIPHIER_MIO_RESET_USB2(11, 3),
  141 + UNIPHIER_MIO_RESET_USB2_BRIDGE(12, 0),
  142 + UNIPHIER_MIO_RESET_USB2_BRIDGE(13, 1),
  143 + UNIPHIER_MIO_RESET_USB2_BRIDGE(14, 2),
  144 + UNIPHIER_MIO_RESET_USB2_BRIDGE(15, 3),
  145 + UNIPHIER_RESET_END,
  146 +};
  147 +
  148 +/* Peripheral reset data */
  149 +#define UNIPHIER_PERI_RESET_UART(id, ch) \
  150 + UNIPHIER_RESETX((id), 0x114, 19 + (ch))
  151 +
  152 +#define UNIPHIER_PERI_RESET_I2C(id, ch) \
  153 + UNIPHIER_RESETX((id), 0x114, 5 + (ch))
  154 +
  155 +#define UNIPHIER_PERI_RESET_FI2C(id, ch) \
  156 + UNIPHIER_RESETX((id), 0x114, 24 + (ch))
  157 +
  158 +const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
  159 + UNIPHIER_PERI_RESET_UART(0, 0),
  160 + UNIPHIER_PERI_RESET_UART(1, 1),
  161 + UNIPHIER_PERI_RESET_UART(2, 2),
  162 + UNIPHIER_PERI_RESET_UART(3, 3),
  163 + UNIPHIER_PERI_RESET_I2C(4, 0),
  164 + UNIPHIER_PERI_RESET_I2C(5, 1),
  165 + UNIPHIER_PERI_RESET_I2C(6, 2),
  166 + UNIPHIER_PERI_RESET_I2C(7, 3),
  167 + UNIPHIER_PERI_RESET_I2C(8, 4),
  168 + UNIPHIER_RESET_END,
  169 +};
  170 +
  171 +const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = {
  172 + UNIPHIER_PERI_RESET_UART(0, 0),
  173 + UNIPHIER_PERI_RESET_UART(1, 1),
  174 + UNIPHIER_PERI_RESET_UART(2, 2),
  175 + UNIPHIER_PERI_RESET_UART(3, 3),
  176 + UNIPHIER_PERI_RESET_FI2C(4, 0),
  177 + UNIPHIER_PERI_RESET_FI2C(5, 1),
  178 + UNIPHIER_PERI_RESET_FI2C(6, 2),
  179 + UNIPHIER_PERI_RESET_FI2C(7, 3),
  180 + UNIPHIER_PERI_RESET_FI2C(8, 4),
  181 + UNIPHIER_PERI_RESET_FI2C(9, 5),
  182 + UNIPHIER_PERI_RESET_FI2C(10, 6),
  183 + UNIPHIER_RESET_END,
  184 +};
  185 +
  186 +/* core implementaton */
  187 +struct uniphier_reset_priv {
  188 + void __iomem *base;
  189 + const struct uniphier_reset_data *data;
  190 +};
  191 +
  192 +static int uniphier_reset_request(struct reset_ctl *reset_ctl)
  193 +{
  194 + return 0;
  195 +}
  196 +
  197 +static int uniphier_reset_free(struct reset_ctl *reset_ctl)
  198 +{
  199 + return 0;
  200 +}
  201 +
  202 +static int uniphier_reset_update(struct reset_ctl *reset_ctl, int assert)
  203 +{
  204 + struct uniphier_reset_priv *priv = dev_get_priv(reset_ctl->dev);
  205 + unsigned long id = reset_ctl->id;
  206 + const struct uniphier_reset_data *p;
  207 +
  208 + for (p = priv->data; p->id != UNIPHIER_RESET_ID_END; p++) {
  209 + u32 mask, val;
  210 +
  211 + if (p->id != id)
  212 + continue;
  213 +
  214 + val = readl(priv->base + p->reg);
  215 +
  216 + if (p->flags & UNIPHIER_RESET_ACTIVE_LOW)
  217 + assert = !assert;
  218 +
  219 + mask = BIT(p->bit);
  220 +
  221 + if (assert)
  222 + val |= mask;
  223 + else
  224 + val &= ~mask;
  225 +
  226 + writel(val, priv->base + p->reg);
  227 +
  228 + return 0;
  229 + }
  230 +
  231 + dev_err(priv->dev, "reset_id=%lu was not handled\n", id);
  232 + return -EINVAL;
  233 +}
  234 +
  235 +static int uniphier_reset_assert(struct reset_ctl *reset_ctl)
  236 +{
  237 + return uniphier_reset_update(reset_ctl, 1);
  238 +}
  239 +
  240 +static int uniphier_reset_deassert(struct reset_ctl *reset_ctl)
  241 +{
  242 + return uniphier_reset_update(reset_ctl, 0);
  243 +}
  244 +
  245 +static const struct reset_ops uniphier_reset_ops = {
  246 + .request = uniphier_reset_request,
  247 + .free = uniphier_reset_free,
  248 + .rst_assert = uniphier_reset_assert,
  249 + .rst_deassert = uniphier_reset_deassert,
  250 +};
  251 +
  252 +static int uniphier_reset_probe(struct udevice *dev)
  253 +{
  254 + struct uniphier_reset_priv *priv = dev_get_priv(dev);
  255 + fdt_addr_t addr;
  256 +
  257 + addr = dev_get_addr(dev->parent);
  258 + if (addr == FDT_ADDR_T_NONE)
  259 + return -EINVAL;
  260 +
  261 + priv->base = devm_ioremap(dev, addr, SZ_4K);
  262 + if (!priv->base)
  263 + return -ENOMEM;
  264 +
  265 + priv->data = (void *)dev_get_driver_data(dev);
  266 +
  267 + return 0;
  268 +}
  269 +
  270 +static const struct udevice_id uniphier_reset_match[] = {
  271 + /* System reset */
  272 + {
  273 + .compatible = "socionext,uniphier-sld3-reset",
  274 + .data = (ulong)uniphier_sld3_sys_reset_data,
  275 + },
  276 + {
  277 + .compatible = "socionext,uniphier-ld4-reset",
  278 + .data = (ulong)uniphier_sld3_sys_reset_data,
  279 + },
  280 + {
  281 + .compatible = "socionext,uniphier-pro4-reset",
  282 + .data = (ulong)uniphier_pro4_sys_reset_data,
  283 + },
  284 + {
  285 + .compatible = "socionext,uniphier-sld8-reset",
  286 + .data = (ulong)uniphier_sld3_sys_reset_data,
  287 + },
  288 + {
  289 + .compatible = "socionext,uniphier-pro5-reset",
  290 + .data = (ulong)uniphier_pro5_sys_reset_data,
  291 + },
  292 + {
  293 + .compatible = "socionext,uniphier-pxs2-reset",
  294 + .data = (ulong)uniphier_pxs2_sys_reset_data,
  295 + },
  296 + {
  297 + .compatible = "socionext,uniphier-ld11-reset",
  298 + .data = (ulong)uniphier_ld11_sys_reset_data,
  299 + },
  300 + {
  301 + .compatible = "socionext,uniphier-ld20-reset",
  302 + .data = (ulong)uniphier_ld20_sys_reset_data,
  303 + },
  304 + /* Media I/O reset */
  305 + {
  306 + .compatible = "socionext,uniphier-sld3-mio-clock",
  307 + .data = (ulong)uniphier_mio_reset_data,
  308 + },
  309 + {
  310 + .compatible = "socionext,uniphier-ld4-mio-reset",
  311 + .data = (ulong)uniphier_mio_reset_data,
  312 + },
  313 + {
  314 + .compatible = "socionext,uniphier-pro4-mio-reset",
  315 + .data = (ulong)uniphier_mio_reset_data,
  316 + },
  317 + {
  318 + .compatible = "socionext,uniphier-sld8-mio-reset",
  319 + .data = (ulong)uniphier_mio_reset_data,
  320 + },
  321 + {
  322 + .compatible = "socionext,uniphier-pro5-mio-reset",
  323 + .data = (ulong)uniphier_mio_reset_data,
  324 + },
  325 + {
  326 + .compatible = "socionext,uniphier-pxs2-mio-reset",
  327 + .data = (ulong)uniphier_mio_reset_data,
  328 + },
  329 + {
  330 + .compatible = "socionext,uniphier-ld11-mio-reset",
  331 + .data = (ulong)uniphier_mio_reset_data,
  332 + },
  333 + {
  334 + .compatible = "socionext,uniphier-ld20-mio-reset",
  335 + .data = (ulong)uniphier_mio_reset_data,
  336 + },
  337 + /* Peripheral reset */
  338 + {
  339 + .compatible = "socionext,uniphier-ld4-peri-reset",
  340 + .data = (ulong)uniphier_ld4_peri_reset_data,
  341 + },
  342 + {
  343 + .compatible = "socionext,uniphier-pro4-peri-reset",
  344 + .data = (ulong)uniphier_pro4_peri_reset_data,
  345 + },
  346 + {
  347 + .compatible = "socionext,uniphier-sld8-peri-reset",
  348 + .data = (ulong)uniphier_ld4_peri_reset_data,
  349 + },
  350 + {
  351 + .compatible = "socionext,uniphier-pro5-peri-reset",
  352 + .data = (ulong)uniphier_pro4_peri_reset_data,
  353 + },
  354 + {
  355 + .compatible = "socionext,uniphier-pxs2-peri-reset",
  356 + .data = (ulong)uniphier_pro4_peri_reset_data,
  357 + },
  358 + {
  359 + .compatible = "socionext,uniphier-ld11-peri-reset",
  360 + .data = (ulong)uniphier_pro4_peri_reset_data,
  361 + },
  362 + {
  363 + .compatible = "socionext,uniphier-ld20-peri-reset",
  364 + .data = (ulong)uniphier_pro4_peri_reset_data,
  365 + },
  366 + { /* sentinel */ }
  367 +};
  368 +
  369 +U_BOOT_DRIVER(uniphier_reset) = {
  370 + .name = "uniphier-reset",
  371 + .id = UCLASS_RESET,
  372 + .of_match = uniphier_reset_match,
  373 + .probe = uniphier_reset_probe,
  374 + .priv_auto_alloc_size = sizeof(struct uniphier_reset_priv),
  375 + .ops = &uniphier_reset_ops,
  376 +};