xref: /openbmc/u-boot/drivers/reset/reset-uniphier.c (revision 699e831e158a5846778d8bd6af054d4276277cb6)
1 /*
2  * Copyright (C) 2016 Socionext Inc.
3  *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 #include <common.h>
9 #include <dm.h>
10 #include <reset-uclass.h>
11 #include <linux/bitops.h>
12 #include <linux/io.h>
13 #include <linux/sizes.h>
14 
15 struct uniphier_reset_data {
16 	unsigned int id;
17 	unsigned int reg;
18 	unsigned int bit;
19 	unsigned int flags;
20 #define UNIPHIER_RESET_ACTIVE_LOW		BIT(0)
21 };
22 
23 #define UNIPHIER_RESET_ID_END		(unsigned int)(-1)
24 
25 #define UNIPHIER_RESET_END				\
26 	{ .id = UNIPHIER_RESET_ID_END }
27 
28 #define UNIPHIER_RESET(_id, _reg, _bit)			\
29 	{						\
30 		.id = (_id),				\
31 		.reg = (_reg),				\
32 		.bit = (_bit),				\
33 	}
34 
35 #define UNIPHIER_RESETX(_id, _reg, _bit)		\
36 	{						\
37 		.id = (_id),				\
38 		.reg = (_reg),				\
39 		.bit = (_bit),				\
40 		.flags = UNIPHIER_RESET_ACTIVE_LOW,	\
41 	}
42 
43 /* System reset data */
44 static const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
45 	UNIPHIER_RESETX(2, 0x2000, 2),		/* NAND */
46 	UNIPHIER_RESETX(6, 0x2000, 12),		/* ETHER */
47 	UNIPHIER_RESETX(8, 0x2000, 10),		/* STDMAC */
48 	UNIPHIER_RESETX(12, 0x2000, 6),		/* GIO */
49 	UNIPHIER_RESETX(14, 0x2000, 17),	/* USB30 */
50 	UNIPHIER_RESETX(15, 0x2004, 17),	/* USB31 */
51 	UNIPHIER_RESET_END,
52 };
53 
54 static const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
55 	UNIPHIER_RESETX(2, 0x2000, 2),		/* NAND */
56 	UNIPHIER_RESETX(6, 0x2000, 12),		/* ETHER */
57 	UNIPHIER_RESETX(8, 0x2000, 10),		/* STDMAC */
58 	UNIPHIER_RESETX(14, 0x2000, 17),	/* USB30 */
59 	UNIPHIER_RESETX(15, 0x2004, 17),	/* USB31 */
60 	UNIPHIER_RESETX(16, 0x2014, 4),		/* USB30-PHY0 */
61 	UNIPHIER_RESETX(17, 0x2014, 0),		/* USB30-PHY1 */
62 	UNIPHIER_RESETX(18, 0x2014, 2),		/* USB30-PHY2 */
63 	UNIPHIER_RESETX(20, 0x2014, 5),		/* USB31-PHY0 */
64 	UNIPHIER_RESETX(21, 0x2014, 1),		/* USB31-PHY1 */
65 	UNIPHIER_RESETX(28, 0x2014, 12),	/* SATA */
66 	UNIPHIER_RESET(29, 0x2014, 8),		/* SATA-PHY (active high) */
67 	UNIPHIER_RESET_END,
68 };
69 
70 static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
71 	UNIPHIER_RESETX(2, 0x200c, 0),		/* NAND */
72 	UNIPHIER_RESETX(4, 0x200c, 2),		/* eMMC */
73 	UNIPHIER_RESETX(6, 0x200c, 6),		/* ETHER */
74 	UNIPHIER_RESETX(8, 0x200c, 8),		/* STDMAC */
75 	UNIPHIER_RESETX(12, 0x200c, 5),		/* GIO */
76 	UNIPHIER_RESETX(16, 0x200c, 12),	/* USB30-PHY0 */
77 	UNIPHIER_RESETX(17, 0x200c, 13),	/* USB30-PHY1 */
78 	UNIPHIER_RESETX(18, 0x200c, 14),	/* USB30-PHY2 */
79 	UNIPHIER_RESETX(19, 0x200c, 15),	/* USB30-PHY3 */
80 	UNIPHIER_RESET_END,
81 };
82 
83 static const struct uniphier_reset_data uniphier_pxs3_sys_reset_data[] = {
84 	UNIPHIER_RESETX(2, 0x200c, 0),		/* NAND */
85 	UNIPHIER_RESETX(4, 0x200c, 2),		/* eMMC */
86 	UNIPHIER_RESETX(6, 0x200c, 9),		/* ETHER0 */
87 	UNIPHIER_RESETX(7, 0x200c, 10),		/* ETHER1 */
88 	UNIPHIER_RESETX(8, 0x200c, 12),		/* STDMAC */
89 	UNIPHIER_RESETX(12, 0x200c, 5),		/* USB30 (GIO0) */
90 	UNIPHIER_RESETX(13, 0x200c, 6),		/* USB31 (GIO1) */
91 	UNIPHIER_RESETX(16, 0x200c, 16),	/* USB30-PHY */
92 	UNIPHIER_RESETX(20, 0x200c, 17),	/* USB31-PHY */
93 	UNIPHIER_RESET_END,
94 };
95 
96 /* Media I/O reset data */
97 #define UNIPHIER_MIO_RESET_SD(id, ch)			\
98 	UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 0)
99 
100 #define UNIPHIER_MIO_RESET_SD_BRIDGE(id, ch)		\
101 	UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 26)
102 
103 #define UNIPHIER_MIO_RESET_EMMC_HW_RESET(id, ch)	\
104 	UNIPHIER_RESETX((id), 0x80 + 0x200 * (ch), 0)
105 
106 #define UNIPHIER_MIO_RESET_USB2(id, ch)			\
107 	UNIPHIER_RESETX((id), 0x114 + 0x200 * (ch), 0)
108 
109 #define UNIPHIER_MIO_RESET_USB2_BRIDGE(id, ch)		\
110 	UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 24)
111 
112 #define UNIPHIER_MIO_RESET_DMAC(id)			\
113 	UNIPHIER_RESETX((id), 0x110, 17)
114 
115 static const struct uniphier_reset_data uniphier_mio_reset_data[] = {
116 	UNIPHIER_MIO_RESET_SD(0, 0),
117 	UNIPHIER_MIO_RESET_SD(1, 1),
118 	UNIPHIER_MIO_RESET_SD(2, 2),
119 	UNIPHIER_MIO_RESET_SD_BRIDGE(3, 0),
120 	UNIPHIER_MIO_RESET_SD_BRIDGE(4, 1),
121 	UNIPHIER_MIO_RESET_SD_BRIDGE(5, 2),
122 	UNIPHIER_MIO_RESET_EMMC_HW_RESET(6, 1),
123 	UNIPHIER_MIO_RESET_DMAC(7),
124 	UNIPHIER_MIO_RESET_USB2(8, 0),
125 	UNIPHIER_MIO_RESET_USB2(9, 1),
126 	UNIPHIER_MIO_RESET_USB2(10, 2),
127 	UNIPHIER_MIO_RESET_USB2(11, 3),
128 	UNIPHIER_MIO_RESET_USB2_BRIDGE(12, 0),
129 	UNIPHIER_MIO_RESET_USB2_BRIDGE(13, 1),
130 	UNIPHIER_MIO_RESET_USB2_BRIDGE(14, 2),
131 	UNIPHIER_MIO_RESET_USB2_BRIDGE(15, 3),
132 	UNIPHIER_RESET_END,
133 };
134 
135 /* Peripheral reset data */
136 #define UNIPHIER_PERI_RESET_UART(id, ch)		\
137 	UNIPHIER_RESETX((id), 0x114, 19 + (ch))
138 
139 #define UNIPHIER_PERI_RESET_I2C(id, ch)			\
140 	UNIPHIER_RESETX((id), 0x114, 5 + (ch))
141 
142 #define UNIPHIER_PERI_RESET_FI2C(id, ch)		\
143 	UNIPHIER_RESETX((id), 0x114, 24 + (ch))
144 
145 static const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
146 	UNIPHIER_PERI_RESET_UART(0, 0),
147 	UNIPHIER_PERI_RESET_UART(1, 1),
148 	UNIPHIER_PERI_RESET_UART(2, 2),
149 	UNIPHIER_PERI_RESET_UART(3, 3),
150 	UNIPHIER_PERI_RESET_I2C(4, 0),
151 	UNIPHIER_PERI_RESET_I2C(5, 1),
152 	UNIPHIER_PERI_RESET_I2C(6, 2),
153 	UNIPHIER_PERI_RESET_I2C(7, 3),
154 	UNIPHIER_PERI_RESET_I2C(8, 4),
155 	UNIPHIER_RESET_END,
156 };
157 
158 static const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = {
159 	UNIPHIER_PERI_RESET_UART(0, 0),
160 	UNIPHIER_PERI_RESET_UART(1, 1),
161 	UNIPHIER_PERI_RESET_UART(2, 2),
162 	UNIPHIER_PERI_RESET_UART(3, 3),
163 	UNIPHIER_PERI_RESET_FI2C(4, 0),
164 	UNIPHIER_PERI_RESET_FI2C(5, 1),
165 	UNIPHIER_PERI_RESET_FI2C(6, 2),
166 	UNIPHIER_PERI_RESET_FI2C(7, 3),
167 	UNIPHIER_PERI_RESET_FI2C(8, 4),
168 	UNIPHIER_PERI_RESET_FI2C(9, 5),
169 	UNIPHIER_PERI_RESET_FI2C(10, 6),
170 	UNIPHIER_RESET_END,
171 };
172 
173 /* core implementaton */
174 struct uniphier_reset_priv {
175 	void __iomem *base;
176 	const struct uniphier_reset_data *data;
177 };
178 
179 static int uniphier_reset_request(struct reset_ctl *reset_ctl)
180 {
181 	return 0;
182 }
183 
184 static int uniphier_reset_free(struct reset_ctl *reset_ctl)
185 {
186 	return 0;
187 }
188 
189 static int uniphier_reset_update(struct reset_ctl *reset_ctl, int assert)
190 {
191 	struct uniphier_reset_priv *priv = dev_get_priv(reset_ctl->dev);
192 	unsigned long id = reset_ctl->id;
193 	const struct uniphier_reset_data *p;
194 
195 	for (p = priv->data; p->id != UNIPHIER_RESET_ID_END; p++) {
196 		u32 mask, val;
197 
198 		if (p->id != id)
199 			continue;
200 
201 		val = readl(priv->base + p->reg);
202 
203 		if (p->flags & UNIPHIER_RESET_ACTIVE_LOW)
204 			assert = !assert;
205 
206 		mask = BIT(p->bit);
207 
208 		if (assert)
209 			val |= mask;
210 		else
211 			val &= ~mask;
212 
213 		writel(val, priv->base + p->reg);
214 
215 		return 0;
216 	}
217 
218 	dev_err(reset_ctl->dev, "reset_id=%lu was not handled\n", id);
219 
220 	return -EINVAL;
221 }
222 
223 static int uniphier_reset_assert(struct reset_ctl *reset_ctl)
224 {
225 	return uniphier_reset_update(reset_ctl, 1);
226 }
227 
228 static int uniphier_reset_deassert(struct reset_ctl *reset_ctl)
229 {
230 	return uniphier_reset_update(reset_ctl, 0);
231 }
232 
233 static const struct reset_ops uniphier_reset_ops = {
234 	.request = uniphier_reset_request,
235 	.free = uniphier_reset_free,
236 	.rst_assert = uniphier_reset_assert,
237 	.rst_deassert = uniphier_reset_deassert,
238 };
239 
240 static int uniphier_reset_probe(struct udevice *dev)
241 {
242 	struct uniphier_reset_priv *priv = dev_get_priv(dev);
243 	fdt_addr_t addr;
244 
245 	addr = devfdt_get_addr(dev->parent);
246 	if (addr == FDT_ADDR_T_NONE)
247 		return -EINVAL;
248 
249 	priv->base = devm_ioremap(dev, addr, SZ_4K);
250 	if (!priv->base)
251 		return -ENOMEM;
252 
253 	priv->data = (void *)dev_get_driver_data(dev);
254 
255 	return 0;
256 }
257 
258 static const struct udevice_id uniphier_reset_match[] = {
259 	/* System reset */
260 	{
261 		.compatible = "socionext,uniphier-ld4-reset",
262 		.data = (ulong)uniphier_pro4_sys_reset_data,
263 	},
264 	{
265 		.compatible = "socionext,uniphier-pro4-reset",
266 		.data = (ulong)uniphier_pro4_sys_reset_data,
267 	},
268 	{
269 		.compatible = "socionext,uniphier-sld8-reset",
270 		.data = (ulong)uniphier_pro4_sys_reset_data,
271 	},
272 	{
273 		.compatible = "socionext,uniphier-pro5-reset",
274 		.data = (ulong)uniphier_pro4_sys_reset_data,
275 	},
276 	{
277 		.compatible = "socionext,uniphier-pxs2-reset",
278 		.data = (ulong)uniphier_pxs2_sys_reset_data,
279 	},
280 	{
281 		.compatible = "socionext,uniphier-ld11-reset",
282 		.data = (ulong)uniphier_ld20_sys_reset_data,
283 	},
284 	{
285 		.compatible = "socionext,uniphier-ld20-reset",
286 		.data = (ulong)uniphier_ld20_sys_reset_data,
287 	},
288 	{
289 		.compatible = "socionext,uniphier-pxs3-reset",
290 		.data = (ulong)uniphier_pxs3_sys_reset_data,
291 	},
292 	/* Media I/O reset */
293 	{
294 		.compatible = "socionext,uniphier-ld4-mio-reset",
295 		.data = (ulong)uniphier_mio_reset_data,
296 	},
297 	{
298 		.compatible = "socionext,uniphier-pro4-mio-reset",
299 		.data = (ulong)uniphier_mio_reset_data,
300 	},
301 	{
302 		.compatible = "socionext,uniphier-sld8-mio-reset",
303 		.data = (ulong)uniphier_mio_reset_data,
304 	},
305 	{
306 		.compatible = "socionext,uniphier-pro5-mio-reset",
307 		.data = (ulong)uniphier_mio_reset_data,
308 	},
309 	{
310 		.compatible = "socionext,uniphier-pxs2-mio-reset",
311 		.data = (ulong)uniphier_mio_reset_data,
312 	},
313 	{
314 		.compatible = "socionext,uniphier-ld11-mio-reset",
315 		.data = (ulong)uniphier_mio_reset_data,
316 	},
317 	{
318 		.compatible = "socionext,uniphier-ld11-sd-reset",
319 		.data = (ulong)uniphier_mio_reset_data,
320 	},
321 	{
322 		.compatible = "socionext,uniphier-ld20-sd-reset",
323 		.data = (ulong)uniphier_mio_reset_data,
324 	},
325 	{
326 		.compatible = "socionext,uniphier-pxs3-sd-reset",
327 		.data = (ulong)uniphier_mio_reset_data,
328 	},
329 	/* Peripheral reset */
330 	{
331 		.compatible = "socionext,uniphier-ld4-peri-reset",
332 		.data = (ulong)uniphier_ld4_peri_reset_data,
333 	},
334 	{
335 		.compatible = "socionext,uniphier-pro4-peri-reset",
336 		.data = (ulong)uniphier_pro4_peri_reset_data,
337 	},
338 	{
339 		.compatible = "socionext,uniphier-sld8-peri-reset",
340 		.data = (ulong)uniphier_ld4_peri_reset_data,
341 	},
342 	{
343 		.compatible = "socionext,uniphier-pro5-peri-reset",
344 		.data = (ulong)uniphier_pro4_peri_reset_data,
345 	},
346 	{
347 		.compatible = "socionext,uniphier-pxs2-peri-reset",
348 		.data = (ulong)uniphier_pro4_peri_reset_data,
349 	},
350 	{
351 		.compatible = "socionext,uniphier-ld11-peri-reset",
352 		.data = (ulong)uniphier_pro4_peri_reset_data,
353 	},
354 	{
355 		.compatible = "socionext,uniphier-ld20-peri-reset",
356 		.data = (ulong)uniphier_pro4_peri_reset_data,
357 	},
358 	{
359 		.compatible = "socionext,uniphier-pxs3-peri-reset",
360 		.data = (ulong)uniphier_pro4_peri_reset_data,
361 	},
362 	{ /* sentinel */ }
363 };
364 
365 U_BOOT_DRIVER(uniphier_reset) = {
366 	.name = "uniphier-reset",
367 	.id = UCLASS_RESET,
368 	.of_match = uniphier_reset_match,
369 	.probe = uniphier_reset_probe,
370 	.priv_auto_alloc_size = sizeof(struct uniphier_reset_priv),
371 	.ops = &uniphier_reset_ops,
372 };
373