xref: /openbmc/u-boot/drivers/reset/reset-meson.c (revision e8f80a5a)
183d290c5STom 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 
meson_reset_request(struct reset_ctl * reset_ctl)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 
meson_reset_free(struct reset_ctl * reset_ctl)3020367bb5SNeil Armstrong static int meson_reset_free(struct reset_ctl *reset_ctl)
3120367bb5SNeil Armstrong {
3220367bb5SNeil Armstrong 	return 0;
3320367bb5SNeil Armstrong }
3420367bb5SNeil Armstrong 
meson_reset_level(struct reset_ctl * reset_ctl,bool assert)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 
meson_reset_assert(struct reset_ctl * reset_ctl)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 
meson_reset_deassert(struct reset_ctl * reset_ctl)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 
meson_reset_probe(struct udevice * dev)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 
79*d3581236SMasahiro Yamada 	return regmap_init_mem(dev_ofnode(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