xref: /openbmc/u-boot/drivers/reset/reset-meson.c (revision 20367bb5)
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