0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/clk.h>
0010 #include <linux/device.h>
0011 #include <linux/err.h>
0012 #include <linux/io.h>
0013 #include <linux/kernel.h>
0014 #include <linux/mod_devicetable.h>
0015 #include <linux/module.h>
0016 #include <linux/moduleparam.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/pm_runtime.h>
0019 #include <linux/types.h>
0020 #include <linux/watchdog.h>
0021
0022 #define DEFAULT_HEARTBEAT 60
0023
0024
0025 #define MAX_HEARTBEAT 1000
0026
0027
0028 #define RTIDWDCTRL 0x90
0029 #define RTIDWDPRLD 0x94
0030 #define RTIWDSTATUS 0x98
0031 #define RTIWDKEY 0x9c
0032 #define RTIDWDCNTR 0xa0
0033 #define RTIWWDRXCTRL 0xa4
0034 #define RTIWWDSIZECTRL 0xa8
0035
0036 #define RTIWWDRX_NMI 0xa
0037
0038 #define RTIWWDSIZE_50P 0x50
0039 #define RTIWWDSIZE_25P 0x500
0040 #define RTIWWDSIZE_12P5 0x5000
0041 #define RTIWWDSIZE_6P25 0x50000
0042 #define RTIWWDSIZE_3P125 0x500000
0043
0044 #define WDENABLE_KEY 0xa98559da
0045
0046 #define WDKEY_SEQ0 0xe51a
0047 #define WDKEY_SEQ1 0xa35c
0048
0049 #define WDT_PRELOAD_SHIFT 13
0050
0051 #define WDT_PRELOAD_MAX 0xfff
0052
0053 #define DWDST BIT(1)
0054
0055 static int heartbeat = DEFAULT_HEARTBEAT;
0056
0057
0058
0059
0060
0061
0062
0063 struct rti_wdt_device {
0064 void __iomem *base;
0065 unsigned long freq;
0066 struct watchdog_device wdd;
0067 };
0068
0069 static int rti_wdt_start(struct watchdog_device *wdd)
0070 {
0071 u32 timer_margin;
0072 struct rti_wdt_device *wdt = watchdog_get_drvdata(wdd);
0073
0074
0075 timer_margin = (u64)wdd->timeout * wdt->freq;
0076 timer_margin >>= WDT_PRELOAD_SHIFT;
0077 if (timer_margin > WDT_PRELOAD_MAX)
0078 timer_margin = WDT_PRELOAD_MAX;
0079 writel_relaxed(timer_margin, wdt->base + RTIDWDPRLD);
0080
0081
0082
0083
0084
0085
0086
0087
0088 wdd->min_hw_heartbeat_ms = 500 * wdd->timeout;
0089
0090
0091 writel_relaxed(RTIWWDRX_NMI, wdt->base + RTIWWDRXCTRL);
0092
0093
0094 writel_relaxed(RTIWWDSIZE_50P, wdt->base + RTIWWDSIZECTRL);
0095
0096 readl_relaxed(wdt->base + RTIWWDSIZECTRL);
0097
0098
0099 writel_relaxed(WDENABLE_KEY, wdt->base + RTIDWDCTRL);
0100 return 0;
0101 }
0102
0103 static int rti_wdt_ping(struct watchdog_device *wdd)
0104 {
0105 struct rti_wdt_device *wdt = watchdog_get_drvdata(wdd);
0106
0107
0108 writel_relaxed(WDKEY_SEQ0, wdt->base + RTIWDKEY);
0109
0110 writel_relaxed(WDKEY_SEQ1, wdt->base + RTIWDKEY);
0111
0112 return 0;
0113 }
0114
0115 static int rti_wdt_setup_hw_hb(struct watchdog_device *wdd, u32 wsize)
0116 {
0117
0118
0119
0120
0121
0122
0123 switch (wsize) {
0124 case RTIWWDSIZE_50P:
0125
0126 wdd->min_hw_heartbeat_ms = 500 * heartbeat;
0127 break;
0128
0129 case RTIWWDSIZE_25P:
0130
0131 wdd->min_hw_heartbeat_ms = 750 * heartbeat;
0132 break;
0133
0134 case RTIWWDSIZE_12P5:
0135
0136 wdd->min_hw_heartbeat_ms = 875 * heartbeat;
0137 break;
0138
0139 case RTIWWDSIZE_6P25:
0140
0141 wdd->min_hw_heartbeat_ms = 935 * heartbeat;
0142 break;
0143
0144 case RTIWWDSIZE_3P125:
0145
0146 wdd->min_hw_heartbeat_ms = 969 * heartbeat;
0147 break;
0148
0149 default:
0150 return -EINVAL;
0151 }
0152
0153 return 0;
0154 }
0155
0156 static unsigned int rti_wdt_get_timeleft_ms(struct watchdog_device *wdd)
0157 {
0158 u64 timer_counter;
0159 u32 val;
0160 struct rti_wdt_device *wdt = watchdog_get_drvdata(wdd);
0161
0162
0163 val = readl_relaxed(wdt->base + RTIWDSTATUS);
0164 if (val & DWDST)
0165 return 0;
0166
0167 timer_counter = readl_relaxed(wdt->base + RTIDWDCNTR);
0168
0169 timer_counter *= 1000;
0170
0171 do_div(timer_counter, wdt->freq);
0172
0173 return timer_counter;
0174 }
0175
0176 static unsigned int rti_wdt_get_timeleft(struct watchdog_device *wdd)
0177 {
0178 return rti_wdt_get_timeleft_ms(wdd) / 1000;
0179 }
0180
0181 static const struct watchdog_info rti_wdt_info = {
0182 .options = WDIOF_KEEPALIVEPING,
0183 .identity = "K3 RTI Watchdog",
0184 };
0185
0186 static const struct watchdog_ops rti_wdt_ops = {
0187 .owner = THIS_MODULE,
0188 .start = rti_wdt_start,
0189 .ping = rti_wdt_ping,
0190 .get_timeleft = rti_wdt_get_timeleft,
0191 };
0192
0193 static int rti_wdt_probe(struct platform_device *pdev)
0194 {
0195 int ret = 0;
0196 struct device *dev = &pdev->dev;
0197 struct watchdog_device *wdd;
0198 struct rti_wdt_device *wdt;
0199 struct clk *clk;
0200 u32 last_ping = 0;
0201
0202 wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
0203 if (!wdt)
0204 return -ENOMEM;
0205
0206 clk = clk_get(dev, NULL);
0207 if (IS_ERR(clk))
0208 return dev_err_probe(dev, PTR_ERR(clk), "failed to get clock\n");
0209
0210 wdt->freq = clk_get_rate(clk);
0211
0212 clk_put(clk);
0213
0214 if (!wdt->freq) {
0215 dev_err(dev, "Failed to get fck rate.\n");
0216 return -EINVAL;
0217 }
0218
0219
0220
0221
0222
0223
0224 if (wdt->freq < 32768)
0225 wdt->freq = wdt->freq * 9 / 10;
0226
0227 pm_runtime_enable(dev);
0228 ret = pm_runtime_get_sync(dev);
0229 if (ret < 0) {
0230 pm_runtime_put_noidle(dev);
0231 pm_runtime_disable(&pdev->dev);
0232 return dev_err_probe(dev, ret, "runtime pm failed\n");
0233 }
0234
0235 platform_set_drvdata(pdev, wdt);
0236
0237 wdd = &wdt->wdd;
0238 wdd->info = &rti_wdt_info;
0239 wdd->ops = &rti_wdt_ops;
0240 wdd->min_timeout = 1;
0241 wdd->max_hw_heartbeat_ms = (WDT_PRELOAD_MAX << WDT_PRELOAD_SHIFT) /
0242 wdt->freq * 1000;
0243 wdd->parent = dev;
0244
0245 watchdog_set_drvdata(wdd, wdt);
0246 watchdog_set_nowayout(wdd, 1);
0247 watchdog_set_restart_priority(wdd, 128);
0248
0249 wdt->base = devm_platform_ioremap_resource(pdev, 0);
0250 if (IS_ERR(wdt->base)) {
0251 ret = PTR_ERR(wdt->base);
0252 goto err_iomap;
0253 }
0254
0255 if (readl(wdt->base + RTIDWDCTRL) == WDENABLE_KEY) {
0256 int preset_heartbeat;
0257 u32 time_left_ms;
0258 u64 heartbeat_ms;
0259 u32 wsize;
0260
0261 set_bit(WDOG_HW_RUNNING, &wdd->status);
0262 time_left_ms = rti_wdt_get_timeleft_ms(wdd);
0263 heartbeat_ms = readl(wdt->base + RTIDWDPRLD);
0264 heartbeat_ms <<= WDT_PRELOAD_SHIFT;
0265 heartbeat_ms *= 1000;
0266 do_div(heartbeat_ms, wdt->freq);
0267 preset_heartbeat = heartbeat_ms + 500;
0268 preset_heartbeat /= 1000;
0269 if (preset_heartbeat != heartbeat)
0270 dev_warn(dev, "watchdog already running, ignoring heartbeat config!\n");
0271
0272 heartbeat = preset_heartbeat;
0273
0274 wsize = readl(wdt->base + RTIWWDSIZECTRL);
0275 ret = rti_wdt_setup_hw_hb(wdd, wsize);
0276 if (ret) {
0277 dev_err(dev, "bad window size.\n");
0278 goto err_iomap;
0279 }
0280
0281 last_ping = heartbeat_ms - time_left_ms;
0282 if (time_left_ms > heartbeat_ms) {
0283 dev_warn(dev, "time_left > heartbeat? Assuming last ping just before now.\n");
0284 last_ping = 0;
0285 }
0286 }
0287
0288 watchdog_init_timeout(wdd, heartbeat, dev);
0289
0290 ret = watchdog_register_device(wdd);
0291 if (ret) {
0292 dev_err(dev, "cannot register watchdog device\n");
0293 goto err_iomap;
0294 }
0295
0296 if (last_ping)
0297 watchdog_set_last_hw_keepalive(wdd, last_ping);
0298
0299 return 0;
0300
0301 err_iomap:
0302 pm_runtime_put_sync(&pdev->dev);
0303 pm_runtime_disable(&pdev->dev);
0304
0305 return ret;
0306 }
0307
0308 static int rti_wdt_remove(struct platform_device *pdev)
0309 {
0310 struct rti_wdt_device *wdt = platform_get_drvdata(pdev);
0311
0312 watchdog_unregister_device(&wdt->wdd);
0313 pm_runtime_put(&pdev->dev);
0314 pm_runtime_disable(&pdev->dev);
0315
0316 return 0;
0317 }
0318
0319 static const struct of_device_id rti_wdt_of_match[] = {
0320 { .compatible = "ti,j7-rti-wdt", },
0321 {},
0322 };
0323 MODULE_DEVICE_TABLE(of, rti_wdt_of_match);
0324
0325 static struct platform_driver rti_wdt_driver = {
0326 .driver = {
0327 .name = "rti-wdt",
0328 .of_match_table = rti_wdt_of_match,
0329 },
0330 .probe = rti_wdt_probe,
0331 .remove = rti_wdt_remove,
0332 };
0333
0334 module_platform_driver(rti_wdt_driver);
0335
0336 MODULE_AUTHOR("Tero Kristo <t-kristo@ti.com>");
0337 MODULE_DESCRIPTION("K3 RTI Watchdog Driver");
0338
0339 module_param(heartbeat, int, 0);
0340 MODULE_PARM_DESC(heartbeat,
0341 "Watchdog heartbeat period in seconds from 1 to "
0342 __MODULE_STRING(MAX_HEARTBEAT) ", default "
0343 __MODULE_STRING(DEFAULT_HEARTBEAT));
0344
0345 MODULE_LICENSE("GPL");
0346 MODULE_ALIAS("platform:rti-wdt");