1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Spreadtrum watchdog driver 4 * Copyright (C) 2017 Spreadtrum - http://www.spreadtrum.com 5 */ 6 7#include <linux/bitops.h> 8#include <linux/clk.h> 9#include <linux/device.h> 10#include <linux/err.h> 11#include <linux/interrupt.h> 12#include <linux/io.h> 13#include <linux/kernel.h> 14#include <linux/module.h> 15#include <linux/of.h> 16#include <linux/of_address.h> 17#include <linux/platform_device.h> 18#include <linux/watchdog.h> 19 20#define SPRD_WDT_LOAD_LOW 0x0 21#define SPRD_WDT_LOAD_HIGH 0x4 22#define SPRD_WDT_CTRL 0x8 23#define SPRD_WDT_INT_CLR 0xc 24#define SPRD_WDT_INT_RAW 0x10 25#define SPRD_WDT_INT_MSK 0x14 26#define SPRD_WDT_CNT_LOW 0x18 27#define SPRD_WDT_CNT_HIGH 0x1c 28#define SPRD_WDT_LOCK 0x20 29#define SPRD_WDT_IRQ_LOAD_LOW 0x2c 30#define SPRD_WDT_IRQ_LOAD_HIGH 0x30 31 32/* WDT_CTRL */ 33#define SPRD_WDT_INT_EN_BIT BIT(0) 34#define SPRD_WDT_CNT_EN_BIT BIT(1) 35#define SPRD_WDT_NEW_VER_EN BIT(2) 36#define SPRD_WDT_RST_EN_BIT BIT(3) 37 38/* WDT_INT_CLR */ 39#define SPRD_WDT_INT_CLEAR_BIT BIT(0) 40#define SPRD_WDT_RST_CLEAR_BIT BIT(3) 41 42/* WDT_INT_RAW */ 43#define SPRD_WDT_INT_RAW_BIT BIT(0) 44#define SPRD_WDT_RST_RAW_BIT BIT(3) 45#define SPRD_WDT_LD_BUSY_BIT BIT(4) 46 47/* 1s equal to 32768 counter steps */ 48#define SPRD_WDT_CNT_STEP 32768 49 50#define SPRD_WDT_UNLOCK_KEY 0xe551 51#define SPRD_WDT_MIN_TIMEOUT 3 52#define SPRD_WDT_MAX_TIMEOUT 60 53 54#define SPRD_WDT_CNT_HIGH_SHIFT 16 55#define SPRD_WDT_LOW_VALUE_MASK GENMASK(15, 0) 56#define SPRD_WDT_LOAD_TIMEOUT 1000 57 58struct sprd_wdt { 59 void __iomem *base; 60 struct watchdog_device wdd; 61 struct clk *enable; 62 struct clk *rtc_enable; 63 int irq; 64}; 65 66static inline struct sprd_wdt *to_sprd_wdt(struct watchdog_device *wdd) 67{ 68 return container_of(wdd, struct sprd_wdt, wdd); 69} 70 71static inline void sprd_wdt_lock(void __iomem *addr) 72{ 73 writel_relaxed(0x0, addr + SPRD_WDT_LOCK); 74} 75 76static inline void sprd_wdt_unlock(void __iomem *addr) 77{ 78 writel_relaxed(SPRD_WDT_UNLOCK_KEY, addr + SPRD_WDT_LOCK); 79} 80 81static irqreturn_t sprd_wdt_isr(int irq, void *dev_id) 82{ 83 struct sprd_wdt *wdt = (struct sprd_wdt *)dev_id; 84 85 sprd_wdt_unlock(wdt->base); 86 writel_relaxed(SPRD_WDT_INT_CLEAR_BIT, wdt->base + SPRD_WDT_INT_CLR); 87 sprd_wdt_lock(wdt->base); 88 watchdog_notify_pretimeout(&wdt->wdd); 89 return IRQ_HANDLED; 90} 91 92static u32 sprd_wdt_get_cnt_value(struct sprd_wdt *wdt) 93{ 94 u32 val; 95 96 val = readl_relaxed(wdt->base + SPRD_WDT_CNT_HIGH) << 97 SPRD_WDT_CNT_HIGH_SHIFT; 98 val |= readl_relaxed(wdt->base + SPRD_WDT_CNT_LOW) & 99 SPRD_WDT_LOW_VALUE_MASK; 100 101 return val; 102} 103 104static int sprd_wdt_load_value(struct sprd_wdt *wdt, u32 timeout, 105 u32 pretimeout) 106{ 107 u32 val, delay_cnt = 0; 108 u32 tmr_step = timeout * SPRD_WDT_CNT_STEP; 109 u32 prtmr_step = pretimeout * SPRD_WDT_CNT_STEP; 110 111 /* 112 * Waiting the load value operation done, 113 * it needs two or three RTC clock cycles. 114 */ 115 do { 116 val = readl_relaxed(wdt->base + SPRD_WDT_INT_RAW); 117 if (!(val & SPRD_WDT_LD_BUSY_BIT)) 118 break; 119 120 cpu_relax(); 121 } while (delay_cnt++ < SPRD_WDT_LOAD_TIMEOUT); 122 123 if (delay_cnt >= SPRD_WDT_LOAD_TIMEOUT) 124 return -EBUSY; 125 126 sprd_wdt_unlock(wdt->base); 127 writel_relaxed((tmr_step >> SPRD_WDT_CNT_HIGH_SHIFT) & 128 SPRD_WDT_LOW_VALUE_MASK, wdt->base + SPRD_WDT_LOAD_HIGH); 129 writel_relaxed((tmr_step & SPRD_WDT_LOW_VALUE_MASK), 130 wdt->base + SPRD_WDT_LOAD_LOW); 131 writel_relaxed((prtmr_step >> SPRD_WDT_CNT_HIGH_SHIFT) & 132 SPRD_WDT_LOW_VALUE_MASK, 133 wdt->base + SPRD_WDT_IRQ_LOAD_HIGH); 134 writel_relaxed(prtmr_step & SPRD_WDT_LOW_VALUE_MASK, 135 wdt->base + SPRD_WDT_IRQ_LOAD_LOW); 136 sprd_wdt_lock(wdt->base); 137 138 return 0; 139} 140 141static int sprd_wdt_enable(struct sprd_wdt *wdt) 142{ 143 u32 val; 144 int ret; 145 146 ret = clk_prepare_enable(wdt->enable); 147 if (ret) 148 return ret; 149 ret = clk_prepare_enable(wdt->rtc_enable); 150 if (ret) { 151 clk_disable_unprepare(wdt->enable); 152 return ret; 153 } 154 155 sprd_wdt_unlock(wdt->base); 156 val = readl_relaxed(wdt->base + SPRD_WDT_CTRL); 157 val |= SPRD_WDT_NEW_VER_EN; 158 writel_relaxed(val, wdt->base + SPRD_WDT_CTRL); 159 sprd_wdt_lock(wdt->base); 160 return 0; 161} 162 163static void sprd_wdt_disable(void *_data) 164{ 165 struct sprd_wdt *wdt = _data; 166 167 sprd_wdt_unlock(wdt->base); 168 writel_relaxed(0x0, wdt->base + SPRD_WDT_CTRL); 169 sprd_wdt_lock(wdt->base); 170 171 clk_disable_unprepare(wdt->rtc_enable); 172 clk_disable_unprepare(wdt->enable); 173} 174 175static int sprd_wdt_start(struct watchdog_device *wdd) 176{ 177 struct sprd_wdt *wdt = to_sprd_wdt(wdd); 178 u32 val; 179 int ret; 180 181 ret = sprd_wdt_load_value(wdt, wdd->timeout, wdd->pretimeout); 182 if (ret) 183 return ret; 184 185 sprd_wdt_unlock(wdt->base); 186 val = readl_relaxed(wdt->base + SPRD_WDT_CTRL); 187 val |= SPRD_WDT_CNT_EN_BIT | SPRD_WDT_INT_EN_BIT | SPRD_WDT_RST_EN_BIT; 188 writel_relaxed(val, wdt->base + SPRD_WDT_CTRL); 189 sprd_wdt_lock(wdt->base); 190 set_bit(WDOG_HW_RUNNING, &wdd->status); 191 192 return 0; 193} 194 195static int sprd_wdt_stop(struct watchdog_device *wdd) 196{ 197 struct sprd_wdt *wdt = to_sprd_wdt(wdd); 198 u32 val; 199 200 sprd_wdt_unlock(wdt->base); 201 val = readl_relaxed(wdt->base + SPRD_WDT_CTRL); 202 val &= ~(SPRD_WDT_CNT_EN_BIT | SPRD_WDT_RST_EN_BIT | 203 SPRD_WDT_INT_EN_BIT); 204 writel_relaxed(val, wdt->base + SPRD_WDT_CTRL); 205 sprd_wdt_lock(wdt->base); 206 return 0; 207} 208 209static int sprd_wdt_set_timeout(struct watchdog_device *wdd, 210 u32 timeout) 211{ 212 struct sprd_wdt *wdt = to_sprd_wdt(wdd); 213 214 if (timeout == wdd->timeout) 215 return 0; 216 217 wdd->timeout = timeout; 218 219 return sprd_wdt_load_value(wdt, timeout, wdd->pretimeout); 220} 221 222static int sprd_wdt_set_pretimeout(struct watchdog_device *wdd, 223 u32 new_pretimeout) 224{ 225 struct sprd_wdt *wdt = to_sprd_wdt(wdd); 226 227 if (new_pretimeout < wdd->min_timeout) 228 return -EINVAL; 229 230 wdd->pretimeout = new_pretimeout; 231 232 return sprd_wdt_load_value(wdt, wdd->timeout, new_pretimeout); 233} 234 235static u32 sprd_wdt_get_timeleft(struct watchdog_device *wdd) 236{ 237 struct sprd_wdt *wdt = to_sprd_wdt(wdd); 238 u32 val; 239 240 val = sprd_wdt_get_cnt_value(wdt); 241 return val / SPRD_WDT_CNT_STEP; 242} 243 244static const struct watchdog_ops sprd_wdt_ops = { 245 .owner = THIS_MODULE, 246 .start = sprd_wdt_start, 247 .stop = sprd_wdt_stop, 248 .set_timeout = sprd_wdt_set_timeout, 249 .set_pretimeout = sprd_wdt_set_pretimeout, 250 .get_timeleft = sprd_wdt_get_timeleft, 251}; 252 253static const struct watchdog_info sprd_wdt_info = { 254 .options = WDIOF_SETTIMEOUT | 255 WDIOF_PRETIMEOUT | 256 WDIOF_MAGICCLOSE | 257 WDIOF_KEEPALIVEPING, 258 .identity = "Spreadtrum Watchdog Timer", 259}; 260 261static int sprd_wdt_probe(struct platform_device *pdev) 262{ 263 struct device *dev = &pdev->dev; 264 struct sprd_wdt *wdt; 265 int ret; 266 267 wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); 268 if (!wdt) 269 return -ENOMEM; 270 271 wdt->base = devm_platform_ioremap_resource(pdev, 0); 272 if (IS_ERR(wdt->base)) 273 return PTR_ERR(wdt->base); 274 275 wdt->enable = devm_clk_get(dev, "enable"); 276 if (IS_ERR(wdt->enable)) { 277 dev_err(dev, "can't get the enable clock\n"); 278 return PTR_ERR(wdt->enable); 279 } 280 281 wdt->rtc_enable = devm_clk_get(dev, "rtc_enable"); 282 if (IS_ERR(wdt->rtc_enable)) { 283 dev_err(dev, "can't get the rtc enable clock\n"); 284 return PTR_ERR(wdt->rtc_enable); 285 } 286 287 wdt->irq = platform_get_irq(pdev, 0); 288 if (wdt->irq < 0) 289 return wdt->irq; 290 291 ret = devm_request_irq(dev, wdt->irq, sprd_wdt_isr, IRQF_NO_SUSPEND, 292 "sprd-wdt", (void *)wdt); 293 if (ret) { 294 dev_err(dev, "failed to register irq\n"); 295 return ret; 296 } 297 298 wdt->wdd.info = &sprd_wdt_info; 299 wdt->wdd.ops = &sprd_wdt_ops; 300 wdt->wdd.parent = dev; 301 wdt->wdd.min_timeout = SPRD_WDT_MIN_TIMEOUT; 302 wdt->wdd.max_timeout = SPRD_WDT_MAX_TIMEOUT; 303 wdt->wdd.timeout = SPRD_WDT_MAX_TIMEOUT; 304 305 ret = sprd_wdt_enable(wdt); 306 if (ret) { 307 dev_err(dev, "failed to enable wdt\n"); 308 return ret; 309 } 310 ret = devm_add_action_or_reset(dev, sprd_wdt_disable, wdt); 311 if (ret) { 312 dev_err(dev, "Failed to add wdt disable action\n"); 313 return ret; 314 } 315 316 watchdog_set_nowayout(&wdt->wdd, WATCHDOG_NOWAYOUT); 317 watchdog_init_timeout(&wdt->wdd, 0, dev); 318 319 ret = devm_watchdog_register_device(dev, &wdt->wdd); 320 if (ret) { 321 sprd_wdt_disable(wdt); 322 return ret; 323 } 324 platform_set_drvdata(pdev, wdt); 325 326 return 0; 327} 328 329static int __maybe_unused sprd_wdt_pm_suspend(struct device *dev) 330{ 331 struct sprd_wdt *wdt = dev_get_drvdata(dev); 332 333 if (watchdog_active(&wdt->wdd)) 334 sprd_wdt_stop(&wdt->wdd); 335 sprd_wdt_disable(wdt); 336 337 return 0; 338} 339 340static int __maybe_unused sprd_wdt_pm_resume(struct device *dev) 341{ 342 struct sprd_wdt *wdt = dev_get_drvdata(dev); 343 int ret; 344 345 ret = sprd_wdt_enable(wdt); 346 if (ret) 347 return ret; 348 349 if (watchdog_active(&wdt->wdd)) 350 ret = sprd_wdt_start(&wdt->wdd); 351 352 return ret; 353} 354 355static const struct dev_pm_ops sprd_wdt_pm_ops = { 356 SET_SYSTEM_SLEEP_PM_OPS(sprd_wdt_pm_suspend, 357 sprd_wdt_pm_resume) 358}; 359 360static const struct of_device_id sprd_wdt_match_table[] = { 361 { .compatible = "sprd,sp9860-wdt", }, 362 {}, 363}; 364MODULE_DEVICE_TABLE(of, sprd_wdt_match_table); 365 366static struct platform_driver sprd_watchdog_driver = { 367 .probe = sprd_wdt_probe, 368 .driver = { 369 .name = "sprd-wdt", 370 .of_match_table = sprd_wdt_match_table, 371 .pm = &sprd_wdt_pm_ops, 372 }, 373}; 374module_platform_driver(sprd_watchdog_driver); 375 376MODULE_AUTHOR("Eric Long <eric.long@spreadtrum.com>"); 377MODULE_DESCRIPTION("Spreadtrum Watchdog Timer Controller Driver"); 378MODULE_LICENSE("GPL v2"); 379