1*20367bb5SNeil Armstrong /* 2*20367bb5SNeil Armstrong * Amlogic Meson Reset Controller driver 3*20367bb5SNeil Armstrong * 4*20367bb5SNeil Armstrong * Copyright (c) 2018 BayLibre, SAS. 5*20367bb5SNeil Armstrong * Author: Neil Armstrong <narmstrong@baylibre.com> 6*20367bb5SNeil Armstrong * 7*20367bb5SNeil Armstrong * SPDX-License-Identifier: GPL-2.0 8*20367bb5SNeil Armstrong */ 9*20367bb5SNeil Armstrong 10*20367bb5SNeil Armstrong #include <common.h> 11*20367bb5SNeil Armstrong #include <dm.h> 12*20367bb5SNeil Armstrong #include <reset-uclass.h> 13*20367bb5SNeil Armstrong #include <regmap.h> 14*20367bb5SNeil Armstrong 15*20367bb5SNeil Armstrong #define REG_COUNT 8 16*20367bb5SNeil Armstrong #define BITS_PER_REG 32 17*20367bb5SNeil Armstrong #define LEVEL_OFFSET 0x7c 18*20367bb5SNeil Armstrong 19*20367bb5SNeil Armstrong struct meson_reset_priv { 20*20367bb5SNeil Armstrong struct regmap *regmap; 21*20367bb5SNeil Armstrong }; 22*20367bb5SNeil Armstrong 23*20367bb5SNeil Armstrong static int meson_reset_request(struct reset_ctl *reset_ctl) 24*20367bb5SNeil Armstrong { 25*20367bb5SNeil Armstrong if (reset_ctl->id > (REG_COUNT * BITS_PER_REG)) 26*20367bb5SNeil Armstrong return -EINVAL; 27*20367bb5SNeil Armstrong 28*20367bb5SNeil Armstrong return 0; 29*20367bb5SNeil Armstrong } 30*20367bb5SNeil Armstrong 31*20367bb5SNeil Armstrong static int meson_reset_free(struct reset_ctl *reset_ctl) 32*20367bb5SNeil Armstrong { 33*20367bb5SNeil Armstrong return 0; 34*20367bb5SNeil Armstrong } 35*20367bb5SNeil Armstrong 36*20367bb5SNeil Armstrong static int meson_reset_level(struct reset_ctl *reset_ctl, bool assert) 37*20367bb5SNeil Armstrong { 38*20367bb5SNeil Armstrong struct meson_reset_priv *priv = dev_get_priv(reset_ctl->dev); 39*20367bb5SNeil Armstrong uint bank = reset_ctl->id / BITS_PER_REG; 40*20367bb5SNeil Armstrong uint offset = reset_ctl->id % BITS_PER_REG; 41*20367bb5SNeil Armstrong uint reg_offset = LEVEL_OFFSET + (bank << 2); 42*20367bb5SNeil Armstrong uint val; 43*20367bb5SNeil Armstrong 44*20367bb5SNeil Armstrong regmap_read(priv->regmap, reg_offset, &val); 45*20367bb5SNeil Armstrong if (assert) 46*20367bb5SNeil Armstrong val &= ~BIT(offset); 47*20367bb5SNeil Armstrong else 48*20367bb5SNeil Armstrong val |= BIT(offset); 49*20367bb5SNeil Armstrong regmap_write(priv->regmap, reg_offset, val); 50*20367bb5SNeil Armstrong 51*20367bb5SNeil Armstrong return 0; 52*20367bb5SNeil Armstrong } 53*20367bb5SNeil Armstrong 54*20367bb5SNeil Armstrong static int meson_reset_assert(struct reset_ctl *reset_ctl) 55*20367bb5SNeil Armstrong { 56*20367bb5SNeil Armstrong return meson_reset_level(reset_ctl, true); 57*20367bb5SNeil Armstrong } 58*20367bb5SNeil Armstrong 59*20367bb5SNeil Armstrong static int meson_reset_deassert(struct reset_ctl *reset_ctl) 60*20367bb5SNeil Armstrong { 61*20367bb5SNeil Armstrong return meson_reset_level(reset_ctl, false); 62*20367bb5SNeil Armstrong } 63*20367bb5SNeil Armstrong 64*20367bb5SNeil Armstrong struct reset_ops meson_reset_ops = { 65*20367bb5SNeil Armstrong .request = meson_reset_request, 66*20367bb5SNeil Armstrong .free = meson_reset_free, 67*20367bb5SNeil Armstrong .rst_assert = meson_reset_assert, 68*20367bb5SNeil Armstrong .rst_deassert = meson_reset_deassert, 69*20367bb5SNeil Armstrong }; 70*20367bb5SNeil Armstrong 71*20367bb5SNeil Armstrong static const struct udevice_id meson_reset_ids[] = { 72*20367bb5SNeil Armstrong { .compatible = "amlogic,meson-gxbb-reset" }, 73*20367bb5SNeil Armstrong { } 74*20367bb5SNeil Armstrong }; 75*20367bb5SNeil Armstrong 76*20367bb5SNeil Armstrong static int meson_reset_probe(struct udevice *dev) 77*20367bb5SNeil Armstrong { 78*20367bb5SNeil Armstrong struct meson_reset_priv *priv = dev_get_priv(dev); 79*20367bb5SNeil Armstrong 80*20367bb5SNeil Armstrong return regmap_init_mem(dev, &priv->regmap); 81*20367bb5SNeil Armstrong } 82*20367bb5SNeil Armstrong 83*20367bb5SNeil Armstrong U_BOOT_DRIVER(meson_reset) = { 84*20367bb5SNeil Armstrong .name = "meson_reset", 85*20367bb5SNeil Armstrong .id = UCLASS_RESET, 86*20367bb5SNeil Armstrong .of_match = meson_reset_ids, 87*20367bb5SNeil Armstrong .probe = meson_reset_probe, 88*20367bb5SNeil Armstrong .ops = &meson_reset_ops, 89*20367bb5SNeil Armstrong .priv_auto_alloc_size = sizeof(struct meson_reset_priv), 90*20367bb5SNeil Armstrong }; 91