0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <linux/bits.h>
0019 #include <linux/bitfield.h>
0020 #include <linux/clk.h>
0021 #include <linux/delay.h>
0022 #include <linux/interrupt.h>
0023 #include <linux/io.h>
0024 #include <linux/math.h>
0025 #include <linux/minmax.h>
0026 #include <linux/module.h>
0027 #include <linux/mod_devicetable.h>
0028 #include <linux/platform_device.h>
0029 #include <linux/property.h>
0030 #include <linux/reboot.h>
0031 #include <linux/watchdog.h>
0032
0033 #define OTTO_WDT_REG_CNTR 0x0
0034 #define OTTO_WDT_CNTR_PING BIT(31)
0035
0036 #define OTTO_WDT_REG_INTR 0x4
0037 #define OTTO_WDT_INTR_PHASE_1 BIT(31)
0038 #define OTTO_WDT_INTR_PHASE_2 BIT(30)
0039
0040 #define OTTO_WDT_REG_CTRL 0x8
0041 #define OTTO_WDT_CTRL_ENABLE BIT(31)
0042 #define OTTO_WDT_CTRL_PRESCALE GENMASK(30, 29)
0043 #define OTTO_WDT_CTRL_PHASE1 GENMASK(26, 22)
0044 #define OTTO_WDT_CTRL_PHASE2 GENMASK(19, 15)
0045 #define OTTO_WDT_CTRL_RST_MODE GENMASK(1, 0)
0046 #define OTTO_WDT_MODE_SOC 0
0047 #define OTTO_WDT_MODE_CPU 1
0048 #define OTTO_WDT_MODE_SOFTWARE 2
0049 #define OTTO_WDT_CTRL_DEFAULT OTTO_WDT_MODE_CPU
0050
0051 #define OTTO_WDT_PRESCALE_MAX 3
0052
0053
0054
0055
0056
0057 #define OTTO_WDT_PHASE_TICKS_MAX 32
0058
0059
0060
0061
0062
0063
0064 #define OTTO_WDT_TIMEOUT_TICKS_MAX (OTTO_WDT_PHASE_TICKS_MAX + 1)
0065
0066 struct otto_wdt_ctrl {
0067 struct watchdog_device wdev;
0068 struct device *dev;
0069 void __iomem *base;
0070 unsigned int clk_rate_khz;
0071 int irq_phase1;
0072 };
0073
0074 static int otto_wdt_start(struct watchdog_device *wdev)
0075 {
0076 struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);
0077 u32 v;
0078
0079 v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL);
0080 v |= OTTO_WDT_CTRL_ENABLE;
0081 iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);
0082
0083 return 0;
0084 }
0085
0086 static int otto_wdt_stop(struct watchdog_device *wdev)
0087 {
0088 struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);
0089 u32 v;
0090
0091 v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL);
0092 v &= ~OTTO_WDT_CTRL_ENABLE;
0093 iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);
0094
0095 return 0;
0096 }
0097
0098 static int otto_wdt_ping(struct watchdog_device *wdev)
0099 {
0100 struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);
0101
0102 iowrite32(OTTO_WDT_CNTR_PING, ctrl->base + OTTO_WDT_REG_CNTR);
0103
0104 return 0;
0105 }
0106
0107 static int otto_wdt_tick_ms(struct otto_wdt_ctrl *ctrl, int prescale)
0108 {
0109 return DIV_ROUND_CLOSEST(1 << (25 + prescale), ctrl->clk_rate_khz);
0110 }
0111
0112
0113
0114
0115
0116
0117 static inline unsigned int div_round_ticks(unsigned int val, unsigned int tick_duration,
0118 unsigned int min_ticks)
0119 {
0120 return max(min_ticks, DIV_ROUND_UP(val, tick_duration));
0121 }
0122
0123 static int otto_wdt_determine_timeouts(struct watchdog_device *wdev, unsigned int timeout,
0124 unsigned int pretimeout)
0125 {
0126 struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);
0127 unsigned int pretimeout_ms = pretimeout * 1000;
0128 unsigned int timeout_ms = timeout * 1000;
0129 unsigned int prescale_next = 0;
0130 unsigned int phase1_ticks;
0131 unsigned int phase2_ticks;
0132 unsigned int total_ticks;
0133 unsigned int prescale;
0134 unsigned int tick_ms;
0135 u32 v;
0136
0137 do {
0138 prescale = prescale_next;
0139 if (prescale > OTTO_WDT_PRESCALE_MAX)
0140 return -EINVAL;
0141
0142 tick_ms = otto_wdt_tick_ms(ctrl, prescale);
0143 total_ticks = div_round_ticks(timeout_ms, tick_ms, 2);
0144 phase1_ticks = div_round_ticks(timeout_ms - pretimeout_ms, tick_ms, 1);
0145 phase2_ticks = total_ticks - phase1_ticks;
0146
0147 prescale_next++;
0148 } while (phase1_ticks > OTTO_WDT_PHASE_TICKS_MAX
0149 || phase2_ticks > OTTO_WDT_PHASE_TICKS_MAX);
0150
0151 v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL);
0152
0153 v &= ~(OTTO_WDT_CTRL_PRESCALE | OTTO_WDT_CTRL_PHASE1 | OTTO_WDT_CTRL_PHASE2);
0154 v |= FIELD_PREP(OTTO_WDT_CTRL_PHASE1, phase1_ticks - 1);
0155 v |= FIELD_PREP(OTTO_WDT_CTRL_PHASE2, phase2_ticks - 1);
0156 v |= FIELD_PREP(OTTO_WDT_CTRL_PRESCALE, prescale);
0157
0158 iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);
0159
0160 timeout_ms = total_ticks * tick_ms;
0161 ctrl->wdev.timeout = timeout_ms / 1000;
0162
0163 pretimeout_ms = phase2_ticks * tick_ms;
0164 ctrl->wdev.pretimeout = pretimeout_ms / 1000;
0165
0166 return 0;
0167 }
0168
0169 static int otto_wdt_set_timeout(struct watchdog_device *wdev, unsigned int val)
0170 {
0171 return otto_wdt_determine_timeouts(wdev, val, min(wdev->pretimeout, val - 1));
0172 }
0173
0174 static int otto_wdt_set_pretimeout(struct watchdog_device *wdev, unsigned int val)
0175 {
0176 return otto_wdt_determine_timeouts(wdev, wdev->timeout, val);
0177 }
0178
0179 static int otto_wdt_restart(struct watchdog_device *wdev, unsigned long reboot_mode,
0180 void *data)
0181 {
0182 struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);
0183 u32 reset_mode;
0184 u32 v;
0185
0186 disable_irq(ctrl->irq_phase1);
0187
0188 switch (reboot_mode) {
0189 case REBOOT_SOFT:
0190 reset_mode = OTTO_WDT_MODE_SOFTWARE;
0191 break;
0192 case REBOOT_WARM:
0193 reset_mode = OTTO_WDT_MODE_CPU;
0194 break;
0195 default:
0196 reset_mode = OTTO_WDT_MODE_SOC;
0197 break;
0198 }
0199
0200
0201 v = FIELD_PREP(OTTO_WDT_CTRL_RST_MODE, reset_mode) | OTTO_WDT_CTRL_ENABLE;
0202 iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);
0203
0204 mdelay(3 * otto_wdt_tick_ms(ctrl, 0));
0205
0206 return 0;
0207 }
0208
0209 static irqreturn_t otto_wdt_phase1_isr(int irq, void *dev_id)
0210 {
0211 struct otto_wdt_ctrl *ctrl = dev_id;
0212
0213 iowrite32(OTTO_WDT_INTR_PHASE_1, ctrl->base + OTTO_WDT_REG_INTR);
0214 dev_crit(ctrl->dev, "phase 1 timeout\n");
0215 watchdog_notify_pretimeout(&ctrl->wdev);
0216
0217 return IRQ_HANDLED;
0218 }
0219
0220 static const struct watchdog_ops otto_wdt_ops = {
0221 .owner = THIS_MODULE,
0222 .start = otto_wdt_start,
0223 .stop = otto_wdt_stop,
0224 .ping = otto_wdt_ping,
0225 .set_timeout = otto_wdt_set_timeout,
0226 .set_pretimeout = otto_wdt_set_pretimeout,
0227 .restart = otto_wdt_restart,
0228 };
0229
0230 static const struct watchdog_info otto_wdt_info = {
0231 .identity = "Realtek Otto watchdog timer",
0232 .options = WDIOF_KEEPALIVEPING |
0233 WDIOF_MAGICCLOSE |
0234 WDIOF_SETTIMEOUT |
0235 WDIOF_PRETIMEOUT,
0236 };
0237
0238 static void otto_wdt_clock_action(void *data)
0239 {
0240 clk_disable_unprepare(data);
0241 }
0242
0243 static int otto_wdt_probe_clk(struct otto_wdt_ctrl *ctrl)
0244 {
0245 struct clk *clk = devm_clk_get(ctrl->dev, NULL);
0246 int ret;
0247
0248 if (IS_ERR(clk))
0249 return dev_err_probe(ctrl->dev, PTR_ERR(clk), "Failed to get clock\n");
0250
0251 ret = clk_prepare_enable(clk);
0252 if (ret)
0253 return dev_err_probe(ctrl->dev, ret, "Failed to enable clock\n");
0254
0255 ret = devm_add_action_or_reset(ctrl->dev, otto_wdt_clock_action, clk);
0256 if (ret)
0257 return ret;
0258
0259 ctrl->clk_rate_khz = clk_get_rate(clk) / 1000;
0260 if (ctrl->clk_rate_khz == 0)
0261 return dev_err_probe(ctrl->dev, -ENXIO, "Failed to get clock rate\n");
0262
0263 return 0;
0264 }
0265
0266 static int otto_wdt_probe_reset_mode(struct otto_wdt_ctrl *ctrl)
0267 {
0268 static const char *mode_property = "realtek,reset-mode";
0269 const struct fwnode_handle *node = ctrl->dev->fwnode;
0270 int mode_count;
0271 u32 mode;
0272 u32 v;
0273
0274 if (!node)
0275 return -ENXIO;
0276
0277 mode_count = fwnode_property_string_array_count(node, mode_property);
0278 if (mode_count < 0)
0279 return mode_count;
0280 else if (mode_count == 0)
0281 return 0;
0282 else if (mode_count != 1)
0283 return -EINVAL;
0284
0285 if (fwnode_property_match_string(node, mode_property, "soc") == 0)
0286 mode = OTTO_WDT_MODE_SOC;
0287 else if (fwnode_property_match_string(node, mode_property, "cpu") == 0)
0288 mode = OTTO_WDT_MODE_CPU;
0289 else if (fwnode_property_match_string(node, mode_property, "software") == 0)
0290 mode = OTTO_WDT_MODE_SOFTWARE;
0291 else
0292 return -EINVAL;
0293
0294 v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL);
0295 v &= ~OTTO_WDT_CTRL_RST_MODE;
0296 v |= FIELD_PREP(OTTO_WDT_CTRL_RST_MODE, mode);
0297 iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);
0298
0299 return 0;
0300 }
0301
0302 static int otto_wdt_probe(struct platform_device *pdev)
0303 {
0304 struct device *dev = &pdev->dev;
0305 struct otto_wdt_ctrl *ctrl;
0306 unsigned int max_tick_ms;
0307 int ret;
0308
0309 ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
0310 if (!ctrl)
0311 return -ENOMEM;
0312
0313 ctrl->dev = dev;
0314 ctrl->base = devm_platform_ioremap_resource(pdev, 0);
0315 if (IS_ERR(ctrl->base))
0316 return PTR_ERR(ctrl->base);
0317
0318
0319 iowrite32(OTTO_WDT_INTR_PHASE_1 | OTTO_WDT_INTR_PHASE_2,
0320 ctrl->base + OTTO_WDT_REG_INTR);
0321 iowrite32(OTTO_WDT_CTRL_DEFAULT, ctrl->base + OTTO_WDT_REG_CTRL);
0322
0323 ret = otto_wdt_probe_clk(ctrl);
0324 if (ret)
0325 return ret;
0326
0327 ctrl->irq_phase1 = platform_get_irq_byname(pdev, "phase1");
0328 if (ctrl->irq_phase1 < 0)
0329 return ctrl->irq_phase1;
0330
0331 ret = devm_request_irq(dev, ctrl->irq_phase1, otto_wdt_phase1_isr, 0,
0332 "realtek-otto-wdt", ctrl);
0333 if (ret)
0334 return dev_err_probe(dev, ret, "Failed to get IRQ for phase1\n");
0335
0336 ret = otto_wdt_probe_reset_mode(ctrl);
0337 if (ret)
0338 return dev_err_probe(dev, ret, "Invalid reset mode specified\n");
0339
0340 ctrl->wdev.parent = dev;
0341 ctrl->wdev.info = &otto_wdt_info;
0342 ctrl->wdev.ops = &otto_wdt_ops;
0343
0344
0345
0346
0347
0348 ctrl->wdev.min_timeout = 2;
0349 max_tick_ms = otto_wdt_tick_ms(ctrl, OTTO_WDT_PRESCALE_MAX);
0350 ctrl->wdev.max_hw_heartbeat_ms = max_tick_ms * OTTO_WDT_TIMEOUT_TICKS_MAX;
0351 ctrl->wdev.timeout = min(30U, ctrl->wdev.max_hw_heartbeat_ms / 1000);
0352
0353 watchdog_set_drvdata(&ctrl->wdev, ctrl);
0354 watchdog_init_timeout(&ctrl->wdev, 0, dev);
0355 watchdog_stop_on_reboot(&ctrl->wdev);
0356 watchdog_set_restart_priority(&ctrl->wdev, 128);
0357
0358 ret = otto_wdt_determine_timeouts(&ctrl->wdev, ctrl->wdev.timeout, 1);
0359 if (ret)
0360 return dev_err_probe(dev, ret, "Failed to set timeout\n");
0361
0362 return devm_watchdog_register_device(dev, &ctrl->wdev);
0363 }
0364
0365 static const struct of_device_id otto_wdt_ids[] = {
0366 { .compatible = "realtek,rtl8380-wdt" },
0367 { .compatible = "realtek,rtl8390-wdt" },
0368 { .compatible = "realtek,rtl9300-wdt" },
0369 { .compatible = "realtek,rtl9310-wdt" },
0370 { }
0371 };
0372 MODULE_DEVICE_TABLE(of, otto_wdt_ids);
0373
0374 static struct platform_driver otto_wdt_driver = {
0375 .probe = otto_wdt_probe,
0376 .driver = {
0377 .name = "realtek-otto-watchdog",
0378 .of_match_table = otto_wdt_ids,
0379 },
0380 };
0381 module_platform_driver(otto_wdt_driver);
0382
0383 MODULE_LICENSE("GPL v2");
0384 MODULE_AUTHOR("Sander Vanheule <sander@svanheule.net>");
0385 MODULE_DESCRIPTION("Realtek Otto watchdog timer driver");