blob: 64bc696f137278756220b5b90c10e3660ab5b073 [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>
Neil Armstrong4f03d6b2018-03-29 14:55:25 +020016
17#define REG_COUNT 8
18#define BITS_PER_REG 32
19#define LEVEL_OFFSET 0x7c
20
21struct meson_reset_priv {
22 struct regmap *regmap;
23};
24
25static 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
Neil Armstrong4f03d6b2018-03-29 14:55:25 +020033static 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
51static int meson_reset_assert(struct reset_ctl *reset_ctl)
52{
53 return meson_reset_level(reset_ctl, true);
54}
55
56static int meson_reset_deassert(struct reset_ctl *reset_ctl)
57{
58 return meson_reset_level(reset_ctl, false);
59}
60
61struct reset_ops meson_reset_ops = {
62 .request = meson_reset_request,
Neil Armstrong4f03d6b2018-03-29 14:55:25 +020063 .rst_assert = meson_reset_assert,
64 .rst_deassert = meson_reset_deassert,
65};
66
Wolfgang Denk9d328a62021-09-27 17:42:38 +020067static const struct udevice_id meson_reset_ids[] = {
68 { .compatible = "amlogic,meson-gxbb-reset" },
Neil Armstrongcbf5ea52019-03-26 11:25:44 +010069 { .compatible = "amlogic,meson-axg-reset" },
Wolfgang Denk9d328a62021-09-27 17:42:38 +020070 { }
71};
Neil Armstrong4f03d6b2018-03-29 14:55:25 +020072
73static int meson_reset_probe(struct udevice *dev)
74{
75 struct meson_reset_priv *priv = dev_get_priv(dev);
Wolfgang Denk9d328a62021-09-27 17:42:38 +020076
Masahiro Yamadae4873e32018-04-19 12:14:03 +090077 return regmap_init_mem(dev_ofnode(dev), &priv->regmap);
Neil Armstrong4f03d6b2018-03-29 14:55:25 +020078}
79
80U_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,
Simon Glass8a2b47f2020-12-03 16:55:17 -070086 .priv_auto = sizeof(struct meson_reset_priv),
Neil Armstrong4f03d6b2018-03-29 14:55:25 +020087};