2 * Copyright (C) 2014 STMicroelectronics
4 * Power off Restart driver, used in STMicroelectronics devices.
6 * Author: Christophe Kerello <christophe.kerello@st.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2, as
10 * published by the Free Software Foundation.
13 #include <linux/module.h>
15 #include <linux/of_platform.h>
16 #include <linux/platform_device.h>
17 #include <linux/mfd/syscon.h>
18 #include <linux/reboot.h>
19 #include <linux/regmap.h>
22 struct regmap
*regmap
;
23 /* syscfg used for reset */
24 unsigned int offset_rst
;
25 unsigned int mask_rst
;
26 /* syscfg used for unmask the reset */
27 unsigned int offset_rst_msk
;
28 unsigned int mask_rst_msk
;
32 #define STIH415_SYSCFG_11 0x2c
33 #define STIH415_SYSCFG_15 0x3c
35 static struct reset_syscfg stih415_reset
= {
36 .offset_rst
= STIH415_SYSCFG_11
,
38 .offset_rst_msk
= STIH415_SYSCFG_15
,
39 .mask_rst_msk
= BIT(0)
43 #define STIH416_SYSCFG_500 0x7d0
44 #define STIH416_SYSCFG_504 0x7e0
46 static struct reset_syscfg stih416_reset
= {
47 .offset_rst
= STIH416_SYSCFG_500
,
49 .offset_rst_msk
= STIH416_SYSCFG_504
,
50 .mask_rst_msk
= BIT(0)
54 #define STIH407_SYSCFG_4000 0x0
55 #define STIH407_SYSCFG_4008 0x20
57 static struct reset_syscfg stih407_reset
= {
58 .offset_rst
= STIH407_SYSCFG_4000
,
60 .offset_rst_msk
= STIH407_SYSCFG_4008
,
61 .mask_rst_msk
= BIT(0)
65 #define STID127_SYSCFG_700 0x0
66 #define STID127_SYSCFG_773 0x124
68 static struct reset_syscfg stid127_reset
= {
69 .offset_rst
= STID127_SYSCFG_773
,
71 .offset_rst_msk
= STID127_SYSCFG_700
,
72 .mask_rst_msk
= BIT(8)
75 static struct reset_syscfg
*st_restart_syscfg
;
77 static int st_restart(struct notifier_block
*this, unsigned long mode
,
80 /* reset syscfg updated */
81 regmap_update_bits(st_restart_syscfg
->regmap
,
82 st_restart_syscfg
->offset_rst
,
83 st_restart_syscfg
->mask_rst
,
86 /* unmask the reset */
87 regmap_update_bits(st_restart_syscfg
->regmap
,
88 st_restart_syscfg
->offset_rst_msk
,
89 st_restart_syscfg
->mask_rst_msk
,
95 static struct notifier_block st_restart_nb
= {
96 .notifier_call
= st_restart
,
100 static const struct of_device_id st_reset_of_match
[] = {
102 .compatible
= "st,stih415-restart",
103 .data
= (void *)&stih415_reset
,
105 .compatible
= "st,stih416-restart",
106 .data
= (void *)&stih416_reset
,
108 .compatible
= "st,stih407-restart",
109 .data
= (void *)&stih407_reset
,
111 .compatible
= "st,stid127-restart",
112 .data
= (void *)&stid127_reset
,
117 static int st_reset_probe(struct platform_device
*pdev
)
119 struct device_node
*np
= pdev
->dev
.of_node
;
120 const struct of_device_id
*match
;
121 struct device
*dev
= &pdev
->dev
;
123 match
= of_match_device(st_reset_of_match
, dev
);
127 st_restart_syscfg
= (struct reset_syscfg
*)match
->data
;
129 st_restart_syscfg
->regmap
=
130 syscon_regmap_lookup_by_phandle(np
, "st,syscfg");
131 if (IS_ERR(st_restart_syscfg
->regmap
)) {
132 dev_err(dev
, "No syscfg phandle specified\n");
133 return PTR_ERR(st_restart_syscfg
->regmap
);
136 return register_restart_handler(&st_restart_nb
);
139 static struct platform_driver st_reset_driver
= {
140 .probe
= st_reset_probe
,
143 .of_match_table
= st_reset_of_match
,
147 static int __init
st_reset_init(void)
149 return platform_driver_register(&st_reset_driver
);
152 device_initcall(st_reset_init
);
154 MODULE_AUTHOR("Christophe Kerello <christophe.kerello@st.com>");
155 MODULE_DESCRIPTION("STMicroelectronics Power off Restart driver");
156 MODULE_LICENSE("GPL v2");