ARM: dts: npcm8xx: add npcm845 function node
[platform/kernel/u-boot.git] / drivers / reset / reset-meson.c
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 <log.h>
12 #include <malloc.h>
13 #include <reset-uclass.h>
14 #include <regmap.h>
15 #include <linux/bitops.h>
16
17 #define REG_COUNT       8
18 #define BITS_PER_REG    32
19 #define LEVEL_OFFSET    0x7c
20
21 struct meson_reset_priv {
22         struct regmap *regmap;
23 };
24
25 static int meson_reset_request(struct reset_ctl *reset_ctl)
26 {
27         if (reset_ctl->id > (REG_COUNT * BITS_PER_REG))
28                 return -EINVAL;
29
30         return 0;
31 }
32
33 static int meson_reset_level(struct reset_ctl *reset_ctl, bool assert)
34 {
35         struct meson_reset_priv *priv = dev_get_priv(reset_ctl->dev);
36         uint bank = reset_ctl->id / BITS_PER_REG;
37         uint offset = reset_ctl->id % BITS_PER_REG;
38         uint reg_offset = LEVEL_OFFSET + (bank << 2);
39         uint val;
40
41         regmap_read(priv->regmap, reg_offset, &val);
42         if (assert)
43                 val &= ~BIT(offset);
44         else
45                 val |= BIT(offset);
46         regmap_write(priv->regmap, reg_offset, val);
47
48         return 0;
49 }
50
51 static int meson_reset_assert(struct reset_ctl *reset_ctl)
52 {
53         return meson_reset_level(reset_ctl, true);
54 }
55
56 static int meson_reset_deassert(struct reset_ctl *reset_ctl)
57 {
58         return meson_reset_level(reset_ctl, false);
59 }
60
61 struct reset_ops meson_reset_ops = {
62         .request = meson_reset_request,
63         .rst_assert = meson_reset_assert,
64         .rst_deassert = meson_reset_deassert,
65 };
66
67 static const struct udevice_id meson_reset_ids[] = {
68         { .compatible = "amlogic,meson-gxbb-reset" },
69         { .compatible = "amlogic,meson-axg-reset" },
70         { }
71 };
72
73 static int meson_reset_probe(struct udevice *dev)
74 {
75         struct meson_reset_priv *priv = dev_get_priv(dev);
76
77         return regmap_init_mem(dev_ofnode(dev), &priv->regmap);
78 }
79
80 U_BOOT_DRIVER(meson_reset) = {
81         .name = "meson_reset",
82         .id = UCLASS_RESET,
83         .of_match = meson_reset_ids,
84         .probe = meson_reset_probe,
85         .ops = &meson_reset_ops,
86         .priv_auto      = sizeof(struct meson_reset_priv),
87 };