1*83d290c5STom 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 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 3020367bb5SNeil Armstrong static int meson_reset_free(struct reset_ctl *reset_ctl) 3120367bb5SNeil Armstrong { 3220367bb5SNeil Armstrong return 0; 3320367bb5SNeil Armstrong } 3420367bb5SNeil Armstrong 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 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 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 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 7920367bb5SNeil Armstrong return regmap_init_mem(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