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 <reset-uclass.h>
  10#include <dm/device.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 */
  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
  59const 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
  64const 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
  72const 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
  80const 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
  94const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = {
  95        UNIPHIER_LD11_SYS_RESET_STDMAC(8),      /* HSC, MIO */
  96        UNIPHIER_RESET_END,
  97};
  98
  99const 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
 128const 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
 158const 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
 171const 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 */
 187struct uniphier_reset_priv {
 188        void __iomem *base;
 189        const struct uniphier_reset_data *data;
 190};
 191
 192static int uniphier_reset_request(struct reset_ctl *reset_ctl)
 193{
 194        return 0;
 195}
 196
 197static int uniphier_reset_free(struct reset_ctl *reset_ctl)
 198{
 199        return 0;
 200}
 201
 202static 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
 235static int uniphier_reset_assert(struct reset_ctl *reset_ctl)
 236{
 237        return uniphier_reset_update(reset_ctl, 1);
 238}
 239
 240static int uniphier_reset_deassert(struct reset_ctl *reset_ctl)
 241{
 242        return uniphier_reset_update(reset_ctl, 0);
 243}
 244
 245static 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
 252static 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
 270static 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
 369U_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};
 377