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