1 // SPDX-License-Identifier: GPL-2.0-only
3 * TI keystone reboot driver
5 * Copyright (C) 2014 Texas Instruments Incorporated. https://www.ti.com/
7 * Author: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
11 #include <linux/module.h>
12 #include <linux/notifier.h>
13 #include <linux/reboot.h>
14 #include <linux/regmap.h>
15 #include <linux/mfd/syscon.h>
16 #include <linux/of_platform.h>
23 #define RSCTRL_KEY_MASK 0x0000ffff
24 #define RSCTRL_RESET_MASK BIT(16)
25 #define RSCTRL_KEY 0x5a69
27 #define RSMUX_OMODE_MASK 0xe
28 #define RSMUX_OMODE_RESET_ON 0xa
29 #define RSMUX_OMODE_RESET_OFF 0x0
30 #define RSMUX_LOCK_MASK 0x1
31 #define RSMUX_LOCK_SET 0x1
33 #define RSCFG_RSTYPE_SOFT 0x300f
34 #define RSCFG_RSTYPE_HARD 0x0
36 #define WDT_MUX_NUMBER 0x4
38 static int rspll_offset
;
39 static struct regmap
*pllctrl_regs
;
42 * rsctrl_enable_rspll_write - enable access to RSCTRL, RSCFG
43 * To be able to access to RSCTRL, RSCFG registers
44 * we have to write a key before
46 static inline int rsctrl_enable_rspll_write(void)
48 return regmap_update_bits(pllctrl_regs
, rspll_offset
+ RSCTRL_RG
,
49 RSCTRL_KEY_MASK
, RSCTRL_KEY
);
52 static int rsctrl_restart_handler(struct notifier_block
*this,
53 unsigned long mode
, void *cmd
)
55 /* enable write access to RSTCTRL */
56 rsctrl_enable_rspll_write();
59 regmap_update_bits(pllctrl_regs
, rspll_offset
+ RSCTRL_RG
,
60 RSCTRL_RESET_MASK
, 0);
65 static struct notifier_block rsctrl_restart_nb
= {
66 .notifier_call
= rsctrl_restart_handler
,
70 static const struct of_device_id rsctrl_of_match
[] = {
71 {.compatible
= "ti,keystone-reset", },
75 static int rsctrl_probe(struct platform_device
*pdev
)
82 struct regmap
*devctrl_regs
;
83 struct device
*dev
= &pdev
->dev
;
84 struct device_node
*np
= dev
->of_node
;
90 pllctrl_regs
= syscon_regmap_lookup_by_phandle(np
, "ti,syscon-pll");
91 if (IS_ERR(pllctrl_regs
))
92 return PTR_ERR(pllctrl_regs
);
94 devctrl_regs
= syscon_regmap_lookup_by_phandle(np
, "ti,syscon-dev");
95 if (IS_ERR(devctrl_regs
))
96 return PTR_ERR(devctrl_regs
);
98 ret
= of_property_read_u32_index(np
, "ti,syscon-pll", 1, &rspll_offset
);
100 dev_err(dev
, "couldn't read the reset pll offset!\n");
104 ret
= of_property_read_u32_index(np
, "ti,syscon-dev", 1, &rsmux_offset
);
106 dev_err(dev
, "couldn't read the rsmux offset!\n");
110 /* set soft/hard reset */
111 val
= of_property_read_bool(np
, "ti,soft-reset");
112 val
= val
? RSCFG_RSTYPE_SOFT
: RSCFG_RSTYPE_HARD
;
114 ret
= rsctrl_enable_rspll_write();
118 ret
= regmap_write(pllctrl_regs
, rspll_offset
+ RSCFG_RG
, val
);
122 /* disable a reset isolation for all module clocks */
123 ret
= regmap_write(pllctrl_regs
, rspll_offset
+ RSISO_RG
, 0);
127 /* enable a reset for watchdogs from wdt-list */
128 for (i
= 0; i
< WDT_MUX_NUMBER
; i
++) {
129 ret
= of_property_read_u32_index(np
, "ti,wdt-list", i
, &val
);
130 if (ret
== -EOVERFLOW
&& !i
) {
131 dev_err(dev
, "ti,wdt-list property has to contain at"
132 "least one entry\n");
138 if (val
>= WDT_MUX_NUMBER
) {
139 dev_err(dev
, "ti,wdt-list property can contain "
140 "only numbers < 4\n");
144 rg
= rsmux_offset
+ val
* 4;
146 ret
= regmap_update_bits(devctrl_regs
, rg
, RSMUX_OMODE_MASK
,
147 RSMUX_OMODE_RESET_ON
|
153 ret
= register_restart_handler(&rsctrl_restart_nb
);
155 dev_err(dev
, "cannot register restart handler (err=%d)\n", ret
);
160 static struct platform_driver rsctrl_driver
= {
161 .probe
= rsctrl_probe
,
163 .name
= KBUILD_MODNAME
,
164 .of_match_table
= rsctrl_of_match
,
167 module_platform_driver(rsctrl_driver
);
169 MODULE_AUTHOR("Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>");
170 MODULE_DESCRIPTION("Texas Instruments keystone reset driver");
171 MODULE_LICENSE("GPL v2");
172 MODULE_ALIAS("platform:" KBUILD_MODNAME
);