0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/io.h>
0011 #include <linux/module.h>
0012 #include <linux/notifier.h>
0013 #include <linux/reboot.h>
0014 #include <linux/regmap.h>
0015 #include <linux/mfd/syscon.h>
0016 #include <linux/of_platform.h>
0017
0018 #define RSTYPE_RG 0x0
0019 #define RSCTRL_RG 0x4
0020 #define RSCFG_RG 0x8
0021 #define RSISO_RG 0xc
0022
0023 #define RSCTRL_KEY_MASK 0x0000ffff
0024 #define RSCTRL_RESET_MASK BIT(16)
0025 #define RSCTRL_KEY 0x5a69
0026
0027 #define RSMUX_OMODE_MASK 0xe
0028 #define RSMUX_OMODE_RESET_ON 0xa
0029 #define RSMUX_OMODE_RESET_OFF 0x0
0030 #define RSMUX_LOCK_MASK 0x1
0031 #define RSMUX_LOCK_SET 0x1
0032
0033 #define RSCFG_RSTYPE_SOFT 0x300f
0034 #define RSCFG_RSTYPE_HARD 0x0
0035
0036 #define WDT_MUX_NUMBER 0x4
0037
0038 static int rspll_offset;
0039 static struct regmap *pllctrl_regs;
0040
0041
0042
0043
0044
0045
0046 static inline int rsctrl_enable_rspll_write(void)
0047 {
0048 return regmap_update_bits(pllctrl_regs, rspll_offset + RSCTRL_RG,
0049 RSCTRL_KEY_MASK, RSCTRL_KEY);
0050 }
0051
0052 static int rsctrl_restart_handler(struct notifier_block *this,
0053 unsigned long mode, void *cmd)
0054 {
0055
0056 rsctrl_enable_rspll_write();
0057
0058
0059 regmap_update_bits(pllctrl_regs, rspll_offset + RSCTRL_RG,
0060 RSCTRL_RESET_MASK, 0);
0061
0062 return NOTIFY_DONE;
0063 }
0064
0065 static struct notifier_block rsctrl_restart_nb = {
0066 .notifier_call = rsctrl_restart_handler,
0067 .priority = 128,
0068 };
0069
0070 static const struct of_device_id rsctrl_of_match[] = {
0071 {.compatible = "ti,keystone-reset", },
0072 {},
0073 };
0074 MODULE_DEVICE_TABLE(of, rsctrl_of_match);
0075
0076 static int rsctrl_probe(struct platform_device *pdev)
0077 {
0078 int i;
0079 int ret;
0080 u32 val;
0081 unsigned int rg;
0082 u32 rsmux_offset;
0083 struct regmap *devctrl_regs;
0084 struct device *dev = &pdev->dev;
0085 struct device_node *np = dev->of_node;
0086
0087 if (!np)
0088 return -ENODEV;
0089
0090
0091 pllctrl_regs = syscon_regmap_lookup_by_phandle(np, "ti,syscon-pll");
0092 if (IS_ERR(pllctrl_regs))
0093 return PTR_ERR(pllctrl_regs);
0094
0095 devctrl_regs = syscon_regmap_lookup_by_phandle(np, "ti,syscon-dev");
0096 if (IS_ERR(devctrl_regs))
0097 return PTR_ERR(devctrl_regs);
0098
0099 ret = of_property_read_u32_index(np, "ti,syscon-pll", 1, &rspll_offset);
0100 if (ret) {
0101 dev_err(dev, "couldn't read the reset pll offset!\n");
0102 return -EINVAL;
0103 }
0104
0105 ret = of_property_read_u32_index(np, "ti,syscon-dev", 1, &rsmux_offset);
0106 if (ret) {
0107 dev_err(dev, "couldn't read the rsmux offset!\n");
0108 return -EINVAL;
0109 }
0110
0111
0112 val = of_property_read_bool(np, "ti,soft-reset");
0113 val = val ? RSCFG_RSTYPE_SOFT : RSCFG_RSTYPE_HARD;
0114
0115 ret = rsctrl_enable_rspll_write();
0116 if (ret)
0117 return ret;
0118
0119 ret = regmap_write(pllctrl_regs, rspll_offset + RSCFG_RG, val);
0120 if (ret)
0121 return ret;
0122
0123
0124 ret = regmap_write(pllctrl_regs, rspll_offset + RSISO_RG, 0);
0125 if (ret)
0126 return ret;
0127
0128
0129 for (i = 0; i < WDT_MUX_NUMBER; i++) {
0130 ret = of_property_read_u32_index(np, "ti,wdt-list", i, &val);
0131 if (ret == -EOVERFLOW && !i) {
0132 dev_err(dev, "ti,wdt-list property has to contain at"
0133 "least one entry\n");
0134 return -EINVAL;
0135 } else if (ret) {
0136 break;
0137 }
0138
0139 if (val >= WDT_MUX_NUMBER) {
0140 dev_err(dev, "ti,wdt-list property can contain "
0141 "only numbers < 4\n");
0142 return -EINVAL;
0143 }
0144
0145 rg = rsmux_offset + val * 4;
0146
0147 ret = regmap_update_bits(devctrl_regs, rg, RSMUX_OMODE_MASK,
0148 RSMUX_OMODE_RESET_ON |
0149 RSMUX_LOCK_SET);
0150 if (ret)
0151 return ret;
0152 }
0153
0154 ret = register_restart_handler(&rsctrl_restart_nb);
0155 if (ret)
0156 dev_err(dev, "cannot register restart handler (err=%d)\n", ret);
0157
0158 return ret;
0159 }
0160
0161 static struct platform_driver rsctrl_driver = {
0162 .probe = rsctrl_probe,
0163 .driver = {
0164 .name = KBUILD_MODNAME,
0165 .of_match_table = rsctrl_of_match,
0166 },
0167 };
0168 module_platform_driver(rsctrl_driver);
0169
0170 MODULE_AUTHOR("Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>");
0171 MODULE_DESCRIPTION("Texas Instruments keystone reset driver");
0172 MODULE_LICENSE("GPL v2");
0173 MODULE_ALIAS("platform:" KBUILD_MODNAME);