blob: 9d0c8b354f4a0e182fdecc9bf31d17f48d2871c2 [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>
Simon Glass0f2af882020-05-10 11:40:05 -060011#include <log.h>
Simon Glass9bc15642020-02-03 07:36:16 -070012#include <malloc.h>
Neil Armstrong4f03d6b2018-03-29 14:55:25 +020013#include <reset-uclass.h>
14#include <regmap.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060015#include <linux/bitops.h>
Alexey Romanovafa70ba2023-10-05 11:54:23 +030016#include <linux/delay.h>
Neil Armstrong4f03d6b2018-03-29 14:55:25 +020017
Neil Armstrong4f03d6b2018-03-29 14:55:25 +020018#define BITS_PER_REG 32
Alexey Romanovafa70ba2023-10-05 11:54:23 +030019
20struct meson_reset_drvdata {
21 unsigned int reg_count;
22 unsigned int level_offset;
23};
Neil Armstrong4f03d6b2018-03-29 14:55:25 +020024
25struct meson_reset_priv {
26 struct regmap *regmap;
Alexey Romanovafa70ba2023-10-05 11:54:23 +030027 struct meson_reset_drvdata *drvdata;
Neil Armstrong4f03d6b2018-03-29 14:55:25 +020028};
29
30static int meson_reset_request(struct reset_ctl *reset_ctl)
31{
Alexey Romanovafa70ba2023-10-05 11:54:23 +030032 struct meson_reset_priv *priv = dev_get_priv(reset_ctl->dev);
33 struct meson_reset_drvdata *data = priv->drvdata;
34
35 if (reset_ctl->id > (data->reg_count * BITS_PER_REG))
Neil Armstrong4f03d6b2018-03-29 14:55:25 +020036 return -EINVAL;
37
38 return 0;
39}
40
Neil Armstrong4f03d6b2018-03-29 14:55:25 +020041static int meson_reset_level(struct reset_ctl *reset_ctl, bool assert)
42{
43 struct meson_reset_priv *priv = dev_get_priv(reset_ctl->dev);
Alexey Romanovafa70ba2023-10-05 11:54:23 +030044 struct meson_reset_drvdata *data = priv->drvdata;
Neil Armstrong4f03d6b2018-03-29 14:55:25 +020045 uint bank = reset_ctl->id / BITS_PER_REG;
46 uint offset = reset_ctl->id % BITS_PER_REG;
Alexey Romanovafa70ba2023-10-05 11:54:23 +030047 uint reg_offset = data->level_offset + (bank << 2);
Neil Armstrong4f03d6b2018-03-29 14:55:25 +020048 uint val;
49
50 regmap_read(priv->regmap, reg_offset, &val);
51 if (assert)
52 val &= ~BIT(offset);
53 else
54 val |= BIT(offset);
55 regmap_write(priv->regmap, reg_offset, val);
56
57 return 0;
58}
59
60static int meson_reset_assert(struct reset_ctl *reset_ctl)
61{
62 return meson_reset_level(reset_ctl, true);
63}
64
65static int meson_reset_deassert(struct reset_ctl *reset_ctl)
66{
67 return meson_reset_level(reset_ctl, false);
68}
69
70struct reset_ops meson_reset_ops = {
71 .request = meson_reset_request,
Neil Armstrong4f03d6b2018-03-29 14:55:25 +020072 .rst_assert = meson_reset_assert,
73 .rst_deassert = meson_reset_deassert,
74};
75
Alexey Romanovafa70ba2023-10-05 11:54:23 +030076static const struct meson_reset_drvdata meson_gxbb_data = {
77 .reg_count = 8,
78 .level_offset = 0x7c,
79};
80
81static const struct meson_reset_drvdata meson_a1_data = {
82 .reg_count = 3,
83 .level_offset = 0x40,
84};
85
Wolfgang Denk9d328a62021-09-27 17:42:38 +020086static const struct udevice_id meson_reset_ids[] = {
Alexey Romanovafa70ba2023-10-05 11:54:23 +030087 {
88 .compatible = "amlogic,meson-gxbb-reset",
89 .data = (ulong)&meson_gxbb_data,
90 },
91 {
92 .compatible = "amlogic,meson-axg-reset",
93 .data = (ulong)&meson_gxbb_data,
94 },
95 {
96 .compatible = "amlogic,meson-a1-reset",
97 .data = (ulong)&meson_a1_data,
98 },
Wolfgang Denk9d328a62021-09-27 17:42:38 +020099 { }
100};
Neil Armstrong4f03d6b2018-03-29 14:55:25 +0200101
102static int meson_reset_probe(struct udevice *dev)
103{
104 struct meson_reset_priv *priv = dev_get_priv(dev);
Alexey Romanovafa70ba2023-10-05 11:54:23 +0300105 priv->drvdata = (struct meson_reset_drvdata *)dev_get_driver_data(dev);
Wolfgang Denk9d328a62021-09-27 17:42:38 +0200106
Masahiro Yamadae4873e32018-04-19 12:14:03 +0900107 return regmap_init_mem(dev_ofnode(dev), &priv->regmap);
Neil Armstrong4f03d6b2018-03-29 14:55:25 +0200108}
109
110U_BOOT_DRIVER(meson_reset) = {
111 .name = "meson_reset",
112 .id = UCLASS_RESET,
113 .of_match = meson_reset_ids,
114 .probe = meson_reset_probe,
115 .ops = &meson_reset_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700116 .priv_auto = sizeof(struct meson_reset_priv),
Neil Armstrong4f03d6b2018-03-29 14:55:25 +0200117};