blob: 31aa4d41e8d6d4a54c113d5eb7fc1ac538cc68d4 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Neil Armstrong4f03d6b2018-03-29 14:55:25 +02002/*
3 * Amlogic Meson Reset Controller driver
4 *
5 * Copyright (c) 2018 BayLibre, SAS.
6 * Author: Neil Armstrong <narmstrong@baylibre.com>
Neil Armstrong4f03d6b2018-03-29 14:55:25 +02007 */
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
18struct meson_reset_priv {
19 struct regmap *regmap;
20};
21
22static 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
30static int meson_reset_free(struct reset_ctl *reset_ctl)
31{
32 return 0;
33}
34
35static 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
53static int meson_reset_assert(struct reset_ctl *reset_ctl)
54{
55 return meson_reset_level(reset_ctl, true);
56}
57
58static int meson_reset_deassert(struct reset_ctl *reset_ctl)
59{
60 return meson_reset_level(reset_ctl, false);
61}
62
63struct 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
70static const struct udevice_id meson_reset_ids[] = {
71 { .compatible = "amlogic,meson-gxbb-reset" },
Neil Armstrongcbf5ea52019-03-26 11:25:44 +010072 { .compatible = "amlogic,meson-axg-reset" },
Neil Armstrong4f03d6b2018-03-29 14:55:25 +020073 { }
74};
75
76static int meson_reset_probe(struct udevice *dev)
77{
78 struct meson_reset_priv *priv = dev_get_priv(dev);
79
Masahiro Yamadae4873e32018-04-19 12:14:03 +090080 return regmap_init_mem(dev_ofnode(dev), &priv->regmap);
Neil Armstrong4f03d6b2018-03-29 14:55:25 +020081}
82
83U_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};