1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Simple Reset Controller Driver
5 * Copyright (C) 2017 Pengutronix, Philipp Zabel <kernel@pengutronix.de>
7 * Based on Allwinner SoCs Reset Controller driver
9 * Copyright 2013 Maxime Ripard
11 * Maxime Ripard <maxime.ripard@free-electrons.com>
14 #include <linux/delay.h>
15 #include <linux/device.h>
16 #include <linux/err.h>
19 #include <linux/of_device.h>
20 #include <linux/platform_device.h>
21 #include <linux/reset-controller.h>
22 #include <linux/reset/reset-simple.h>
23 #include <linux/spinlock.h>
25 static inline struct reset_simple_data
*
26 to_reset_simple_data(struct reset_controller_dev
*rcdev
)
28 return container_of(rcdev
, struct reset_simple_data
, rcdev
);
31 static int reset_simple_update(struct reset_controller_dev
*rcdev
,
32 unsigned long id
, bool assert)
34 struct reset_simple_data
*data
= to_reset_simple_data(rcdev
);
35 int reg_width
= sizeof(u32
);
36 int bank
= id
/ (reg_width
* BITS_PER_BYTE
);
37 int offset
= id
% (reg_width
* BITS_PER_BYTE
);
41 spin_lock_irqsave(&data
->lock
, flags
);
43 reg
= readl(data
->membase
+ (bank
* reg_width
));
44 if (assert ^ data
->active_low
)
48 writel(reg
, data
->membase
+ (bank
* reg_width
));
50 spin_unlock_irqrestore(&data
->lock
, flags
);
55 static int reset_simple_assert(struct reset_controller_dev
*rcdev
,
58 return reset_simple_update(rcdev
, id
, true);
61 static int reset_simple_deassert(struct reset_controller_dev
*rcdev
,
64 return reset_simple_update(rcdev
, id
, false);
67 static int reset_simple_reset(struct reset_controller_dev
*rcdev
,
70 struct reset_simple_data
*data
= to_reset_simple_data(rcdev
);
76 ret
= reset_simple_assert(rcdev
, id
);
80 usleep_range(data
->reset_us
, data
->reset_us
* 2);
82 return reset_simple_deassert(rcdev
, id
);
85 static int reset_simple_status(struct reset_controller_dev
*rcdev
,
88 struct reset_simple_data
*data
= to_reset_simple_data(rcdev
);
89 int reg_width
= sizeof(u32
);
90 int bank
= id
/ (reg_width
* BITS_PER_BYTE
);
91 int offset
= id
% (reg_width
* BITS_PER_BYTE
);
94 reg
= readl(data
->membase
+ (bank
* reg_width
));
96 return !(reg
& BIT(offset
)) ^ !data
->status_active_low
;
99 const struct reset_control_ops reset_simple_ops
= {
100 .assert = reset_simple_assert
,
101 .deassert
= reset_simple_deassert
,
102 .reset
= reset_simple_reset
,
103 .status
= reset_simple_status
,
105 EXPORT_SYMBOL_GPL(reset_simple_ops
);
108 * struct reset_simple_devdata - simple reset controller properties
109 * @reg_offset: offset between base address and first reset register.
110 * @nr_resets: number of resets. If not set, default to resource size in bits.
111 * @active_low: if true, bits are cleared to assert the reset. Otherwise, bits
112 * are set to assert the reset.
113 * @status_active_low: if true, bits read back as cleared while the reset is
114 * asserted. Otherwise, bits read back as set while the
117 struct reset_simple_devdata
{
121 bool status_active_low
;
124 #define SOCFPGA_NR_BANKS 8
126 static const struct reset_simple_devdata reset_simple_socfpga
= {
128 .nr_resets
= SOCFPGA_NR_BANKS
* 32,
129 .status_active_low
= true,
132 static const struct reset_simple_devdata reset_simple_active_low
= {
134 .status_active_low
= true,
137 static const struct of_device_id reset_simple_dt_ids
[] = {
138 { .compatible
= "altr,stratix10-rst-mgr",
139 .data
= &reset_simple_socfpga
},
140 { .compatible
= "st,stm32-rcc", },
141 { .compatible
= "allwinner,sun6i-a31-clock-reset",
142 .data
= &reset_simple_active_low
},
143 { .compatible
= "zte,zx296718-reset",
144 .data
= &reset_simple_active_low
},
145 { .compatible
= "aspeed,ast2400-lpc-reset" },
146 { .compatible
= "aspeed,ast2500-lpc-reset" },
147 { .compatible
= "bitmain,bm1880-reset",
148 .data
= &reset_simple_active_low
},
149 { .compatible
= "snps,dw-high-reset" },
150 { .compatible
= "snps,dw-low-reset",
151 .data
= &reset_simple_active_low
},
155 static int reset_simple_probe(struct platform_device
*pdev
)
157 struct device
*dev
= &pdev
->dev
;
158 const struct reset_simple_devdata
*devdata
;
159 struct reset_simple_data
*data
;
160 void __iomem
*membase
;
161 struct resource
*res
;
164 devdata
= of_device_get_match_data(dev
);
166 data
= devm_kzalloc(dev
, sizeof(*data
), GFP_KERNEL
);
170 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
171 membase
= devm_ioremap_resource(dev
, res
);
173 return PTR_ERR(membase
);
175 spin_lock_init(&data
->lock
);
176 data
->membase
= membase
;
177 data
->rcdev
.owner
= THIS_MODULE
;
178 data
->rcdev
.nr_resets
= resource_size(res
) * BITS_PER_BYTE
;
179 data
->rcdev
.ops
= &reset_simple_ops
;
180 data
->rcdev
.of_node
= dev
->of_node
;
183 reg_offset
= devdata
->reg_offset
;
184 if (devdata
->nr_resets
)
185 data
->rcdev
.nr_resets
= devdata
->nr_resets
;
186 data
->active_low
= devdata
->active_low
;
187 data
->status_active_low
= devdata
->status_active_low
;
190 data
->membase
+= reg_offset
;
192 return devm_reset_controller_register(dev
, &data
->rcdev
);
195 static struct platform_driver reset_simple_driver
= {
196 .probe
= reset_simple_probe
,
198 .name
= "simple-reset",
199 .of_match_table
= reset_simple_dt_ids
,
202 builtin_platform_driver(reset_simple_driver
);