blob: 6337cdaaffa2ba5b1d8ee72693ff752ff372fba5 [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
Neil Armstrong20367bb2018-03-29 14:55:25 +02009#include <dm.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060010#include <log.h>
Simon Glass336d4612020-02-03 07:36:16 -070011#include <malloc.h>
Neil Armstrong20367bb2018-03-29 14:55:25 +020012#include <reset-uclass.h>
13#include <regmap.h>
Simon Glasscd93d622020-05-10 11:40:13 -060014#include <linux/bitops.h>
Alexey Romanovcffe3122023-10-05 11:54:23 +030015#include <linux/delay.h>
Neil Armstrong20367bb2018-03-29 14:55:25 +020016
Neil Armstrong20367bb2018-03-29 14:55:25 +020017#define BITS_PER_REG 32
Alexey Romanovcffe3122023-10-05 11:54:23 +030018
19struct meson_reset_drvdata {
20 unsigned int reg_count;
21 unsigned int level_offset;
22};
Neil Armstrong20367bb2018-03-29 14:55:25 +020023
24struct meson_reset_priv {
25 struct regmap *regmap;
Alexey Romanovcffe3122023-10-05 11:54:23 +030026 struct meson_reset_drvdata *drvdata;
Neil Armstrong20367bb2018-03-29 14:55:25 +020027};
28
29static int meson_reset_request(struct reset_ctl *reset_ctl)
30{
Alexey Romanovcffe3122023-10-05 11:54:23 +030031 struct meson_reset_priv *priv = dev_get_priv(reset_ctl->dev);
32 struct meson_reset_drvdata *data = priv->drvdata;
33
34 if (reset_ctl->id > (data->reg_count * BITS_PER_REG))
Neil Armstrong20367bb2018-03-29 14:55:25 +020035 return -EINVAL;
36
37 return 0;
38}
39
Neil Armstrong20367bb2018-03-29 14:55:25 +020040static int meson_reset_level(struct reset_ctl *reset_ctl, bool assert)
41{
42 struct meson_reset_priv *priv = dev_get_priv(reset_ctl->dev);
Alexey Romanovcffe3122023-10-05 11:54:23 +030043 struct meson_reset_drvdata *data = priv->drvdata;
Neil Armstrong20367bb2018-03-29 14:55:25 +020044 uint bank = reset_ctl->id / BITS_PER_REG;
45 uint offset = reset_ctl->id % BITS_PER_REG;
Alexey Romanovcffe3122023-10-05 11:54:23 +030046 uint reg_offset = data->level_offset + (bank << 2);
Neil Armstrong20367bb2018-03-29 14:55:25 +020047 uint val;
48
49 regmap_read(priv->regmap, reg_offset, &val);
50 if (assert)
51 val &= ~BIT(offset);
52 else
53 val |= BIT(offset);
54 regmap_write(priv->regmap, reg_offset, val);
55
56 return 0;
57}
58
59static int meson_reset_assert(struct reset_ctl *reset_ctl)
60{
61 return meson_reset_level(reset_ctl, true);
62}
63
64static int meson_reset_deassert(struct reset_ctl *reset_ctl)
65{
66 return meson_reset_level(reset_ctl, false);
67}
68
69struct reset_ops meson_reset_ops = {
70 .request = meson_reset_request,
Neil Armstrong20367bb2018-03-29 14:55:25 +020071 .rst_assert = meson_reset_assert,
72 .rst_deassert = meson_reset_deassert,
73};
74
Alexey Romanovcffe3122023-10-05 11:54:23 +030075static const struct meson_reset_drvdata meson_gxbb_data = {
76 .reg_count = 8,
77 .level_offset = 0x7c,
78};
79
80static const struct meson_reset_drvdata meson_a1_data = {
81 .reg_count = 3,
82 .level_offset = 0x40,
83};
84
Wolfgang Denk0a50b3c2021-09-27 17:42:38 +020085static const struct udevice_id meson_reset_ids[] = {
Alexey Romanovcffe3122023-10-05 11:54:23 +030086 {
87 .compatible = "amlogic,meson-gxbb-reset",
88 .data = (ulong)&meson_gxbb_data,
89 },
90 {
91 .compatible = "amlogic,meson-axg-reset",
92 .data = (ulong)&meson_gxbb_data,
93 },
94 {
95 .compatible = "amlogic,meson-a1-reset",
96 .data = (ulong)&meson_a1_data,
97 },
Wolfgang Denk0a50b3c2021-09-27 17:42:38 +020098 { }
99};
Neil Armstrong20367bb2018-03-29 14:55:25 +0200100
101static int meson_reset_probe(struct udevice *dev)
102{
103 struct meson_reset_priv *priv = dev_get_priv(dev);
Alexey Romanovcffe3122023-10-05 11:54:23 +0300104 priv->drvdata = (struct meson_reset_drvdata *)dev_get_driver_data(dev);
Wolfgang Denk0a50b3c2021-09-27 17:42:38 +0200105
Masahiro Yamadad3581232018-04-19 12:14:03 +0900106 return regmap_init_mem(dev_ofnode(dev), &priv->regmap);
Neil Armstrong20367bb2018-03-29 14:55:25 +0200107}
108
109U_BOOT_DRIVER(meson_reset) = {
110 .name = "meson_reset",
111 .id = UCLASS_RESET,
112 .of_match = meson_reset_ids,
113 .probe = meson_reset_probe,
114 .ops = &meson_reset_ops,
Simon Glass41575d82020-12-03 16:55:17 -0700115 .priv_auto = sizeof(struct meson_reset_priv),
Neil Armstrong20367bb2018-03-29 14:55:25 +0200116};