1 From a8051a7daa45056f469686286886968bc62b94df Mon Sep 17 00:00:00 2001
2 From: Emil Renner Berthing <kernel@esmil.dk>
3 Date: Sat, 1 Apr 2023 19:19:21 +0800
4 Subject: [PATCH 009/122] reset: starfive: Factor out common JH71X0 reset code
6 The StarFive JH7100 SoC has additional reset controllers for audio and
7 video, but the registers follow the same structure. On the JH7110 the
8 reset registers don't get their own memory range, but instead follow the
9 clock control registers. The registers still follow the same structure
10 though, so let's factor out the common code to handle all these cases.
12 Tested-by: Tommaso Merciai <tomm.merciai@gmail.com>
13 Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
14 Reviewed-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
15 Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
16 Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
17 Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
19 drivers/reset/starfive/Kconfig | 4 +
20 drivers/reset/starfive/Makefile | 2 +
21 .../reset/starfive/reset-starfive-jh7100.c | 150 +---------------
22 .../reset/starfive/reset-starfive-jh71x0.c | 162 ++++++++++++++++++
23 .../reset/starfive/reset-starfive-jh71x0.h | 11 ++
24 5 files changed, 180 insertions(+), 149 deletions(-)
25 create mode 100644 drivers/reset/starfive/reset-starfive-jh71x0.c
26 create mode 100644 drivers/reset/starfive/reset-starfive-jh71x0.h
28 diff --git a/drivers/reset/starfive/Kconfig b/drivers/reset/starfive/Kconfig
29 index abbf0c52d03e..1927a5a3b53a 100644
30 --- a/drivers/reset/starfive/Kconfig
31 +++ b/drivers/reset/starfive/Kconfig
33 # SPDX-License-Identifier: GPL-2.0-only
35 +config RESET_STARFIVE_JH71X0
38 config RESET_STARFIVE_JH7100
39 bool "StarFive JH7100 Reset Driver"
40 depends on ARCH_STARFIVE || COMPILE_TEST
41 + select RESET_STARFIVE_JH71X0
44 This enables the reset controller driver for the StarFive JH7100 SoC.
45 diff --git a/drivers/reset/starfive/Makefile b/drivers/reset/starfive/Makefile
46 index 670d049423f5..f6aa12466fad 100644
47 --- a/drivers/reset/starfive/Makefile
48 +++ b/drivers/reset/starfive/Makefile
50 # SPDX-License-Identifier: GPL-2.0
51 +obj-$(CONFIG_RESET_STARFIVE_JH71X0) += reset-starfive-jh71x0.o
53 obj-$(CONFIG_RESET_STARFIVE_JH7100) += reset-starfive-jh7100.o
54 diff --git a/drivers/reset/starfive/reset-starfive-jh7100.c b/drivers/reset/starfive/reset-starfive-jh7100.c
55 index fc44b2fb3e03..5a68327c1f6a 100644
56 --- a/drivers/reset/starfive/reset-starfive-jh7100.c
57 +++ b/drivers/reset/starfive/reset-starfive-jh7100.c
59 * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
62 -#include <linux/bitmap.h>
63 -#include <linux/io.h>
64 -#include <linux/io-64-nonatomic-lo-hi.h>
65 -#include <linux/iopoll.h>
66 #include <linux/mod_devicetable.h>
67 #include <linux/platform_device.h>
68 -#include <linux/reset-controller.h>
69 -#include <linux/spinlock.h>
71 -#include <dt-bindings/reset/starfive-jh7100.h>
73 -/* register offsets */
74 -#define JH7100_RESET_ASSERT0 0x00
75 -#define JH7100_RESET_ASSERT1 0x04
76 -#define JH7100_RESET_ASSERT2 0x08
77 -#define JH7100_RESET_ASSERT3 0x0c
78 -#define JH7100_RESET_STATUS0 0x10
79 -#define JH7100_RESET_STATUS1 0x14
80 -#define JH7100_RESET_STATUS2 0x18
81 -#define JH7100_RESET_STATUS3 0x1c
84 - * Writing a 1 to the n'th bit of the m'th ASSERT register asserts
85 - * line 32m + n, and writing a 0 deasserts the same line.
86 - * Most reset lines have their status inverted so a 0 bit in the STATUS
87 - * register means the line is asserted and a 1 means it's deasserted. A few
88 - * lines don't though, so store the expected value of the status registers when
89 - * all lines are asserted.
91 -static const u64 jh7100_reset_asserted[2] = {
93 - BIT_ULL_MASK(JH7100_RST_U74) |
94 - BIT_ULL_MASK(JH7100_RST_VP6_DRESET) |
95 - BIT_ULL_MASK(JH7100_RST_VP6_BRESET) |
97 - BIT_ULL_MASK(JH7100_RST_HIFI4_DRESET) |
98 - BIT_ULL_MASK(JH7100_RST_HIFI4_BRESET),
100 - BIT_ULL_MASK(JH7100_RST_E24) |
105 -struct jh7100_reset {
106 - struct reset_controller_dev rcdev;
107 - /* protect registers against concurrent read-modify-write */
109 - void __iomem *base;
112 -static inline struct jh7100_reset *
113 -jh7100_reset_from(struct reset_controller_dev *rcdev)
115 - return container_of(rcdev, struct jh7100_reset, rcdev);
118 -static int jh7100_reset_update(struct reset_controller_dev *rcdev,
119 - unsigned long id, bool assert)
121 - struct jh7100_reset *data = jh7100_reset_from(rcdev);
122 - unsigned long offset = BIT_ULL_WORD(id);
123 - u64 mask = BIT_ULL_MASK(id);
124 - void __iomem *reg_assert = data->base + JH7100_RESET_ASSERT0 + offset * sizeof(u64);
125 - void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64);
126 - u64 done = jh7100_reset_asserted[offset] & mask;
128 - unsigned long flags;
134 - spin_lock_irqsave(&data->lock, flags);
136 - value = readq(reg_assert);
141 - writeq(value, reg_assert);
143 - /* if the associated clock is gated, deasserting might otherwise hang forever */
144 - ret = readq_poll_timeout_atomic(reg_status, value, (value & mask) == done, 0, 1000);
146 - spin_unlock_irqrestore(&data->lock, flags);
150 -static int jh7100_reset_assert(struct reset_controller_dev *rcdev,
153 - return jh7100_reset_update(rcdev, id, true);
156 -static int jh7100_reset_deassert(struct reset_controller_dev *rcdev,
159 - return jh7100_reset_update(rcdev, id, false);
162 -static int jh7100_reset_reset(struct reset_controller_dev *rcdev,
167 - ret = jh7100_reset_assert(rcdev, id);
171 - return jh7100_reset_deassert(rcdev, id);
174 -static int jh7100_reset_status(struct reset_controller_dev *rcdev,
177 - struct jh7100_reset *data = jh7100_reset_from(rcdev);
178 - unsigned long offset = BIT_ULL_WORD(id);
179 - u64 mask = BIT_ULL_MASK(id);
180 - void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64);
181 - u64 value = readq(reg_status);
183 - return !((value ^ jh7100_reset_asserted[offset]) & mask);
186 -static const struct reset_control_ops jh7100_reset_ops = {
187 - .assert = jh7100_reset_assert,
188 - .deassert = jh7100_reset_deassert,
189 - .reset = jh7100_reset_reset,
190 - .status = jh7100_reset_status,
193 -static int __init jh7100_reset_probe(struct platform_device *pdev)
195 - struct jh7100_reset *data;
197 - data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
201 - data->base = devm_platform_ioremap_resource(pdev, 0);
202 - if (IS_ERR(data->base))
203 - return PTR_ERR(data->base);
205 - data->rcdev.ops = &jh7100_reset_ops;
206 - data->rcdev.owner = THIS_MODULE;
207 - data->rcdev.nr_resets = JH7100_RSTN_END;
208 - data->rcdev.dev = &pdev->dev;
209 - data->rcdev.of_node = pdev->dev.of_node;
210 - spin_lock_init(&data->lock);
212 - return devm_reset_controller_register(&pdev->dev, &data->rcdev);
214 +#include "reset-starfive-jh71x0.h"
216 static const struct of_device_id jh7100_reset_dt_ids[] = {
217 { .compatible = "starfive,jh7100-reset" },
218 diff --git a/drivers/reset/starfive/reset-starfive-jh71x0.c b/drivers/reset/starfive/reset-starfive-jh71x0.c
220 index 000000000000..114a13c4b8a6
222 +++ b/drivers/reset/starfive/reset-starfive-jh71x0.c
224 +// SPDX-License-Identifier: GPL-2.0-or-later
226 + * Reset driver for the StarFive JH7100 SoC
228 + * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
231 +#include <linux/bitmap.h>
232 +#include <linux/device.h>
233 +#include <linux/io.h>
234 +#include <linux/io-64-nonatomic-lo-hi.h>
235 +#include <linux/iopoll.h>
236 +#include <linux/platform_device.h>
237 +#include <linux/reset-controller.h>
238 +#include <linux/spinlock.h>
240 +#include "reset-starfive-jh71x0.h"
242 +#include <dt-bindings/reset/starfive-jh7100.h>
244 +/* register offsets */
245 +#define JH7100_RESET_ASSERT0 0x00
246 +#define JH7100_RESET_ASSERT1 0x04
247 +#define JH7100_RESET_ASSERT2 0x08
248 +#define JH7100_RESET_ASSERT3 0x0c
249 +#define JH7100_RESET_STATUS0 0x10
250 +#define JH7100_RESET_STATUS1 0x14
251 +#define JH7100_RESET_STATUS2 0x18
252 +#define JH7100_RESET_STATUS3 0x1c
255 + * Writing a 1 to the n'th bit of the m'th ASSERT register asserts
256 + * line 32m + n, and writing a 0 deasserts the same line.
257 + * Most reset lines have their status inverted so a 0 bit in the STATUS
258 + * register means the line is asserted and a 1 means it's deasserted. A few
259 + * lines don't though, so store the expected value of the status registers when
260 + * all lines are asserted.
262 +static const u64 jh7100_reset_asserted[2] = {
264 + BIT_ULL_MASK(JH7100_RST_U74) |
265 + BIT_ULL_MASK(JH7100_RST_VP6_DRESET) |
266 + BIT_ULL_MASK(JH7100_RST_VP6_BRESET) |
268 + BIT_ULL_MASK(JH7100_RST_HIFI4_DRESET) |
269 + BIT_ULL_MASK(JH7100_RST_HIFI4_BRESET),
271 + BIT_ULL_MASK(JH7100_RST_E24) |
276 +struct jh7100_reset {
277 + struct reset_controller_dev rcdev;
278 + /* protect registers against concurrent read-modify-write */
280 + void __iomem *base;
283 +static inline struct jh7100_reset *
284 +jh7100_reset_from(struct reset_controller_dev *rcdev)
286 + return container_of(rcdev, struct jh7100_reset, rcdev);
289 +static int jh7100_reset_update(struct reset_controller_dev *rcdev,
290 + unsigned long id, bool assert)
292 + struct jh7100_reset *data = jh7100_reset_from(rcdev);
293 + unsigned long offset = BIT_ULL_WORD(id);
294 + u64 mask = BIT_ULL_MASK(id);
295 + void __iomem *reg_assert = data->base + JH7100_RESET_ASSERT0 + offset * sizeof(u64);
296 + void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64);
297 + u64 done = jh7100_reset_asserted[offset] & mask;
299 + unsigned long flags;
305 + spin_lock_irqsave(&data->lock, flags);
307 + value = readq(reg_assert);
312 + writeq(value, reg_assert);
314 + /* if the associated clock is gated, deasserting might otherwise hang forever */
315 + ret = readq_poll_timeout_atomic(reg_status, value, (value & mask) == done, 0, 1000);
317 + spin_unlock_irqrestore(&data->lock, flags);
321 +static int jh7100_reset_assert(struct reset_controller_dev *rcdev,
324 + return jh7100_reset_update(rcdev, id, true);
327 +static int jh7100_reset_deassert(struct reset_controller_dev *rcdev,
330 + return jh7100_reset_update(rcdev, id, false);
333 +static int jh7100_reset_reset(struct reset_controller_dev *rcdev,
338 + ret = jh7100_reset_assert(rcdev, id);
342 + return jh7100_reset_deassert(rcdev, id);
345 +static int jh7100_reset_status(struct reset_controller_dev *rcdev,
348 + struct jh7100_reset *data = jh7100_reset_from(rcdev);
349 + unsigned long offset = BIT_ULL_WORD(id);
350 + u64 mask = BIT_ULL_MASK(id);
351 + void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64);
352 + u64 value = readq(reg_status);
354 + return !((value ^ jh7100_reset_asserted[offset]) & mask);
357 +static const struct reset_control_ops jh7100_reset_ops = {
358 + .assert = jh7100_reset_assert,
359 + .deassert = jh7100_reset_deassert,
360 + .reset = jh7100_reset_reset,
361 + .status = jh7100_reset_status,
364 +int jh7100_reset_probe(struct platform_device *pdev)
366 + struct jh7100_reset *data;
368 + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
372 + data->base = devm_platform_ioremap_resource(pdev, 0);
373 + if (IS_ERR(data->base))
374 + return PTR_ERR(data->base);
376 + data->rcdev.ops = &jh7100_reset_ops;
377 + data->rcdev.owner = THIS_MODULE;
378 + data->rcdev.nr_resets = JH7100_RSTN_END;
379 + data->rcdev.dev = &pdev->dev;
380 + data->rcdev.of_node = pdev->dev.of_node;
381 + spin_lock_init(&data->lock);
383 + return devm_reset_controller_register(&pdev->dev, &data->rcdev);
385 +EXPORT_SYMBOL_GPL(jh7100_reset_probe);
386 diff --git a/drivers/reset/starfive/reset-starfive-jh71x0.h b/drivers/reset/starfive/reset-starfive-jh71x0.h
388 index 000000000000..318d7a0e096a
390 +++ b/drivers/reset/starfive/reset-starfive-jh71x0.h
392 +/* SPDX-License-Identifier: GPL-2.0-or-later */
394 + * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
397 +#ifndef __RESET_STARFIVE_JH71X0_H
398 +#define __RESET_STARFIVE_JH71X0_H
400 +int jh7100_reset_probe(struct platform_device *pdev);
402 +#endif /* __RESET_STARFIVE_JH71X0_H */