|
20 | 20 | #include <linux/platform_device.h>
|
21 | 21 | #include <linux/pm_clock.h>
|
22 | 22 | #include <linux/pm_domain.h>
|
| 23 | +#include <linux/reboot.h> |
23 | 24 | #include <linux/slab.h>
|
24 | 25 | #include <linux/soc/renesas/r9a06g032-sysctrl.h>
|
25 | 26 | #include <linux/spinlock.h>
|
|
29 | 30 | #define R9A06G032_SYSCTRL_USB_H2MODE (1<<1)
|
30 | 31 | #define R9A06G032_SYSCTRL_DMAMUX 0xA0
|
31 | 32 |
|
| 33 | +#define R9A06G032_SYSCTRL_RSTEN 0x120 |
| 34 | +#define R9A06G032_SYSCTRL_RSTEN_MRESET_EN BIT(0) |
| 35 | +#define R9A06G032_SYSCTRL_RSTCTRL 0x198 |
| 36 | +/* These work for both reset registers */ |
| 37 | +#define R9A06G032_SYSCTRL_SWRST BIT(6) |
| 38 | +#define R9A06G032_SYSCTRL_WDA7RST_1 BIT(2) |
| 39 | +#define R9A06G032_SYSCTRL_WDA7RST_0 BIT(1) |
| 40 | + |
32 | 41 | /**
|
33 | 42 | * struct regbit - describe one bit in a register
|
34 | 43 | * @reg: offset of register relative to base address,
|
@@ -1270,6 +1279,12 @@ static void r9a06g032_clocks_del_clk_provider(void *data)
|
1270 | 1279 | of_clk_del_provider(data);
|
1271 | 1280 | }
|
1272 | 1281 |
|
| 1282 | +static int r9a06g032_restart_handler(struct sys_off_data *data) |
| 1283 | +{ |
| 1284 | + writel(R9A06G032_SYSCTRL_SWRST, sysctrl_priv->reg + R9A06G032_SYSCTRL_RSTCTRL); |
| 1285 | + return NOTIFY_DONE; |
| 1286 | +} |
| 1287 | + |
1273 | 1288 | static void __init r9a06g032_init_h2mode(struct r9a06g032_priv *clocks)
|
1274 | 1289 | {
|
1275 | 1290 | struct device_node *usbf_np;
|
@@ -1324,6 +1339,18 @@ static int __init r9a06g032_clocks_probe(struct platform_device *pdev)
|
1324 | 1339 |
|
1325 | 1340 | r9a06g032_init_h2mode(clocks);
|
1326 | 1341 |
|
| 1342 | + /* Clear potentially pending resets */ |
| 1343 | + writel(R9A06G032_SYSCTRL_WDA7RST_0 | R9A06G032_SYSCTRL_WDA7RST_1, |
| 1344 | + clocks->reg + R9A06G032_SYSCTRL_RSTCTRL); |
| 1345 | + /* Allow software reset */ |
| 1346 | + writel(R9A06G032_SYSCTRL_SWRST | R9A06G032_SYSCTRL_RSTEN_MRESET_EN, |
| 1347 | + clocks->reg + R9A06G032_SYSCTRL_RSTEN); |
| 1348 | + |
| 1349 | + error = devm_register_sys_off_handler(dev, SYS_OFF_MODE_RESTART, SYS_OFF_PRIO_HIGH, |
| 1350 | + r9a06g032_restart_handler, NULL); |
| 1351 | + if (error) |
| 1352 | + dev_warn(dev, "couldn't register restart handler (%d)\n", error); |
| 1353 | + |
1327 | 1354 | for (i = 0; i < ARRAY_SIZE(r9a06g032_clocks); ++i) {
|
1328 | 1355 | const struct r9a06g032_clkdesc *d = &r9a06g032_clocks[i];
|
1329 | 1356 | const char *parent_name = d->source ?
|
|
0 commit comments