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