root/drivers/watchdog/sprd_wdt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. to_sprd_wdt
  2. sprd_wdt_lock
  3. sprd_wdt_unlock
  4. sprd_wdt_isr
  5. sprd_wdt_get_cnt_value
  6. sprd_wdt_load_value
  7. sprd_wdt_enable
  8. sprd_wdt_disable
  9. sprd_wdt_start
  10. sprd_wdt_stop
  11. sprd_wdt_set_timeout
  12. sprd_wdt_set_pretimeout
  13. sprd_wdt_get_timeleft
  14. sprd_wdt_probe
  15. sprd_wdt_pm_suspend
  16. sprd_wdt_pm_resume

   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 
  58 struct 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 
  66 static inline struct sprd_wdt *to_sprd_wdt(struct watchdog_device *wdd)
  67 {
  68         return container_of(wdd, struct sprd_wdt, wdd);
  69 }
  70 
  71 static inline void sprd_wdt_lock(void __iomem *addr)
  72 {
  73         writel_relaxed(0x0, addr + SPRD_WDT_LOCK);
  74 }
  75 
  76 static inline void sprd_wdt_unlock(void __iomem *addr)
  77 {
  78         writel_relaxed(SPRD_WDT_UNLOCK_KEY, addr + SPRD_WDT_LOCK);
  79 }
  80 
  81 static 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 
  92 static 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 
 104 static 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         sprd_wdt_unlock(wdt->base);
 112         writel_relaxed((tmr_step >> SPRD_WDT_CNT_HIGH_SHIFT) &
 113                       SPRD_WDT_LOW_VALUE_MASK, wdt->base + SPRD_WDT_LOAD_HIGH);
 114         writel_relaxed((tmr_step & SPRD_WDT_LOW_VALUE_MASK),
 115                        wdt->base + SPRD_WDT_LOAD_LOW);
 116         writel_relaxed((prtmr_step >> SPRD_WDT_CNT_HIGH_SHIFT) &
 117                         SPRD_WDT_LOW_VALUE_MASK,
 118                        wdt->base + SPRD_WDT_IRQ_LOAD_HIGH);
 119         writel_relaxed(prtmr_step & SPRD_WDT_LOW_VALUE_MASK,
 120                        wdt->base + SPRD_WDT_IRQ_LOAD_LOW);
 121         sprd_wdt_lock(wdt->base);
 122 
 123         /*
 124          * Waiting the load value operation done,
 125          * it needs two or three RTC clock cycles.
 126          */
 127         do {
 128                 val = readl_relaxed(wdt->base + SPRD_WDT_INT_RAW);
 129                 if (!(val & SPRD_WDT_LD_BUSY_BIT))
 130                         break;
 131 
 132                 cpu_relax();
 133         } while (delay_cnt++ < SPRD_WDT_LOAD_TIMEOUT);
 134 
 135         if (delay_cnt >= SPRD_WDT_LOAD_TIMEOUT)
 136                 return -EBUSY;
 137         return 0;
 138 }
 139 
 140 static int sprd_wdt_enable(struct sprd_wdt *wdt)
 141 {
 142         u32 val;
 143         int ret;
 144 
 145         ret = clk_prepare_enable(wdt->enable);
 146         if (ret)
 147                 return ret;
 148         ret = clk_prepare_enable(wdt->rtc_enable);
 149         if (ret) {
 150                 clk_disable_unprepare(wdt->enable);
 151                 return ret;
 152         }
 153 
 154         sprd_wdt_unlock(wdt->base);
 155         val = readl_relaxed(wdt->base + SPRD_WDT_CTRL);
 156         val |= SPRD_WDT_NEW_VER_EN;
 157         writel_relaxed(val, wdt->base + SPRD_WDT_CTRL);
 158         sprd_wdt_lock(wdt->base);
 159         return 0;
 160 }
 161 
 162 static void sprd_wdt_disable(void *_data)
 163 {
 164         struct sprd_wdt *wdt = _data;
 165 
 166         sprd_wdt_unlock(wdt->base);
 167         writel_relaxed(0x0, wdt->base + SPRD_WDT_CTRL);
 168         sprd_wdt_lock(wdt->base);
 169 
 170         clk_disable_unprepare(wdt->rtc_enable);
 171         clk_disable_unprepare(wdt->enable);
 172 }
 173 
 174 static int sprd_wdt_start(struct watchdog_device *wdd)
 175 {
 176         struct sprd_wdt *wdt = to_sprd_wdt(wdd);
 177         u32 val;
 178         int ret;
 179 
 180         ret = sprd_wdt_load_value(wdt, wdd->timeout, wdd->pretimeout);
 181         if (ret)
 182                 return ret;
 183 
 184         sprd_wdt_unlock(wdt->base);
 185         val = readl_relaxed(wdt->base + SPRD_WDT_CTRL);
 186         val |= SPRD_WDT_CNT_EN_BIT | SPRD_WDT_INT_EN_BIT | SPRD_WDT_RST_EN_BIT;
 187         writel_relaxed(val, wdt->base + SPRD_WDT_CTRL);
 188         sprd_wdt_lock(wdt->base);
 189         set_bit(WDOG_HW_RUNNING, &wdd->status);
 190 
 191         return 0;
 192 }
 193 
 194 static int sprd_wdt_stop(struct watchdog_device *wdd)
 195 {
 196         struct sprd_wdt *wdt = to_sprd_wdt(wdd);
 197         u32 val;
 198 
 199         sprd_wdt_unlock(wdt->base);
 200         val = readl_relaxed(wdt->base + SPRD_WDT_CTRL);
 201         val &= ~(SPRD_WDT_CNT_EN_BIT | SPRD_WDT_RST_EN_BIT |
 202                 SPRD_WDT_INT_EN_BIT);
 203         writel_relaxed(val, wdt->base + SPRD_WDT_CTRL);
 204         sprd_wdt_lock(wdt->base);
 205         return 0;
 206 }
 207 
 208 static int sprd_wdt_set_timeout(struct watchdog_device *wdd,
 209                                 u32 timeout)
 210 {
 211         struct sprd_wdt *wdt = to_sprd_wdt(wdd);
 212 
 213         if (timeout == wdd->timeout)
 214                 return 0;
 215 
 216         wdd->timeout = timeout;
 217 
 218         return sprd_wdt_load_value(wdt, timeout, wdd->pretimeout);
 219 }
 220 
 221 static int sprd_wdt_set_pretimeout(struct watchdog_device *wdd,
 222                                    u32 new_pretimeout)
 223 {
 224         struct sprd_wdt *wdt = to_sprd_wdt(wdd);
 225 
 226         if (new_pretimeout < wdd->min_timeout)
 227                 return -EINVAL;
 228 
 229         wdd->pretimeout = new_pretimeout;
 230 
 231         return sprd_wdt_load_value(wdt, wdd->timeout, new_pretimeout);
 232 }
 233 
 234 static u32 sprd_wdt_get_timeleft(struct watchdog_device *wdd)
 235 {
 236         struct sprd_wdt *wdt = to_sprd_wdt(wdd);
 237         u32 val;
 238 
 239         val = sprd_wdt_get_cnt_value(wdt);
 240         return val / SPRD_WDT_CNT_STEP;
 241 }
 242 
 243 static const struct watchdog_ops sprd_wdt_ops = {
 244         .owner = THIS_MODULE,
 245         .start = sprd_wdt_start,
 246         .stop = sprd_wdt_stop,
 247         .set_timeout = sprd_wdt_set_timeout,
 248         .set_pretimeout = sprd_wdt_set_pretimeout,
 249         .get_timeleft = sprd_wdt_get_timeleft,
 250 };
 251 
 252 static const struct watchdog_info sprd_wdt_info = {
 253         .options = WDIOF_SETTIMEOUT |
 254                    WDIOF_PRETIMEOUT |
 255                    WDIOF_MAGICCLOSE |
 256                    WDIOF_KEEPALIVEPING,
 257         .identity = "Spreadtrum Watchdog Timer",
 258 };
 259 
 260 static int sprd_wdt_probe(struct platform_device *pdev)
 261 {
 262         struct device *dev = &pdev->dev;
 263         struct sprd_wdt *wdt;
 264         int ret;
 265 
 266         wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
 267         if (!wdt)
 268                 return -ENOMEM;
 269 
 270         wdt->base = devm_platform_ioremap_resource(pdev, 0);
 271         if (IS_ERR(wdt->base))
 272                 return PTR_ERR(wdt->base);
 273 
 274         wdt->enable = devm_clk_get(dev, "enable");
 275         if (IS_ERR(wdt->enable)) {
 276                 dev_err(dev, "can't get the enable clock\n");
 277                 return PTR_ERR(wdt->enable);
 278         }
 279 
 280         wdt->rtc_enable = devm_clk_get(dev, "rtc_enable");
 281         if (IS_ERR(wdt->rtc_enable)) {
 282                 dev_err(dev, "can't get the rtc enable clock\n");
 283                 return PTR_ERR(wdt->rtc_enable);
 284         }
 285 
 286         wdt->irq = platform_get_irq(pdev, 0);
 287         if (wdt->irq < 0)
 288                 return wdt->irq;
 289 
 290         ret = devm_request_irq(dev, wdt->irq, sprd_wdt_isr, IRQF_NO_SUSPEND,
 291                                "sprd-wdt", (void *)wdt);
 292         if (ret) {
 293                 dev_err(dev, "failed to register irq\n");
 294                 return ret;
 295         }
 296 
 297         wdt->wdd.info = &sprd_wdt_info;
 298         wdt->wdd.ops = &sprd_wdt_ops;
 299         wdt->wdd.parent = dev;
 300         wdt->wdd.min_timeout = SPRD_WDT_MIN_TIMEOUT;
 301         wdt->wdd.max_timeout = SPRD_WDT_MAX_TIMEOUT;
 302         wdt->wdd.timeout = SPRD_WDT_MAX_TIMEOUT;
 303 
 304         ret = sprd_wdt_enable(wdt);
 305         if (ret) {
 306                 dev_err(dev, "failed to enable wdt\n");
 307                 return ret;
 308         }
 309         ret = devm_add_action_or_reset(dev, sprd_wdt_disable, wdt);
 310         if (ret) {
 311                 dev_err(dev, "Failed to add wdt disable action\n");
 312                 return ret;
 313         }
 314 
 315         watchdog_set_nowayout(&wdt->wdd, WATCHDOG_NOWAYOUT);
 316         watchdog_init_timeout(&wdt->wdd, 0, dev);
 317 
 318         ret = devm_watchdog_register_device(dev, &wdt->wdd);
 319         if (ret) {
 320                 sprd_wdt_disable(wdt);
 321                 return ret;
 322         }
 323         platform_set_drvdata(pdev, wdt);
 324 
 325         return 0;
 326 }
 327 
 328 static int __maybe_unused sprd_wdt_pm_suspend(struct device *dev)
 329 {
 330         struct sprd_wdt *wdt = dev_get_drvdata(dev);
 331 
 332         if (watchdog_active(&wdt->wdd))
 333                 sprd_wdt_stop(&wdt->wdd);
 334         sprd_wdt_disable(wdt);
 335 
 336         return 0;
 337 }
 338 
 339 static int __maybe_unused sprd_wdt_pm_resume(struct device *dev)
 340 {
 341         struct sprd_wdt *wdt = dev_get_drvdata(dev);
 342         int ret;
 343 
 344         ret = sprd_wdt_enable(wdt);
 345         if (ret)
 346                 return ret;
 347 
 348         if (watchdog_active(&wdt->wdd)) {
 349                 ret = sprd_wdt_start(&wdt->wdd);
 350                 if (ret) {
 351                         sprd_wdt_disable(wdt);
 352                         return ret;
 353                 }
 354         }
 355 
 356         return 0;
 357 }
 358 
 359 static const struct dev_pm_ops sprd_wdt_pm_ops = {
 360         SET_SYSTEM_SLEEP_PM_OPS(sprd_wdt_pm_suspend,
 361                                 sprd_wdt_pm_resume)
 362 };
 363 
 364 static const struct of_device_id sprd_wdt_match_table[] = {
 365         { .compatible = "sprd,sp9860-wdt", },
 366         {},
 367 };
 368 MODULE_DEVICE_TABLE(of, sprd_wdt_match_table);
 369 
 370 static struct platform_driver sprd_watchdog_driver = {
 371         .probe  = sprd_wdt_probe,
 372         .driver = {
 373                 .name = "sprd-wdt",
 374                 .of_match_table = sprd_wdt_match_table,
 375                 .pm = &sprd_wdt_pm_ops,
 376         },
 377 };
 378 module_platform_driver(sprd_watchdog_driver);
 379 
 380 MODULE_AUTHOR("Eric Long <eric.long@spreadtrum.com>");
 381 MODULE_DESCRIPTION("Spreadtrum Watchdog Timer Controller Driver");
 382 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */