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