uboot/drivers/reset/reset-uniphier.c
<<
>>
Prefs
   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 <dm.h>
  10#include <reset-uclass.h>
  11#include <linux/bitops.h>
  12#include <linux/io.h>
  13#include <linux/sizes.h>
  14
  15struct 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 */
  44static const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
  45        UNIPHIER_RESETX(2, 0x2000, 2),          /* NAND */
  46        UNIPHIER_RESETX(8, 0x2000, 10),         /* STDMAC */
  47        UNIPHIER_RESETX(12, 0x2000, 6),         /* GIO */
  48        UNIPHIER_RESETX(14, 0x2000, 17),        /* USB30 */
  49        UNIPHIER_RESETX(15, 0x2004, 17),        /* USB31 */
  50        UNIPHIER_RESET_END,
  51};
  52
  53static const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
  54        UNIPHIER_RESETX(2, 0x2000, 2),          /* NAND */
  55        UNIPHIER_RESETX(8, 0x2000, 10),         /* STDMAC */
  56        UNIPHIER_RESETX(14, 0x2000, 17),        /* USB30 */
  57        UNIPHIER_RESETX(15, 0x2004, 17),        /* USB31 */
  58        UNIPHIER_RESETX(16, 0x2014, 4),         /* USB30-PHY0 */
  59        UNIPHIER_RESETX(17, 0x2014, 0),         /* USB30-PHY1 */
  60        UNIPHIER_RESETX(18, 0x2014, 2),         /* USB30-PHY2 */
  61        UNIPHIER_RESETX(20, 0x2014, 5),         /* USB31-PHY0 */
  62        UNIPHIER_RESETX(21, 0x2014, 1),         /* USB31-PHY1 */
  63        UNIPHIER_RESETX(28, 0x2014, 12),        /* SATA */
  64        UNIPHIER_RESET(29, 0x2014, 8),          /* SATA-PHY (active high) */
  65        UNIPHIER_RESET_END,
  66};
  67
  68static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
  69        UNIPHIER_RESETX(2, 0x200c, 0),          /* NAND */
  70        UNIPHIER_RESETX(4, 0x200c, 2),          /* eMMC */
  71        UNIPHIER_RESETX(8, 0x200c, 8),          /* STDMAC */
  72        UNIPHIER_RESETX(12, 0x200c, 5),         /* GIO */
  73        UNIPHIER_RESETX(16, 0x200c, 12),        /* USB30-PHY0 */
  74        UNIPHIER_RESETX(17, 0x200c, 13),        /* USB30-PHY1 */
  75        UNIPHIER_RESETX(18, 0x200c, 14),        /* USB30-PHY2 */
  76        UNIPHIER_RESETX(19, 0x200c, 15),        /* USB30-PHY3 */
  77        UNIPHIER_RESET_END,
  78};
  79
  80static const struct uniphier_reset_data uniphier_pxs3_sys_reset_data[] = {
  81        UNIPHIER_RESETX(2, 0x200c, 0),          /* NAND */
  82        UNIPHIER_RESETX(4, 0x200c, 2),          /* eMMC */
  83        UNIPHIER_RESETX(8, 0x200c, 12),         /* STDMAC */
  84        UNIPHIER_RESETX(12, 0x200c, 5),         /* USB30 (GIO0) */
  85        UNIPHIER_RESETX(13, 0x200c, 6),         /* USB31 (GIO1) */
  86        UNIPHIER_RESETX(16, 0x200c, 16),        /* USB30-PHY */
  87        UNIPHIER_RESETX(20, 0x200c, 17),        /* USB31-PHY */
  88        UNIPHIER_RESET_END,
  89};
  90
  91/* Media I/O reset data */
  92#define UNIPHIER_MIO_RESET_SD(id, ch)                   \
  93        UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 0)
  94
  95#define UNIPHIER_MIO_RESET_SD_BRIDGE(id, ch)            \
  96        UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 26)
  97
  98#define UNIPHIER_MIO_RESET_EMMC_HW_RESET(id, ch)        \
  99        UNIPHIER_RESETX((id), 0x80 + 0x200 * (ch), 0)
 100
 101#define UNIPHIER_MIO_RESET_USB2(id, ch)                 \
 102        UNIPHIER_RESETX((id), 0x114 + 0x200 * (ch), 0)
 103
 104#define UNIPHIER_MIO_RESET_USB2_BRIDGE(id, ch)          \
 105        UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 24)
 106
 107#define UNIPHIER_MIO_RESET_DMAC(id)                     \
 108        UNIPHIER_RESETX((id), 0x110, 17)
 109
 110static const struct uniphier_reset_data uniphier_mio_reset_data[] = {
 111        UNIPHIER_MIO_RESET_SD(0, 0),
 112        UNIPHIER_MIO_RESET_SD(1, 1),
 113        UNIPHIER_MIO_RESET_SD(2, 2),
 114        UNIPHIER_MIO_RESET_SD_BRIDGE(3, 0),
 115        UNIPHIER_MIO_RESET_SD_BRIDGE(4, 1),
 116        UNIPHIER_MIO_RESET_SD_BRIDGE(5, 2),
 117        UNIPHIER_MIO_RESET_EMMC_HW_RESET(6, 1),
 118        UNIPHIER_MIO_RESET_DMAC(7),
 119        UNIPHIER_MIO_RESET_USB2(8, 0),
 120        UNIPHIER_MIO_RESET_USB2(9, 1),
 121        UNIPHIER_MIO_RESET_USB2(10, 2),
 122        UNIPHIER_MIO_RESET_USB2(11, 3),
 123        UNIPHIER_MIO_RESET_USB2_BRIDGE(12, 0),
 124        UNIPHIER_MIO_RESET_USB2_BRIDGE(13, 1),
 125        UNIPHIER_MIO_RESET_USB2_BRIDGE(14, 2),
 126        UNIPHIER_MIO_RESET_USB2_BRIDGE(15, 3),
 127        UNIPHIER_RESET_END,
 128};
 129
 130/* Peripheral reset data */
 131#define UNIPHIER_PERI_RESET_UART(id, ch)                \
 132        UNIPHIER_RESETX((id), 0x114, 19 + (ch))
 133
 134#define UNIPHIER_PERI_RESET_I2C(id, ch)                 \
 135        UNIPHIER_RESETX((id), 0x114, 5 + (ch))
 136
 137#define UNIPHIER_PERI_RESET_FI2C(id, ch)                \
 138        UNIPHIER_RESETX((id), 0x114, 24 + (ch))
 139
 140static const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
 141        UNIPHIER_PERI_RESET_UART(0, 0),
 142        UNIPHIER_PERI_RESET_UART(1, 1),
 143        UNIPHIER_PERI_RESET_UART(2, 2),
 144        UNIPHIER_PERI_RESET_UART(3, 3),
 145        UNIPHIER_PERI_RESET_I2C(4, 0),
 146        UNIPHIER_PERI_RESET_I2C(5, 1),
 147        UNIPHIER_PERI_RESET_I2C(6, 2),
 148        UNIPHIER_PERI_RESET_I2C(7, 3),
 149        UNIPHIER_PERI_RESET_I2C(8, 4),
 150        UNIPHIER_RESET_END,
 151};
 152
 153static const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = {
 154        UNIPHIER_PERI_RESET_UART(0, 0),
 155        UNIPHIER_PERI_RESET_UART(1, 1),
 156        UNIPHIER_PERI_RESET_UART(2, 2),
 157        UNIPHIER_PERI_RESET_UART(3, 3),
 158        UNIPHIER_PERI_RESET_FI2C(4, 0),
 159        UNIPHIER_PERI_RESET_FI2C(5, 1),
 160        UNIPHIER_PERI_RESET_FI2C(6, 2),
 161        UNIPHIER_PERI_RESET_FI2C(7, 3),
 162        UNIPHIER_PERI_RESET_FI2C(8, 4),
 163        UNIPHIER_PERI_RESET_FI2C(9, 5),
 164        UNIPHIER_PERI_RESET_FI2C(10, 6),
 165        UNIPHIER_RESET_END,
 166};
 167
 168/* core implementaton */
 169struct uniphier_reset_priv {
 170        void __iomem *base;
 171        const struct uniphier_reset_data *data;
 172};
 173
 174static int uniphier_reset_request(struct reset_ctl *reset_ctl)
 175{
 176        return 0;
 177}
 178
 179static int uniphier_reset_free(struct reset_ctl *reset_ctl)
 180{
 181        return 0;
 182}
 183
 184static int uniphier_reset_update(struct reset_ctl *reset_ctl, int assert)
 185{
 186        struct uniphier_reset_priv *priv = dev_get_priv(reset_ctl->dev);
 187        unsigned long id = reset_ctl->id;
 188        const struct uniphier_reset_data *p;
 189
 190        for (p = priv->data; p->id != UNIPHIER_RESET_ID_END; p++) {
 191                u32 mask, val;
 192
 193                if (p->id != id)
 194                        continue;
 195
 196                val = readl(priv->base + p->reg);
 197
 198                if (p->flags & UNIPHIER_RESET_ACTIVE_LOW)
 199                        assert = !assert;
 200
 201                mask = BIT(p->bit);
 202
 203                if (assert)
 204                        val |= mask;
 205                else
 206                        val &= ~mask;
 207
 208                writel(val, priv->base + p->reg);
 209
 210                return 0;
 211        }
 212
 213        dev_err(reset_ctl->dev, "reset_id=%lu was not handled\n", id);
 214
 215        return -EINVAL;
 216}
 217
 218static int uniphier_reset_assert(struct reset_ctl *reset_ctl)
 219{
 220        return uniphier_reset_update(reset_ctl, 1);
 221}
 222
 223static int uniphier_reset_deassert(struct reset_ctl *reset_ctl)
 224{
 225        return uniphier_reset_update(reset_ctl, 0);
 226}
 227
 228static const struct reset_ops uniphier_reset_ops = {
 229        .request = uniphier_reset_request,
 230        .free = uniphier_reset_free,
 231        .rst_assert = uniphier_reset_assert,
 232        .rst_deassert = uniphier_reset_deassert,
 233};
 234
 235static int uniphier_reset_probe(struct udevice *dev)
 236{
 237        struct uniphier_reset_priv *priv = dev_get_priv(dev);
 238        fdt_addr_t addr;
 239
 240        addr = devfdt_get_addr(dev->parent);
 241        if (addr == FDT_ADDR_T_NONE)
 242                return -EINVAL;
 243
 244        priv->base = devm_ioremap(dev, addr, SZ_4K);
 245        if (!priv->base)
 246                return -ENOMEM;
 247
 248        priv->data = (void *)dev_get_driver_data(dev);
 249
 250        return 0;
 251}
 252
 253static const struct udevice_id uniphier_reset_match[] = {
 254        /* System reset */
 255        {
 256                .compatible = "socionext,uniphier-ld4-reset",
 257                .data = (ulong)uniphier_pro4_sys_reset_data,
 258        },
 259        {
 260                .compatible = "socionext,uniphier-pro4-reset",
 261                .data = (ulong)uniphier_pro4_sys_reset_data,
 262        },
 263        {
 264                .compatible = "socionext,uniphier-sld8-reset",
 265                .data = (ulong)uniphier_pro4_sys_reset_data,
 266        },
 267        {
 268                .compatible = "socionext,uniphier-pro5-reset",
 269                .data = (ulong)uniphier_pro4_sys_reset_data,
 270        },
 271        {
 272                .compatible = "socionext,uniphier-pxs2-reset",
 273                .data = (ulong)uniphier_pxs2_sys_reset_data,
 274        },
 275        {
 276                .compatible = "socionext,uniphier-ld11-reset",
 277                .data = (ulong)uniphier_ld20_sys_reset_data,
 278        },
 279        {
 280                .compatible = "socionext,uniphier-ld20-reset",
 281                .data = (ulong)uniphier_ld20_sys_reset_data,
 282        },
 283        {
 284                .compatible = "socionext,uniphier-pxs3-reset",
 285                .data = (ulong)uniphier_pxs3_sys_reset_data,
 286        },
 287        /* Media I/O reset */
 288        {
 289                .compatible = "socionext,uniphier-ld4-mio-reset",
 290                .data = (ulong)uniphier_mio_reset_data,
 291        },
 292        {
 293                .compatible = "socionext,uniphier-pro4-mio-reset",
 294                .data = (ulong)uniphier_mio_reset_data,
 295        },
 296        {
 297                .compatible = "socionext,uniphier-sld8-mio-reset",
 298                .data = (ulong)uniphier_mio_reset_data,
 299        },
 300        {
 301                .compatible = "socionext,uniphier-pro5-mio-reset",
 302                .data = (ulong)uniphier_mio_reset_data,
 303        },
 304        {
 305                .compatible = "socionext,uniphier-pxs2-mio-reset",
 306                .data = (ulong)uniphier_mio_reset_data,
 307        },
 308        {
 309                .compatible = "socionext,uniphier-ld11-mio-reset",
 310                .data = (ulong)uniphier_mio_reset_data,
 311        },
 312        {
 313                .compatible = "socionext,uniphier-ld11-sd-reset",
 314                .data = (ulong)uniphier_mio_reset_data,
 315        },
 316        {
 317                .compatible = "socionext,uniphier-ld20-sd-reset",
 318                .data = (ulong)uniphier_mio_reset_data,
 319        },
 320        {
 321                .compatible = "socionext,uniphier-pxs3-sd-reset",
 322                .data = (ulong)uniphier_mio_reset_data,
 323        },
 324        /* Peripheral reset */
 325        {
 326                .compatible = "socionext,uniphier-ld4-peri-reset",
 327                .data = (ulong)uniphier_ld4_peri_reset_data,
 328        },
 329        {
 330                .compatible = "socionext,uniphier-pro4-peri-reset",
 331                .data = (ulong)uniphier_pro4_peri_reset_data,
 332        },
 333        {
 334                .compatible = "socionext,uniphier-sld8-peri-reset",
 335                .data = (ulong)uniphier_ld4_peri_reset_data,
 336        },
 337        {
 338                .compatible = "socionext,uniphier-pro5-peri-reset",
 339                .data = (ulong)uniphier_pro4_peri_reset_data,
 340        },
 341        {
 342                .compatible = "socionext,uniphier-pxs2-peri-reset",
 343                .data = (ulong)uniphier_pro4_peri_reset_data,
 344        },
 345        {
 346                .compatible = "socionext,uniphier-ld11-peri-reset",
 347                .data = (ulong)uniphier_pro4_peri_reset_data,
 348        },
 349        {
 350                .compatible = "socionext,uniphier-ld20-peri-reset",
 351                .data = (ulong)uniphier_pro4_peri_reset_data,
 352        },
 353        {
 354                .compatible = "socionext,uniphier-pxs3-peri-reset",
 355                .data = (ulong)uniphier_pro4_peri_reset_data,
 356        },
 357        { /* sentinel */ }
 358};
 359
 360U_BOOT_DRIVER(uniphier_reset) = {
 361        .name = "uniphier-reset",
 362        .id = UCLASS_RESET,
 363        .of_match = uniphier_reset_match,
 364        .probe = uniphier_reset_probe,
 365        .priv_auto_alloc_size = sizeof(struct uniphier_reset_priv),
 366        .ops = &uniphier_reset_ops,
 367};
 368