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