1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright (c) 2014, The Linux Foundation. All rights reserved. 3 */ 4 #include <linux/bits.h> 5 #include <linux/clk.h> 6 #include <linux/delay.h> 7 #include <linux/interrupt.h> 8 #include <linux/io.h> 9 #include <linux/kernel.h> 10 #include <linux/module.h> 11 #include <linux/of.h> 12 #include <linux/platform_device.h> 13 #include <linux/watchdog.h> 14 #include <linux/of_device.h> 15 16 enum wdt_reg { 17 WDT_RST, 18 WDT_EN, 19 WDT_STS, 20 WDT_BARK_TIME, 21 WDT_BITE_TIME, 22 }; 23 24 #define QCOM_WDT_ENABLE BIT(0) 25 #define QCOM_WDT_ENABLE_IRQ BIT(1) 26 27 static const u32 reg_offset_data_apcs_tmr[] = { 28 [WDT_RST] = 0x38, 29 [WDT_EN] = 0x40, 30 [WDT_STS] = 0x44, 31 [WDT_BARK_TIME] = 0x4C, 32 [WDT_BITE_TIME] = 0x5C, 33 }; 34 35 static const u32 reg_offset_data_kpss[] = { 36 [WDT_RST] = 0x4, 37 [WDT_EN] = 0x8, 38 [WDT_STS] = 0xC, 39 [WDT_BARK_TIME] = 0x10, 40 [WDT_BITE_TIME] = 0x14, 41 }; 42 43 struct qcom_wdt_match_data { 44 const u32 *offset; 45 bool pretimeout; 46 }; 47 48 struct qcom_wdt { 49 struct watchdog_device wdd; 50 unsigned long rate; 51 void __iomem *base; 52 const u32 *layout; 53 }; 54 55 static void __iomem *wdt_addr(struct qcom_wdt *wdt, enum wdt_reg reg) 56 { 57 return wdt->base + wdt->layout[reg]; 58 } 59 60 static inline 61 struct qcom_wdt *to_qcom_wdt(struct watchdog_device *wdd) 62 { 63 return container_of(wdd, struct qcom_wdt, wdd); 64 } 65 66 static inline int qcom_get_enable(struct watchdog_device *wdd) 67 { 68 int enable = QCOM_WDT_ENABLE; 69 70 if (wdd->pretimeout) 71 enable |= QCOM_WDT_ENABLE_IRQ; 72 73 return enable; 74 } 75 76 static irqreturn_t qcom_wdt_isr(int irq, void *arg) 77 { 78 struct watchdog_device *wdd = arg; 79 80 watchdog_notify_pretimeout(wdd); 81 82 return IRQ_HANDLED; 83 } 84 85 static int qcom_wdt_start(struct watchdog_device *wdd) 86 { 87 struct qcom_wdt *wdt = to_qcom_wdt(wdd); 88 unsigned int bark = wdd->timeout - wdd->pretimeout; 89 90 writel(0, wdt_addr(wdt, WDT_EN)); 91 writel(1, wdt_addr(wdt, WDT_RST)); 92 writel(bark * wdt->rate, wdt_addr(wdt, WDT_BARK_TIME)); 93 writel(wdd->timeout * wdt->rate, wdt_addr(wdt, WDT_BITE_TIME)); 94 writel(qcom_get_enable(wdd), wdt_addr(wdt, WDT_EN)); 95 return 0; 96 } 97 98 static int qcom_wdt_stop(struct watchdog_device *wdd) 99 { 100 struct qcom_wdt *wdt = to_qcom_wdt(wdd); 101 102 writel(0, wdt_addr(wdt, WDT_EN)); 103 return 0; 104 } 105 106 static int qcom_wdt_ping(struct watchdog_device *wdd) 107 { 108 struct qcom_wdt *wdt = to_qcom_wdt(wdd); 109 110 writel(1, wdt_addr(wdt, WDT_RST)); 111 return 0; 112 } 113 114 static int qcom_wdt_set_timeout(struct watchdog_device *wdd, 115 unsigned int timeout) 116 { 117 wdd->timeout = timeout; 118 return qcom_wdt_start(wdd); 119 } 120 121 static int qcom_wdt_set_pretimeout(struct watchdog_device *wdd, 122 unsigned int timeout) 123 { 124 wdd->pretimeout = timeout; 125 return qcom_wdt_start(wdd); 126 } 127 128 static int qcom_wdt_restart(struct watchdog_device *wdd, unsigned long action, 129 void *data) 130 { 131 struct qcom_wdt *wdt = to_qcom_wdt(wdd); 132 u32 timeout; 133 134 /* 135 * Trigger watchdog bite: 136 * Setup BITE_TIME to be 128ms, and enable WDT. 137 */ 138 timeout = 128 * wdt->rate / 1000; 139 140 writel(0, wdt_addr(wdt, WDT_EN)); 141 writel(1, wdt_addr(wdt, WDT_RST)); 142 writel(timeout, wdt_addr(wdt, WDT_BARK_TIME)); 143 writel(timeout, wdt_addr(wdt, WDT_BITE_TIME)); 144 writel(QCOM_WDT_ENABLE, wdt_addr(wdt, WDT_EN)); 145 146 /* 147 * Actually make sure the above sequence hits hardware before sleeping. 148 */ 149 wmb(); 150 151 msleep(150); 152 return 0; 153 } 154 155 static const struct watchdog_ops qcom_wdt_ops = { 156 .start = qcom_wdt_start, 157 .stop = qcom_wdt_stop, 158 .ping = qcom_wdt_ping, 159 .set_timeout = qcom_wdt_set_timeout, 160 .set_pretimeout = qcom_wdt_set_pretimeout, 161 .restart = qcom_wdt_restart, 162 .owner = THIS_MODULE, 163 }; 164 165 static const struct watchdog_info qcom_wdt_info = { 166 .options = WDIOF_KEEPALIVEPING 167 | WDIOF_MAGICCLOSE 168 | WDIOF_SETTIMEOUT 169 | WDIOF_CARDRESET, 170 .identity = KBUILD_MODNAME, 171 }; 172 173 static const struct watchdog_info qcom_wdt_pt_info = { 174 .options = WDIOF_KEEPALIVEPING 175 | WDIOF_MAGICCLOSE 176 | WDIOF_SETTIMEOUT 177 | WDIOF_PRETIMEOUT 178 | WDIOF_CARDRESET, 179 .identity = KBUILD_MODNAME, 180 }; 181 182 static void qcom_clk_disable_unprepare(void *data) 183 { 184 clk_disable_unprepare(data); 185 } 186 187 static const struct qcom_wdt_match_data match_data_apcs_tmr = { 188 .offset = reg_offset_data_apcs_tmr, 189 .pretimeout = false, 190 }; 191 192 static const struct qcom_wdt_match_data match_data_kpss = { 193 .offset = reg_offset_data_kpss, 194 .pretimeout = true, 195 }; 196 197 static int qcom_wdt_probe(struct platform_device *pdev) 198 { 199 struct device *dev = &pdev->dev; 200 struct qcom_wdt *wdt; 201 struct resource *res; 202 struct device_node *np = dev->of_node; 203 const struct qcom_wdt_match_data *data; 204 u32 percpu_offset; 205 int irq, ret; 206 struct clk *clk; 207 208 data = of_device_get_match_data(dev); 209 if (!data) { 210 dev_err(dev, "Unsupported QCOM WDT module\n"); 211 return -ENODEV; 212 } 213 214 wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); 215 if (!wdt) 216 return -ENOMEM; 217 218 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 219 if (!res) 220 return -ENOMEM; 221 222 /* We use CPU0's DGT for the watchdog */ 223 if (of_property_read_u32(np, "cpu-offset", &percpu_offset)) 224 percpu_offset = 0; 225 226 res->start += percpu_offset; 227 res->end += percpu_offset; 228 229 wdt->base = devm_ioremap_resource(dev, res); 230 if (IS_ERR(wdt->base)) 231 return PTR_ERR(wdt->base); 232 233 clk = devm_clk_get(dev, NULL); 234 if (IS_ERR(clk)) { 235 dev_err(dev, "failed to get input clock\n"); 236 return PTR_ERR(clk); 237 } 238 239 ret = clk_prepare_enable(clk); 240 if (ret) { 241 dev_err(dev, "failed to setup clock\n"); 242 return ret; 243 } 244 ret = devm_add_action_or_reset(dev, qcom_clk_disable_unprepare, clk); 245 if (ret) 246 return ret; 247 248 /* 249 * We use the clock rate to calculate the max timeout, so ensure it's 250 * not zero to avoid a divide-by-zero exception. 251 * 252 * WATCHDOG_CORE assumes units of seconds, if the WDT is clocked such 253 * that it would bite before a second elapses it's usefulness is 254 * limited. Bail if this is the case. 255 */ 256 wdt->rate = clk_get_rate(clk); 257 if (wdt->rate == 0 || 258 wdt->rate > 0x10000000U) { 259 dev_err(dev, "invalid clock rate\n"); 260 return -EINVAL; 261 } 262 263 /* check if there is pretimeout support */ 264 irq = platform_get_irq_optional(pdev, 0); 265 if (data->pretimeout && irq > 0) { 266 ret = devm_request_irq(dev, irq, qcom_wdt_isr, 0, 267 "wdt_bark", &wdt->wdd); 268 if (ret) 269 return ret; 270 271 wdt->wdd.info = &qcom_wdt_pt_info; 272 wdt->wdd.pretimeout = 1; 273 } else { 274 if (irq == -EPROBE_DEFER) 275 return -EPROBE_DEFER; 276 277 wdt->wdd.info = &qcom_wdt_info; 278 } 279 280 wdt->wdd.ops = &qcom_wdt_ops; 281 wdt->wdd.min_timeout = 1; 282 wdt->wdd.max_timeout = 0x10000000U / wdt->rate; 283 wdt->wdd.parent = dev; 284 wdt->layout = data->offset; 285 286 if (readl(wdt_addr(wdt, WDT_STS)) & 1) 287 wdt->wdd.bootstatus = WDIOF_CARDRESET; 288 289 /* 290 * If 'timeout-sec' unspecified in devicetree, assume a 30 second 291 * default, unless the max timeout is less than 30 seconds, then use 292 * the max instead. 293 */ 294 wdt->wdd.timeout = min(wdt->wdd.max_timeout, 30U); 295 watchdog_init_timeout(&wdt->wdd, 0, dev); 296 297 ret = devm_watchdog_register_device(dev, &wdt->wdd); 298 if (ret) 299 return ret; 300 301 platform_set_drvdata(pdev, wdt); 302 return 0; 303 } 304 305 static int __maybe_unused qcom_wdt_suspend(struct device *dev) 306 { 307 struct qcom_wdt *wdt = dev_get_drvdata(dev); 308 309 if (watchdog_active(&wdt->wdd)) 310 qcom_wdt_stop(&wdt->wdd); 311 312 return 0; 313 } 314 315 static int __maybe_unused qcom_wdt_resume(struct device *dev) 316 { 317 struct qcom_wdt *wdt = dev_get_drvdata(dev); 318 319 if (watchdog_active(&wdt->wdd)) 320 qcom_wdt_start(&wdt->wdd); 321 322 return 0; 323 } 324 325 static SIMPLE_DEV_PM_OPS(qcom_wdt_pm_ops, qcom_wdt_suspend, qcom_wdt_resume); 326 327 static const struct of_device_id qcom_wdt_of_table[] = { 328 { .compatible = "qcom,kpss-timer", .data = &match_data_apcs_tmr }, 329 { .compatible = "qcom,scss-timer", .data = &match_data_apcs_tmr }, 330 { .compatible = "qcom,kpss-wdt", .data = &match_data_kpss }, 331 { }, 332 }; 333 MODULE_DEVICE_TABLE(of, qcom_wdt_of_table); 334 335 static struct platform_driver qcom_watchdog_driver = { 336 .probe = qcom_wdt_probe, 337 .driver = { 338 .name = KBUILD_MODNAME, 339 .of_match_table = qcom_wdt_of_table, 340 .pm = &qcom_wdt_pm_ops, 341 }, 342 }; 343 module_platform_driver(qcom_watchdog_driver); 344 345 MODULE_DESCRIPTION("QCOM KPSS Watchdog Driver"); 346 MODULE_LICENSE("GPL v2"); 347