183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0
220367bb5SNeil Armstrong /*
320367bb5SNeil Armstrong * Amlogic Meson Reset Controller driver
420367bb5SNeil Armstrong *
520367bb5SNeil Armstrong * Copyright (c) 2018 BayLibre, SAS.
620367bb5SNeil Armstrong * Author: Neil Armstrong <narmstrong@baylibre.com>
720367bb5SNeil Armstrong */
820367bb5SNeil Armstrong
920367bb5SNeil Armstrong #include <common.h>
1020367bb5SNeil Armstrong #include <dm.h>
1120367bb5SNeil Armstrong #include <reset-uclass.h>
1220367bb5SNeil Armstrong #include <regmap.h>
1320367bb5SNeil Armstrong
1420367bb5SNeil Armstrong #define REG_COUNT 8
1520367bb5SNeil Armstrong #define BITS_PER_REG 32
1620367bb5SNeil Armstrong #define LEVEL_OFFSET 0x7c
1720367bb5SNeil Armstrong
1820367bb5SNeil Armstrong struct meson_reset_priv {
1920367bb5SNeil Armstrong struct regmap *regmap;
2020367bb5SNeil Armstrong };
2120367bb5SNeil Armstrong
meson_reset_request(struct reset_ctl * reset_ctl)2220367bb5SNeil Armstrong static int meson_reset_request(struct reset_ctl *reset_ctl)
2320367bb5SNeil Armstrong {
2420367bb5SNeil Armstrong if (reset_ctl->id > (REG_COUNT * BITS_PER_REG))
2520367bb5SNeil Armstrong return -EINVAL;
2620367bb5SNeil Armstrong
2720367bb5SNeil Armstrong return 0;
2820367bb5SNeil Armstrong }
2920367bb5SNeil Armstrong
meson_reset_free(struct reset_ctl * reset_ctl)3020367bb5SNeil Armstrong static int meson_reset_free(struct reset_ctl *reset_ctl)
3120367bb5SNeil Armstrong {
3220367bb5SNeil Armstrong return 0;
3320367bb5SNeil Armstrong }
3420367bb5SNeil Armstrong
meson_reset_level(struct reset_ctl * reset_ctl,bool assert)3520367bb5SNeil Armstrong static int meson_reset_level(struct reset_ctl *reset_ctl, bool assert)
3620367bb5SNeil Armstrong {
3720367bb5SNeil Armstrong struct meson_reset_priv *priv = dev_get_priv(reset_ctl->dev);
3820367bb5SNeil Armstrong uint bank = reset_ctl->id / BITS_PER_REG;
3920367bb5SNeil Armstrong uint offset = reset_ctl->id % BITS_PER_REG;
4020367bb5SNeil Armstrong uint reg_offset = LEVEL_OFFSET + (bank << 2);
4120367bb5SNeil Armstrong uint val;
4220367bb5SNeil Armstrong
4320367bb5SNeil Armstrong regmap_read(priv->regmap, reg_offset, &val);
4420367bb5SNeil Armstrong if (assert)
4520367bb5SNeil Armstrong val &= ~BIT(offset);
4620367bb5SNeil Armstrong else
4720367bb5SNeil Armstrong val |= BIT(offset);
4820367bb5SNeil Armstrong regmap_write(priv->regmap, reg_offset, val);
4920367bb5SNeil Armstrong
5020367bb5SNeil Armstrong return 0;
5120367bb5SNeil Armstrong }
5220367bb5SNeil Armstrong
meson_reset_assert(struct reset_ctl * reset_ctl)5320367bb5SNeil Armstrong static int meson_reset_assert(struct reset_ctl *reset_ctl)
5420367bb5SNeil Armstrong {
5520367bb5SNeil Armstrong return meson_reset_level(reset_ctl, true);
5620367bb5SNeil Armstrong }
5720367bb5SNeil Armstrong
meson_reset_deassert(struct reset_ctl * reset_ctl)5820367bb5SNeil Armstrong static int meson_reset_deassert(struct reset_ctl *reset_ctl)
5920367bb5SNeil Armstrong {
6020367bb5SNeil Armstrong return meson_reset_level(reset_ctl, false);
6120367bb5SNeil Armstrong }
6220367bb5SNeil Armstrong
6320367bb5SNeil Armstrong struct reset_ops meson_reset_ops = {
6420367bb5SNeil Armstrong .request = meson_reset_request,
6520367bb5SNeil Armstrong .free = meson_reset_free,
6620367bb5SNeil Armstrong .rst_assert = meson_reset_assert,
6720367bb5SNeil Armstrong .rst_deassert = meson_reset_deassert,
6820367bb5SNeil Armstrong };
6920367bb5SNeil Armstrong
7020367bb5SNeil Armstrong static const struct udevice_id meson_reset_ids[] = {
7120367bb5SNeil Armstrong { .compatible = "amlogic,meson-gxbb-reset" },
7220367bb5SNeil Armstrong { }
7320367bb5SNeil Armstrong };
7420367bb5SNeil Armstrong
meson_reset_probe(struct udevice * dev)7520367bb5SNeil Armstrong static int meson_reset_probe(struct udevice *dev)
7620367bb5SNeil Armstrong {
7720367bb5SNeil Armstrong struct meson_reset_priv *priv = dev_get_priv(dev);
7820367bb5SNeil Armstrong
79*d3581236SMasahiro Yamada return regmap_init_mem(dev_ofnode(dev), &priv->regmap);
8020367bb5SNeil Armstrong }
8120367bb5SNeil Armstrong
8220367bb5SNeil Armstrong U_BOOT_DRIVER(meson_reset) = {
8320367bb5SNeil Armstrong .name = "meson_reset",
8420367bb5SNeil Armstrong .id = UCLASS_RESET,
8520367bb5SNeil Armstrong .of_match = meson_reset_ids,
8620367bb5SNeil Armstrong .probe = meson_reset_probe,
8720367bb5SNeil Armstrong .ops = &meson_reset_ops,
8820367bb5SNeil Armstrong .priv_auto_alloc_size = sizeof(struct meson_reset_priv),
8920367bb5SNeil Armstrong };
90