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