blob: 461c0ccb7a0b4f6cde711abf7c4389a373e358d8 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Neil Armstrong20367bb2018-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 Armstrong20367bb2018-03-29 14:55:25 +02007 */
8
9#include <common.h>
10#include <dm.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060011#include <log.h>
Simon Glass336d4612020-02-03 07:36:16 -070012#include <malloc.h>
Neil Armstrong20367bb2018-03-29 14:55:25 +020013#include <reset-uclass.h>
14#include <regmap.h>
15
16#define REG_COUNT 8
17#define BITS_PER_REG 32
18#define LEVEL_OFFSET 0x7c
19
20struct meson_reset_priv {
21 struct regmap *regmap;
22};
23
24static int meson_reset_request(struct reset_ctl *reset_ctl)
25{
26 if (reset_ctl->id > (REG_COUNT * BITS_PER_REG))
27 return -EINVAL;
28
29 return 0;
30}
31
32static int meson_reset_free(struct reset_ctl *reset_ctl)
33{
34 return 0;
35}
36
37static int meson_reset_level(struct reset_ctl *reset_ctl, bool assert)
38{
39 struct meson_reset_priv *priv = dev_get_priv(reset_ctl->dev);
40 uint bank = reset_ctl->id / BITS_PER_REG;
41 uint offset = reset_ctl->id % BITS_PER_REG;
42 uint reg_offset = LEVEL_OFFSET + (bank << 2);
43 uint val;
44
45 regmap_read(priv->regmap, reg_offset, &val);
46 if (assert)
47 val &= ~BIT(offset);
48 else
49 val |= BIT(offset);
50 regmap_write(priv->regmap, reg_offset, val);
51
52 return 0;
53}
54
55static int meson_reset_assert(struct reset_ctl *reset_ctl)
56{
57 return meson_reset_level(reset_ctl, true);
58}
59
60static int meson_reset_deassert(struct reset_ctl *reset_ctl)
61{
62 return meson_reset_level(reset_ctl, false);
63}
64
65struct reset_ops meson_reset_ops = {
66 .request = meson_reset_request,
Simon Glass94474b22020-02-03 07:35:52 -070067 .rfree = meson_reset_free,
Neil Armstrong20367bb2018-03-29 14:55:25 +020068 .rst_assert = meson_reset_assert,
69 .rst_deassert = meson_reset_deassert,
70};
71
72static const struct udevice_id meson_reset_ids[] = {
73 { .compatible = "amlogic,meson-gxbb-reset" },
Neil Armstrongfd6b9342019-03-26 11:25:44 +010074 { .compatible = "amlogic,meson-axg-reset" },
Neil Armstrong20367bb2018-03-29 14:55:25 +020075 { }
76};
77
78static int meson_reset_probe(struct udevice *dev)
79{
80 struct meson_reset_priv *priv = dev_get_priv(dev);
81
Masahiro Yamadad3581232018-04-19 12:14:03 +090082 return regmap_init_mem(dev_ofnode(dev), &priv->regmap);
Neil Armstrong20367bb2018-03-29 14:55:25 +020083}
84
85U_BOOT_DRIVER(meson_reset) = {
86 .name = "meson_reset",
87 .id = UCLASS_RESET,
88 .of_match = meson_reset_ids,
89 .probe = meson_reset_probe,
90 .ops = &meson_reset_ops,
91 .priv_auto_alloc_size = sizeof(struct meson_reset_priv),
92};