1 | /* |
2 | * Atmel AT91 SAM9 & SAMA5 SoCs reset code |
3 | * |
4 | * Copyright (C) 2007 Atmel Corporation. |
5 | * Copyright (C) BitBox Ltd 2010 |
6 | * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcosoft.com> |
7 | * Copyright (C) 2014 Free Electrons |
8 | * |
9 | * This file is licensed under the terms of the GNU General Public |
10 | * License version 2. This program is licensed "as is" without any |
11 | * warranty of any kind, whether express or implied. |
12 | */ |
13 | |
14 | #include <linux/clk.h> |
15 | #include <linux/io.h> |
16 | #include <linux/module.h> |
17 | #include <linux/of_address.h> |
18 | #include <linux/platform_device.h> |
19 | #include <linux/reboot.h> |
20 | #include <linux/reset-controller.h> |
21 | #include <linux/power/power_on_reason.h> |
22 | |
23 | #include <soc/at91/at91sam9_ddrsdr.h> |
24 | #include <soc/at91/at91sam9_sdramc.h> |
25 | |
26 | #include <dt-bindings/reset/sama7g5-reset.h> |
27 | |
28 | #define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */ |
29 | #define AT91_RSTC_PROCRST BIT(0) /* Processor Reset */ |
30 | #define AT91_RSTC_PERRST BIT(2) /* Peripheral Reset */ |
31 | #define AT91_RSTC_EXTRST BIT(3) /* External Reset */ |
32 | #define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */ |
33 | |
34 | #define AT91_RSTC_SR 0x04 /* Reset Controller Status Register */ |
35 | #define AT91_RSTC_URSTS BIT(0) /* User Reset Status */ |
36 | #define AT91_RSTC_RSTTYP GENMASK(10, 8) /* Reset Type */ |
37 | #define AT91_RSTC_NRSTL BIT(16) /* NRST Pin Level */ |
38 | #define AT91_RSTC_SRCMP BIT(17) /* Software Reset Command in Progress */ |
39 | |
40 | #define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */ |
41 | #define AT91_RSTC_URSTEN BIT(0) /* User Reset Enable */ |
42 | #define AT91_RSTC_URSTASYNC BIT(2) /* User Reset Asynchronous Control */ |
43 | #define AT91_RSTC_URSTIEN BIT(4) /* User Reset Interrupt Enable */ |
44 | #define AT91_RSTC_ERSTL GENMASK(11, 8) /* External Reset Length */ |
45 | |
46 | /** |
47 | * enum reset_type - reset types |
48 | * @RESET_TYPE_GENERAL: first power-up reset |
49 | * @RESET_TYPE_WAKEUP: return from backup mode |
50 | * @RESET_TYPE_WATCHDOG: watchdog fault |
51 | * @RESET_TYPE_SOFTWARE: processor reset required by software |
52 | * @RESET_TYPE_USER: NRST pin detected low |
53 | * @RESET_TYPE_CPU_FAIL: CPU clock failure detection |
54 | * @RESET_TYPE_XTAL_FAIL: 32KHz crystal failure dectection fault |
55 | * @RESET_TYPE_ULP2: ULP2 reset |
56 | */ |
57 | enum reset_type { |
58 | RESET_TYPE_GENERAL = 0, |
59 | RESET_TYPE_WAKEUP = 1, |
60 | RESET_TYPE_WATCHDOG = 2, |
61 | RESET_TYPE_SOFTWARE = 3, |
62 | RESET_TYPE_USER = 4, |
63 | RESET_TYPE_CPU_FAIL = 6, |
64 | RESET_TYPE_XTAL_FAIL = 7, |
65 | RESET_TYPE_ULP2 = 8, |
66 | }; |
67 | |
68 | /** |
69 | * struct at91_reset - AT91 reset specific data structure |
70 | * @rstc_base: base address for system reset |
71 | * @ramc_base: array with base addresses of RAM controllers |
72 | * @dev_base: base address for devices reset |
73 | * @sclk: slow clock |
74 | * @data: platform specific reset data |
75 | * @rcdev: reset controller device |
76 | * @lock: lock for devices reset register access |
77 | * @nb: reset notifier block |
78 | * @args: SoC specific system reset arguments |
79 | * @ramc_lpr: SDRAM Controller Low Power Register |
80 | */ |
81 | struct at91_reset { |
82 | void __iomem *rstc_base; |
83 | void __iomem *ramc_base[2]; |
84 | void __iomem *dev_base; |
85 | struct clk *sclk; |
86 | const struct at91_reset_data *data; |
87 | struct reset_controller_dev rcdev; |
88 | spinlock_t lock; |
89 | struct notifier_block nb; |
90 | u32 args; |
91 | u32 ramc_lpr; |
92 | }; |
93 | |
94 | #define to_at91_reset(r) container_of(r, struct at91_reset, rcdev) |
95 | |
96 | /** |
97 | * struct at91_reset_data - AT91 reset data |
98 | * @reset_args: SoC specific system reset arguments |
99 | * @n_device_reset: number of device resets |
100 | * @device_reset_min_id: min id for device reset |
101 | * @device_reset_max_id: max id for device reset |
102 | */ |
103 | struct at91_reset_data { |
104 | u32 reset_args; |
105 | u32 n_device_reset; |
106 | u8 device_reset_min_id; |
107 | u8 device_reset_max_id; |
108 | }; |
109 | |
110 | /* |
111 | * unless the SDRAM is cleanly shutdown before we hit the |
112 | * reset register it can be left driving the data bus and |
113 | * killing the chance of a subsequent boot from NAND |
114 | */ |
115 | static int at91_reset(struct notifier_block *this, unsigned long mode, |
116 | void *cmd) |
117 | { |
118 | struct at91_reset *reset = container_of(this, struct at91_reset, nb); |
119 | |
120 | asm volatile( |
121 | /* Align to cache lines */ |
122 | ".balign 32\n\t" |
123 | |
124 | /* Disable SDRAM0 accesses */ |
125 | " tst %0, #0\n\t" |
126 | " beq 1f\n\t" |
127 | " str %3, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t" |
128 | /* Power down SDRAM0 */ |
129 | " str %4, [%0, %6]\n\t" |
130 | /* Disable SDRAM1 accesses */ |
131 | "1: tst %1, #0\n\t" |
132 | " strne %3, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t" |
133 | /* Power down SDRAM1 */ |
134 | " strne %4, [%1, %6]\n\t" |
135 | /* Reset CPU */ |
136 | " str %5, [%2, #" __stringify(AT91_RSTC_CR) "]\n\t" |
137 | |
138 | " b .\n\t" |
139 | : |
140 | : "r" (reset->ramc_base[0]), |
141 | "r" (reset->ramc_base[1]), |
142 | "r" (reset->rstc_base), |
143 | "r" (1), |
144 | "r" cpu_to_le32(AT91_DDRSDRC_LPCB_POWER_DOWN), |
145 | "r" (reset->data->reset_args), |
146 | "r" (reset->ramc_lpr) |
147 | ); |
148 | |
149 | return NOTIFY_DONE; |
150 | } |
151 | |
152 | static const char *at91_reset_reason(struct at91_reset *reset) |
153 | { |
154 | u32 reg = readl(addr: reset->rstc_base + AT91_RSTC_SR); |
155 | const char *reason; |
156 | |
157 | switch ((reg & AT91_RSTC_RSTTYP) >> 8) { |
158 | case RESET_TYPE_GENERAL: |
159 | reason = POWER_ON_REASON_REGULAR; |
160 | break; |
161 | case RESET_TYPE_WAKEUP: |
162 | reason = POWER_ON_REASON_RTC; |
163 | break; |
164 | case RESET_TYPE_WATCHDOG: |
165 | reason = POWER_ON_REASON_WATCHDOG; |
166 | break; |
167 | case RESET_TYPE_SOFTWARE: |
168 | reason = POWER_ON_REASON_SOFTWARE; |
169 | break; |
170 | case RESET_TYPE_USER: |
171 | reason = POWER_ON_REASON_RST_BTN; |
172 | break; |
173 | case RESET_TYPE_CPU_FAIL: |
174 | reason = POWER_ON_REASON_CPU_CLK_FAIL; |
175 | break; |
176 | case RESET_TYPE_XTAL_FAIL: |
177 | reason = POWER_ON_REASON_XTAL_FAIL; |
178 | break; |
179 | case RESET_TYPE_ULP2: |
180 | reason = POWER_ON_REASON_BROWN_OUT; |
181 | break; |
182 | default: |
183 | reason = POWER_ON_REASON_UNKNOWN; |
184 | break; |
185 | } |
186 | |
187 | return reason; |
188 | } |
189 | |
190 | static ssize_t power_on_reason_show(struct device *dev, |
191 | struct device_attribute *attr, char *buf) |
192 | { |
193 | struct platform_device *pdev = to_platform_device(dev); |
194 | struct at91_reset *reset = platform_get_drvdata(pdev); |
195 | |
196 | return sprintf(buf, fmt: "%s\n" , at91_reset_reason(reset)); |
197 | } |
198 | static DEVICE_ATTR_RO(power_on_reason); |
199 | |
200 | static const struct of_device_id at91_ramc_of_match[] = { |
201 | { |
202 | .compatible = "atmel,at91sam9260-sdramc" , |
203 | .data = (void *)AT91_SDRAMC_LPR, |
204 | }, |
205 | { |
206 | .compatible = "atmel,at91sam9g45-ddramc" , |
207 | .data = (void *)AT91_DDRSDRC_LPR, |
208 | }, |
209 | { /* sentinel */ } |
210 | }; |
211 | |
212 | static const struct at91_reset_data sam9260 = { |
213 | .reset_args = AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST, |
214 | }; |
215 | |
216 | static const struct at91_reset_data samx7 = { |
217 | .reset_args = AT91_RSTC_KEY | AT91_RSTC_PROCRST, |
218 | }; |
219 | |
220 | static const struct at91_reset_data sama7g5 = { |
221 | .reset_args = AT91_RSTC_KEY | AT91_RSTC_PROCRST, |
222 | .n_device_reset = 3, |
223 | .device_reset_min_id = SAMA7G5_RESET_USB_PHY1, |
224 | .device_reset_max_id = SAMA7G5_RESET_USB_PHY3, |
225 | }; |
226 | |
227 | static const struct of_device_id at91_reset_of_match[] = { |
228 | { |
229 | .compatible = "atmel,at91sam9260-rstc" , |
230 | .data = &sam9260, |
231 | }, |
232 | { |
233 | .compatible = "atmel,at91sam9g45-rstc" , |
234 | .data = &sam9260, |
235 | }, |
236 | { |
237 | .compatible = "atmel,sama5d3-rstc" , |
238 | .data = &sam9260, |
239 | }, |
240 | { |
241 | .compatible = "atmel,samx7-rstc" , |
242 | .data = &samx7, |
243 | }, |
244 | { |
245 | .compatible = "microchip,sam9x60-rstc" , |
246 | .data = &samx7, |
247 | }, |
248 | { |
249 | .compatible = "microchip,sama7g5-rstc" , |
250 | .data = &sama7g5, |
251 | }, |
252 | { /* sentinel */ } |
253 | }; |
254 | MODULE_DEVICE_TABLE(of, at91_reset_of_match); |
255 | |
256 | static int at91_reset_update(struct reset_controller_dev *rcdev, |
257 | unsigned long id, bool assert) |
258 | { |
259 | struct at91_reset *reset = to_at91_reset(rcdev); |
260 | unsigned long flags; |
261 | u32 val; |
262 | |
263 | spin_lock_irqsave(&reset->lock, flags); |
264 | val = readl_relaxed(reset->dev_base); |
265 | if (assert) |
266 | val |= BIT(id); |
267 | else |
268 | val &= ~BIT(id); |
269 | writel_relaxed(val, reset->dev_base); |
270 | spin_unlock_irqrestore(lock: &reset->lock, flags); |
271 | |
272 | return 0; |
273 | } |
274 | |
275 | static int at91_reset_assert(struct reset_controller_dev *rcdev, |
276 | unsigned long id) |
277 | { |
278 | return at91_reset_update(rcdev, id, assert: true); |
279 | } |
280 | |
281 | static int at91_reset_deassert(struct reset_controller_dev *rcdev, |
282 | unsigned long id) |
283 | { |
284 | return at91_reset_update(rcdev, id, assert: false); |
285 | } |
286 | |
287 | static int at91_reset_dev_status(struct reset_controller_dev *rcdev, |
288 | unsigned long id) |
289 | { |
290 | struct at91_reset *reset = to_at91_reset(rcdev); |
291 | u32 val; |
292 | |
293 | val = readl_relaxed(reset->dev_base); |
294 | |
295 | return !!(val & BIT(id)); |
296 | } |
297 | |
298 | static const struct reset_control_ops at91_reset_ops = { |
299 | .assert = at91_reset_assert, |
300 | .deassert = at91_reset_deassert, |
301 | .status = at91_reset_dev_status, |
302 | }; |
303 | |
304 | static int at91_reset_of_xlate(struct reset_controller_dev *rcdev, |
305 | const struct of_phandle_args *reset_spec) |
306 | { |
307 | struct at91_reset *reset = to_at91_reset(rcdev); |
308 | |
309 | if (!reset->data->n_device_reset || |
310 | (reset_spec->args[0] < reset->data->device_reset_min_id || |
311 | reset_spec->args[0] > reset->data->device_reset_max_id)) |
312 | return -EINVAL; |
313 | |
314 | return reset_spec->args[0]; |
315 | } |
316 | |
317 | static int at91_rcdev_init(struct at91_reset *reset, |
318 | struct platform_device *pdev) |
319 | { |
320 | if (!reset->data->n_device_reset) |
321 | return 0; |
322 | |
323 | reset->dev_base = devm_of_iomap(dev: &pdev->dev, node: pdev->dev.of_node, index: 1, |
324 | NULL); |
325 | if (IS_ERR(ptr: reset->dev_base)) |
326 | return -ENODEV; |
327 | |
328 | spin_lock_init(&reset->lock); |
329 | reset->rcdev.ops = &at91_reset_ops; |
330 | reset->rcdev.owner = THIS_MODULE; |
331 | reset->rcdev.of_node = pdev->dev.of_node; |
332 | reset->rcdev.nr_resets = reset->data->n_device_reset; |
333 | reset->rcdev.of_reset_n_cells = 1; |
334 | reset->rcdev.of_xlate = at91_reset_of_xlate; |
335 | |
336 | return devm_reset_controller_register(dev: &pdev->dev, rcdev: &reset->rcdev); |
337 | } |
338 | |
339 | static int at91_reset_probe(struct platform_device *pdev) |
340 | { |
341 | const struct of_device_id *match; |
342 | struct at91_reset *reset; |
343 | struct device_node *np; |
344 | int ret, idx = 0; |
345 | |
346 | reset = devm_kzalloc(dev: &pdev->dev, size: sizeof(*reset), GFP_KERNEL); |
347 | if (!reset) |
348 | return -ENOMEM; |
349 | |
350 | reset->rstc_base = devm_of_iomap(dev: &pdev->dev, node: pdev->dev.of_node, index: 0, NULL); |
351 | if (IS_ERR(ptr: reset->rstc_base)) { |
352 | dev_err(&pdev->dev, "Could not map reset controller address\n" ); |
353 | return -ENODEV; |
354 | } |
355 | |
356 | if (!of_device_is_compatible(device: pdev->dev.of_node, "atmel,sama5d3-rstc" )) { |
357 | /* we need to shutdown the ddr controller, so get ramc base */ |
358 | for_each_matching_node_and_match(np, at91_ramc_of_match, &match) { |
359 | reset->ramc_lpr = (u32)match->data; |
360 | reset->ramc_base[idx] = devm_of_iomap(dev: &pdev->dev, node: np, index: 0, NULL); |
361 | if (IS_ERR(ptr: reset->ramc_base[idx])) { |
362 | dev_err(&pdev->dev, "Could not map ram controller address\n" ); |
363 | of_node_put(node: np); |
364 | return -ENODEV; |
365 | } |
366 | idx++; |
367 | } |
368 | } |
369 | |
370 | reset->data = device_get_match_data(dev: &pdev->dev); |
371 | if (!reset->data) |
372 | return -ENODEV; |
373 | |
374 | reset->nb.notifier_call = at91_reset; |
375 | reset->nb.priority = 192; |
376 | |
377 | reset->sclk = devm_clk_get(dev: &pdev->dev, NULL); |
378 | if (IS_ERR(ptr: reset->sclk)) |
379 | return PTR_ERR(ptr: reset->sclk); |
380 | |
381 | ret = clk_prepare_enable(clk: reset->sclk); |
382 | if (ret) { |
383 | dev_err(&pdev->dev, "Could not enable slow clock\n" ); |
384 | return ret; |
385 | } |
386 | |
387 | platform_set_drvdata(pdev, data: reset); |
388 | |
389 | ret = at91_rcdev_init(reset, pdev); |
390 | if (ret) |
391 | goto disable_clk; |
392 | |
393 | if (of_device_is_compatible(device: pdev->dev.of_node, "microchip,sam9x60-rstc" )) { |
394 | u32 val = readl(addr: reset->rstc_base + AT91_RSTC_MR); |
395 | |
396 | writel(AT91_RSTC_KEY | AT91_RSTC_URSTASYNC | val, |
397 | addr: reset->rstc_base + AT91_RSTC_MR); |
398 | } |
399 | |
400 | ret = register_restart_handler(&reset->nb); |
401 | if (ret) |
402 | goto disable_clk; |
403 | |
404 | ret = device_create_file(device: &pdev->dev, entry: &dev_attr_power_on_reason); |
405 | if (ret) { |
406 | dev_err(&pdev->dev, "Could not create sysfs entry\n" ); |
407 | return ret; |
408 | } |
409 | |
410 | dev_info(&pdev->dev, "Starting after %s\n" , at91_reset_reason(reset)); |
411 | |
412 | return 0; |
413 | |
414 | disable_clk: |
415 | clk_disable_unprepare(clk: reset->sclk); |
416 | return ret; |
417 | } |
418 | |
419 | static void at91_reset_remove(struct platform_device *pdev) |
420 | { |
421 | struct at91_reset *reset = platform_get_drvdata(pdev); |
422 | |
423 | unregister_restart_handler(&reset->nb); |
424 | clk_disable_unprepare(clk: reset->sclk); |
425 | } |
426 | |
427 | static struct platform_driver at91_reset_driver = { |
428 | .probe = at91_reset_probe, |
429 | .remove = at91_reset_remove, |
430 | .driver = { |
431 | .name = "at91-reset" , |
432 | .of_match_table = at91_reset_of_match, |
433 | }, |
434 | }; |
435 | module_platform_driver(at91_reset_driver); |
436 | |
437 | MODULE_AUTHOR("Atmel Corporation" ); |
438 | MODULE_DESCRIPTION("Reset driver for Atmel SoCs" ); |
439 | MODULE_LICENSE("GPL v2" ); |
440 | |