Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.9.
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Reset driver for the StarFive JH7100 SoC
  4 *
  5 * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
  6 */
  7
  8#include <linux/bitmap.h>
  9#include <linux/io.h>
 10#include <linux/io-64-nonatomic-lo-hi.h>
 11#include <linux/iopoll.h>
 12#include <linux/mod_devicetable.h>
 13#include <linux/platform_device.h>
 14#include <linux/reset-controller.h>
 15#include <linux/spinlock.h>
 16
 17#include <dt-bindings/reset/starfive-jh7100.h>
 18
 19/* register offsets */
 20#define JH7100_RESET_ASSERT0	0x00
 21#define JH7100_RESET_ASSERT1	0x04
 22#define JH7100_RESET_ASSERT2	0x08
 23#define JH7100_RESET_ASSERT3	0x0c
 24#define JH7100_RESET_STATUS0	0x10
 25#define JH7100_RESET_STATUS1	0x14
 26#define JH7100_RESET_STATUS2	0x18
 27#define JH7100_RESET_STATUS3	0x1c
 28
 29/*
 30 * Writing a 1 to the n'th bit of the m'th ASSERT register asserts
 31 * line 32m + n, and writing a 0 deasserts the same line.
 32 * Most reset lines have their status inverted so a 0 bit in the STATUS
 33 * register means the line is asserted and a 1 means it's deasserted. A few
 34 * lines don't though, so store the expected value of the status registers when
 35 * all lines are asserted.
 36 */
 37static const u64 jh7100_reset_asserted[2] = {
 38	/* STATUS0 */
 39	BIT_ULL_MASK(JH7100_RST_U74) |
 40	BIT_ULL_MASK(JH7100_RST_VP6_DRESET) |
 41	BIT_ULL_MASK(JH7100_RST_VP6_BRESET) |
 42	/* STATUS1 */
 43	BIT_ULL_MASK(JH7100_RST_HIFI4_DRESET) |
 44	BIT_ULL_MASK(JH7100_RST_HIFI4_BRESET),
 45	/* STATUS2 */
 46	BIT_ULL_MASK(JH7100_RST_E24) |
 47	/* STATUS3 */
 48	0,
 49};
 50
 51struct jh7100_reset {
 52	struct reset_controller_dev rcdev;
 53	/* protect registers against concurrent read-modify-write */
 54	spinlock_t lock;
 55	void __iomem *base;
 56};
 57
 58static inline struct jh7100_reset *
 59jh7100_reset_from(struct reset_controller_dev *rcdev)
 60{
 61	return container_of(rcdev, struct jh7100_reset, rcdev);
 62}
 63
 64static int jh7100_reset_update(struct reset_controller_dev *rcdev,
 65			       unsigned long id, bool assert)
 66{
 67	struct jh7100_reset *data = jh7100_reset_from(rcdev);
 68	unsigned long offset = BIT_ULL_WORD(id);
 69	u64 mask = BIT_ULL_MASK(id);
 70	void __iomem *reg_assert = data->base + JH7100_RESET_ASSERT0 + offset * sizeof(u64);
 71	void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64);
 72	u64 done = jh7100_reset_asserted[offset] & mask;
 73	u64 value;
 74	unsigned long flags;
 75	int ret;
 76
 77	if (!assert)
 78		done ^= mask;
 79
 80	spin_lock_irqsave(&data->lock, flags);
 81
 82	value = readq(reg_assert);
 83	if (assert)
 84		value |= mask;
 85	else
 86		value &= ~mask;
 87	writeq(value, reg_assert);
 88
 89	/* if the associated clock is gated, deasserting might otherwise hang forever */
 90	ret = readq_poll_timeout_atomic(reg_status, value, (value & mask) == done, 0, 1000);
 91
 92	spin_unlock_irqrestore(&data->lock, flags);
 93	return ret;
 94}
 95
 96static int jh7100_reset_assert(struct reset_controller_dev *rcdev,
 97			       unsigned long id)
 98{
 99	return jh7100_reset_update(rcdev, id, true);
100}
101
102static int jh7100_reset_deassert(struct reset_controller_dev *rcdev,
103				 unsigned long id)
104{
105	return jh7100_reset_update(rcdev, id, false);
106}
107
108static int jh7100_reset_reset(struct reset_controller_dev *rcdev,
109			      unsigned long id)
110{
111	int ret;
112
113	ret = jh7100_reset_assert(rcdev, id);
114	if (ret)
115		return ret;
116
117	return jh7100_reset_deassert(rcdev, id);
118}
119
120static int jh7100_reset_status(struct reset_controller_dev *rcdev,
121			       unsigned long id)
122{
123	struct jh7100_reset *data = jh7100_reset_from(rcdev);
124	unsigned long offset = BIT_ULL_WORD(id);
125	u64 mask = BIT_ULL_MASK(id);
126	void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64);
127	u64 value = readq(reg_status);
128
129	return !((value ^ jh7100_reset_asserted[offset]) & mask);
130}
131
132static const struct reset_control_ops jh7100_reset_ops = {
133	.assert		= jh7100_reset_assert,
134	.deassert	= jh7100_reset_deassert,
135	.reset		= jh7100_reset_reset,
136	.status		= jh7100_reset_status,
137};
138
139static int __init jh7100_reset_probe(struct platform_device *pdev)
140{
141	struct jh7100_reset *data;
142
143	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
144	if (!data)
145		return -ENOMEM;
146
147	data->base = devm_platform_ioremap_resource(pdev, 0);
148	if (IS_ERR(data->base))
149		return PTR_ERR(data->base);
150
151	data->rcdev.ops = &jh7100_reset_ops;
152	data->rcdev.owner = THIS_MODULE;
153	data->rcdev.nr_resets = JH7100_RSTN_END;
154	data->rcdev.dev = &pdev->dev;
155	data->rcdev.of_node = pdev->dev.of_node;
156	spin_lock_init(&data->lock);
157
158	return devm_reset_controller_register(&pdev->dev, &data->rcdev);
159}
160
161static const struct of_device_id jh7100_reset_dt_ids[] = {
162	{ .compatible = "starfive,jh7100-reset" },
163	{ /* sentinel */ }
164};
165
166static struct platform_driver jh7100_reset_driver = {
167	.driver = {
168		.name = "jh7100-reset",
169		.of_match_table = jh7100_reset_dt_ids,
170		.suppress_bind_attrs = true,
171	},
172};
173builtin_platform_driver_probe(jh7100_reset_driver, jh7100_reset_probe);