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