39b607d5bdd18d0cee90753e4557338f871fe930
[openwrt/staging/noltari.git] / target / linux / bmips / patches-5.10 / 003-v5.12-reset-add-BCM6345-reset-controller-driver.patch
1 From aac025437f14c1647dc6054b95daeebed34f6971 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
3 Date: Wed, 17 Jun 2020 12:50:35 +0200
4 Subject: [PATCH 3/9] reset: add BCM6345 reset controller driver
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 Add support for resetting blocks through the Linux reset controller
10 subsystem for BCM63xx SoCs.
11
12 Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
13 Reviewed-by: Florian Fainelli <F.fainelli@gmail.com>
14 Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
15 Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
16 ---
17 drivers/reset/Kconfig | 7 ++
18 drivers/reset/Makefile | 1 +
19 drivers/reset/reset-bcm6345.c | 135 ++++++++++++++++++++++++++++++++++
20 3 files changed, 143 insertions(+)
21 create mode 100644 drivers/reset/reset-bcm6345.c
22
23 --- a/drivers/reset/Kconfig
24 +++ b/drivers/reset/Kconfig
25 @@ -35,6 +35,13 @@ config RESET_AXS10X
26 help
27 This enables the reset controller driver for AXS10x.
28
29 +config RESET_BCM6345
30 + bool "BCM6345 Reset Controller"
31 + depends on BMIPS_GENERIC || COMPILE_TEST
32 + default BMIPS_GENERIC
33 + help
34 + This enables the reset controller driver for BCM6345 SoCs.
35 +
36 config RESET_BERLIN
37 bool "Berlin Reset Driver" if COMPILE_TEST
38 default ARCH_BERLIN
39 --- a/drivers/reset/Makefile
40 +++ b/drivers/reset/Makefile
41 @@ -6,6 +6,7 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/
42 obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o
43 obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
44 obj-$(CONFIG_RESET_AXS10X) += reset-axs10x.o
45 +obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o
46 obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
47 obj-$(CONFIG_RESET_BRCMSTB) += reset-brcmstb.o
48 obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o
49 --- /dev/null
50 +++ b/drivers/reset/reset-bcm6345.c
51 @@ -0,0 +1,135 @@
52 +// SPDX-License-Identifier: GPL-2.0-or-later
53 +/*
54 + * BCM6345 Reset Controller Driver
55 + *
56 + * Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com>
57 + */
58 +
59 +#include <linux/delay.h>
60 +#include <linux/init.h>
61 +#include <linux/io.h>
62 +#include <linux/mod_devicetable.h>
63 +#include <linux/platform_device.h>
64 +#include <linux/reset-controller.h>
65 +
66 +#define BCM6345_RESET_NUM 32
67 +#define BCM6345_RESET_SLEEP_MIN_US 10000
68 +#define BCM6345_RESET_SLEEP_MAX_US 20000
69 +
70 +struct bcm6345_reset {
71 + struct reset_controller_dev rcdev;
72 + void __iomem *base;
73 + spinlock_t lock;
74 +};
75 +
76 +static inline struct bcm6345_reset *
77 +to_bcm6345_reset(struct reset_controller_dev *rcdev)
78 +{
79 + return container_of(rcdev, struct bcm6345_reset, rcdev);
80 +}
81 +
82 +static int bcm6345_reset_update(struct reset_controller_dev *rcdev,
83 + unsigned long id, bool assert)
84 +{
85 + struct bcm6345_reset *bcm6345_reset = to_bcm6345_reset(rcdev);
86 + unsigned long flags;
87 + uint32_t val;
88 +
89 + spin_lock_irqsave(&bcm6345_reset->lock, flags);
90 + val = __raw_readl(bcm6345_reset->base);
91 + if (assert)
92 + val &= ~BIT(id);
93 + else
94 + val |= BIT(id);
95 + __raw_writel(val, bcm6345_reset->base);
96 + spin_unlock_irqrestore(&bcm6345_reset->lock, flags);
97 +
98 + return 0;
99 +}
100 +
101 +static int bcm6345_reset_assert(struct reset_controller_dev *rcdev,
102 + unsigned long id)
103 +{
104 + return bcm6345_reset_update(rcdev, id, true);
105 +}
106 +
107 +static int bcm6345_reset_deassert(struct reset_controller_dev *rcdev,
108 + unsigned long id)
109 +{
110 + return bcm6345_reset_update(rcdev, id, false);
111 +}
112 +
113 +static int bcm6345_reset_reset(struct reset_controller_dev *rcdev,
114 + unsigned long id)
115 +{
116 + bcm6345_reset_update(rcdev, id, true);
117 + usleep_range(BCM6345_RESET_SLEEP_MIN_US,
118 + BCM6345_RESET_SLEEP_MAX_US);
119 +
120 + bcm6345_reset_update(rcdev, id, false);
121 + /*
122 + * Ensure component is taken out reset state by sleeping also after
123 + * deasserting the reset. Otherwise, the component may not be ready
124 + * for operation.
125 + */
126 + usleep_range(BCM6345_RESET_SLEEP_MIN_US,
127 + BCM6345_RESET_SLEEP_MAX_US);
128 +
129 + return 0;
130 +}
131 +
132 +static int bcm6345_reset_status(struct reset_controller_dev *rcdev,
133 + unsigned long id)
134 +{
135 + struct bcm6345_reset *bcm6345_reset = to_bcm6345_reset(rcdev);
136 +
137 + return !(__raw_readl(bcm6345_reset->base) & BIT(id));
138 +}
139 +
140 +static struct reset_control_ops bcm6345_reset_ops = {
141 + .assert = bcm6345_reset_assert,
142 + .deassert = bcm6345_reset_deassert,
143 + .reset = bcm6345_reset_reset,
144 + .status = bcm6345_reset_status,
145 +};
146 +
147 +static int bcm6345_reset_probe(struct platform_device *pdev)
148 +{
149 + struct bcm6345_reset *bcm6345_reset;
150 +
151 + bcm6345_reset = devm_kzalloc(&pdev->dev,
152 + sizeof(*bcm6345_reset), GFP_KERNEL);
153 + if (!bcm6345_reset)
154 + return -ENOMEM;
155 +
156 + platform_set_drvdata(pdev, bcm6345_reset);
157 +
158 + bcm6345_reset->base = devm_platform_ioremap_resource(pdev, 0);
159 + if (IS_ERR(bcm6345_reset->base))
160 + return PTR_ERR(bcm6345_reset->base);
161 +
162 + spin_lock_init(&bcm6345_reset->lock);
163 + bcm6345_reset->rcdev.ops = &bcm6345_reset_ops;
164 + bcm6345_reset->rcdev.owner = THIS_MODULE;
165 + bcm6345_reset->rcdev.of_node = pdev->dev.of_node;
166 + bcm6345_reset->rcdev.of_reset_n_cells = 1;
167 + bcm6345_reset->rcdev.nr_resets = BCM6345_RESET_NUM;
168 +
169 + return devm_reset_controller_register(&pdev->dev,
170 + &bcm6345_reset->rcdev);
171 +}
172 +
173 +static const struct of_device_id bcm6345_reset_of_match[] = {
174 + { .compatible = "brcm,bcm6345-reset" },
175 + { /* sentinel */ },
176 +};
177 +
178 +static struct platform_driver bcm6345_reset_driver = {
179 + .probe = bcm6345_reset_probe,
180 + .driver = {
181 + .name = "bcm6345-reset",
182 + .of_match_table = bcm6345_reset_of_match,
183 + .suppress_bind_attrs = true,
184 + },
185 +};
186 +builtin_platform_driver(bcm6345_reset_driver);