diff options
Diffstat (limited to 'roms/u-boot/drivers/reset/reset-meson.c')
-rw-r--r-- | roms/u-boot/drivers/reset/reset-meson.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/roms/u-boot/drivers/reset/reset-meson.c b/roms/u-boot/drivers/reset/reset-meson.c new file mode 100644 index 000000000..d4e0745d0 --- /dev/null +++ b/roms/u-boot/drivers/reset/reset-meson.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Amlogic Meson Reset Controller driver + * + * Copyright (c) 2018 BayLibre, SAS. + * Author: Neil Armstrong <narmstrong@baylibre.com> + */ + +#include <common.h> +#include <dm.h> +#include <log.h> +#include <malloc.h> +#include <reset-uclass.h> +#include <regmap.h> +#include <linux/bitops.h> + +#define REG_COUNT 8 +#define BITS_PER_REG 32 +#define LEVEL_OFFSET 0x7c + +struct meson_reset_priv { + struct regmap *regmap; +}; + +static int meson_reset_request(struct reset_ctl *reset_ctl) +{ + if (reset_ctl->id > (REG_COUNT * BITS_PER_REG)) + return -EINVAL; + + return 0; +} + +static int meson_reset_free(struct reset_ctl *reset_ctl) +{ + return 0; +} + +static int meson_reset_level(struct reset_ctl *reset_ctl, bool assert) +{ + struct meson_reset_priv *priv = dev_get_priv(reset_ctl->dev); + uint bank = reset_ctl->id / BITS_PER_REG; + uint offset = reset_ctl->id % BITS_PER_REG; + uint reg_offset = LEVEL_OFFSET + (bank << 2); + uint val; + + regmap_read(priv->regmap, reg_offset, &val); + if (assert) + val &= ~BIT(offset); + else + val |= BIT(offset); + regmap_write(priv->regmap, reg_offset, val); + + return 0; +} + +static int meson_reset_assert(struct reset_ctl *reset_ctl) +{ + return meson_reset_level(reset_ctl, true); +} + +static int meson_reset_deassert(struct reset_ctl *reset_ctl) +{ + return meson_reset_level(reset_ctl, false); +} + +struct reset_ops meson_reset_ops = { + .request = meson_reset_request, + .rfree = meson_reset_free, + .rst_assert = meson_reset_assert, + .rst_deassert = meson_reset_deassert, +}; + +static const struct udevice_id meson_reset_ids[] = { + { .compatible = "amlogic,meson-gxbb-reset" }, + { .compatible = "amlogic,meson-axg-reset" }, + { } +}; + +static int meson_reset_probe(struct udevice *dev) +{ + struct meson_reset_priv *priv = dev_get_priv(dev); + + return regmap_init_mem(dev_ofnode(dev), &priv->regmap); +} + +U_BOOT_DRIVER(meson_reset) = { + .name = "meson_reset", + .id = UCLASS_RESET, + .of_match = meson_reset_ids, + .probe = meson_reset_probe, + .ops = &meson_reset_ops, + .priv_auto = sizeof(struct meson_reset_priv), +}; |