root/drivers/watchdog/qcom-wdt.c

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

DEFINITIONS

This source file includes following definitions.
  1. wdt_addr
  2. to_qcom_wdt
  3. qcom_get_enable
  4. qcom_wdt_isr
  5. qcom_wdt_start
  6. qcom_wdt_stop
  7. qcom_wdt_ping
  8. qcom_wdt_set_timeout
  9. qcom_wdt_set_pretimeout
  10. qcom_wdt_restart
  11. qcom_clk_disable_unprepare
  12. qcom_wdt_probe
  13. qcom_wdt_suspend
  14. qcom_wdt_resume

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

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