Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * drivers/char/watchdog/sp805-wdt.c
0004  *
0005  * Watchdog driver for ARM SP805 watchdog module
0006  *
0007  * Copyright (C) 2010 ST Microelectronics
0008  * Viresh Kumar <vireshk@kernel.org>
0009  *
0010  * This file is licensed under the terms of the GNU General Public
0011  * License version 2 or later. This program is licensed "as is" without any
0012  * warranty of any kind, whether express or implied.
0013  */
0014 
0015 #include <linux/device.h>
0016 #include <linux/resource.h>
0017 #include <linux/amba/bus.h>
0018 #include <linux/bitops.h>
0019 #include <linux/clk.h>
0020 #include <linux/io.h>
0021 #include <linux/ioport.h>
0022 #include <linux/kernel.h>
0023 #include <linux/math64.h>
0024 #include <linux/module.h>
0025 #include <linux/moduleparam.h>
0026 #include <linux/pm.h>
0027 #include <linux/property.h>
0028 #include <linux/slab.h>
0029 #include <linux/spinlock.h>
0030 #include <linux/types.h>
0031 #include <linux/watchdog.h>
0032 
0033 /* default timeout in seconds */
0034 #define DEFAULT_TIMEOUT     60
0035 
0036 #define MODULE_NAME     "sp805-wdt"
0037 
0038 /* watchdog register offsets and masks */
0039 #define WDTLOAD         0x000
0040     #define LOAD_MIN    0x00000001
0041     #define LOAD_MAX    0xFFFFFFFF
0042 #define WDTVALUE        0x004
0043 #define WDTCONTROL      0x008
0044     /* control register masks */
0045     #define INT_ENABLE  (1 << 0)
0046     #define RESET_ENABLE    (1 << 1)
0047     #define ENABLE_MASK (INT_ENABLE | RESET_ENABLE)
0048 #define WDTINTCLR       0x00C
0049 #define WDTRIS          0x010
0050 #define WDTMIS          0x014
0051     #define INT_MASK    (1 << 0)
0052 #define WDTLOCK         0xC00
0053     #define UNLOCK      0x1ACCE551
0054     #define LOCK        0x00000001
0055 
0056 /**
0057  * struct sp805_wdt: sp805 wdt device structure
0058  * @wdd: instance of struct watchdog_device
0059  * @lock: spin lock protecting dev structure and io access
0060  * @base: base address of wdt
0061  * @clk: (optional) clock structure of wdt
0062  * @rate: (optional) clock rate when provided via properties
0063  * @adev: amba device structure of wdt
0064  * @status: current status of wdt
0065  * @load_val: load value to be set for current timeout
0066  */
0067 struct sp805_wdt {
0068     struct watchdog_device      wdd;
0069     spinlock_t          lock;
0070     void __iomem            *base;
0071     struct clk          *clk;
0072     u64             rate;
0073     struct amba_device      *adev;
0074     unsigned int            load_val;
0075 };
0076 
0077 static bool nowayout = WATCHDOG_NOWAYOUT;
0078 module_param(nowayout, bool, 0);
0079 MODULE_PARM_DESC(nowayout,
0080         "Set to 1 to keep watchdog running after device release");
0081 
0082 /* returns true if wdt is running; otherwise returns false */
0083 static bool wdt_is_running(struct watchdog_device *wdd)
0084 {
0085     struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
0086     u32 wdtcontrol = readl_relaxed(wdt->base + WDTCONTROL);
0087 
0088     return (wdtcontrol & ENABLE_MASK) == ENABLE_MASK;
0089 }
0090 
0091 /* This routine finds load value that will reset system in required timout */
0092 static int wdt_setload(struct watchdog_device *wdd, unsigned int timeout)
0093 {
0094     struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
0095     u64 load, rate;
0096 
0097     rate = wdt->rate;
0098 
0099     /*
0100      * sp805 runs counter with given value twice, after the end of first
0101      * counter it gives an interrupt and then starts counter again. If
0102      * interrupt already occurred then it resets the system. This is why
0103      * load is half of what should be required.
0104      */
0105     load = div_u64(rate, 2) * timeout - 1;
0106 
0107     load = (load > LOAD_MAX) ? LOAD_MAX : load;
0108     load = (load < LOAD_MIN) ? LOAD_MIN : load;
0109 
0110     spin_lock(&wdt->lock);
0111     wdt->load_val = load;
0112     /* roundup timeout to closest positive integer value */
0113     wdd->timeout = div_u64((load + 1) * 2 + (rate / 2), rate);
0114     spin_unlock(&wdt->lock);
0115 
0116     return 0;
0117 }
0118 
0119 /* returns number of seconds left for reset to occur */
0120 static unsigned int wdt_timeleft(struct watchdog_device *wdd)
0121 {
0122     struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
0123     u64 load;
0124 
0125     spin_lock(&wdt->lock);
0126     load = readl_relaxed(wdt->base + WDTVALUE);
0127 
0128     /*If the interrupt is inactive then time left is WDTValue + WDTLoad. */
0129     if (!(readl_relaxed(wdt->base + WDTRIS) & INT_MASK))
0130         load += wdt->load_val + 1;
0131     spin_unlock(&wdt->lock);
0132 
0133     return div_u64(load, wdt->rate);
0134 }
0135 
0136 static int
0137 wdt_restart(struct watchdog_device *wdd, unsigned long mode, void *cmd)
0138 {
0139     struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
0140 
0141     writel_relaxed(UNLOCK, wdt->base + WDTLOCK);
0142     writel_relaxed(0, wdt->base + WDTCONTROL);
0143     writel_relaxed(0, wdt->base + WDTLOAD);
0144     writel_relaxed(INT_ENABLE | RESET_ENABLE, wdt->base + WDTCONTROL);
0145 
0146     /* Flush posted writes. */
0147     readl_relaxed(wdt->base + WDTLOCK);
0148 
0149     return 0;
0150 }
0151 
0152 static int wdt_config(struct watchdog_device *wdd, bool ping)
0153 {
0154     struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
0155     int ret;
0156 
0157     if (!ping) {
0158 
0159         ret = clk_prepare_enable(wdt->clk);
0160         if (ret) {
0161             dev_err(&wdt->adev->dev, "clock enable fail");
0162             return ret;
0163         }
0164     }
0165 
0166     spin_lock(&wdt->lock);
0167 
0168     writel_relaxed(UNLOCK, wdt->base + WDTLOCK);
0169     writel_relaxed(wdt->load_val, wdt->base + WDTLOAD);
0170     writel_relaxed(INT_MASK, wdt->base + WDTINTCLR);
0171 
0172     if (!ping)
0173         writel_relaxed(INT_ENABLE | RESET_ENABLE, wdt->base +
0174                 WDTCONTROL);
0175 
0176     writel_relaxed(LOCK, wdt->base + WDTLOCK);
0177 
0178     /* Flush posted writes. */
0179     readl_relaxed(wdt->base + WDTLOCK);
0180     spin_unlock(&wdt->lock);
0181 
0182     return 0;
0183 }
0184 
0185 static int wdt_ping(struct watchdog_device *wdd)
0186 {
0187     return wdt_config(wdd, true);
0188 }
0189 
0190 /* enables watchdog timers reset */
0191 static int wdt_enable(struct watchdog_device *wdd)
0192 {
0193     return wdt_config(wdd, false);
0194 }
0195 
0196 /* disables watchdog timers reset */
0197 static int wdt_disable(struct watchdog_device *wdd)
0198 {
0199     struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
0200 
0201     spin_lock(&wdt->lock);
0202 
0203     writel_relaxed(UNLOCK, wdt->base + WDTLOCK);
0204     writel_relaxed(0, wdt->base + WDTCONTROL);
0205     writel_relaxed(LOCK, wdt->base + WDTLOCK);
0206 
0207     /* Flush posted writes. */
0208     readl_relaxed(wdt->base + WDTLOCK);
0209     spin_unlock(&wdt->lock);
0210 
0211     clk_disable_unprepare(wdt->clk);
0212 
0213     return 0;
0214 }
0215 
0216 static const struct watchdog_info wdt_info = {
0217     .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
0218     .identity = MODULE_NAME,
0219 };
0220 
0221 static const struct watchdog_ops wdt_ops = {
0222     .owner      = THIS_MODULE,
0223     .start      = wdt_enable,
0224     .stop       = wdt_disable,
0225     .ping       = wdt_ping,
0226     .set_timeout    = wdt_setload,
0227     .get_timeleft   = wdt_timeleft,
0228     .restart    = wdt_restart,
0229 };
0230 
0231 static int
0232 sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
0233 {
0234     struct sp805_wdt *wdt;
0235     u64 rate = 0;
0236     int ret = 0;
0237 
0238     wdt = devm_kzalloc(&adev->dev, sizeof(*wdt), GFP_KERNEL);
0239     if (!wdt) {
0240         ret = -ENOMEM;
0241         goto err;
0242     }
0243 
0244     wdt->base = devm_ioremap_resource(&adev->dev, &adev->res);
0245     if (IS_ERR(wdt->base))
0246         return PTR_ERR(wdt->base);
0247 
0248     /*
0249      * When driver probe with ACPI device, clock devices
0250      * are not available, so watchdog rate get from
0251      * clock-frequency property given in _DSD object.
0252      */
0253     device_property_read_u64(&adev->dev, "clock-frequency", &rate);
0254 
0255     wdt->clk = devm_clk_get_optional(&adev->dev, NULL);
0256     if (IS_ERR(wdt->clk))
0257         return dev_err_probe(&adev->dev, PTR_ERR(wdt->clk), "Clock not found\n");
0258 
0259     wdt->rate = clk_get_rate(wdt->clk);
0260     if (!wdt->rate)
0261         wdt->rate = rate;
0262     if (!wdt->rate) {
0263         dev_err(&adev->dev, "no clock-frequency property\n");
0264         return -ENODEV;
0265     }
0266 
0267     wdt->adev = adev;
0268     wdt->wdd.info = &wdt_info;
0269     wdt->wdd.ops = &wdt_ops;
0270     wdt->wdd.parent = &adev->dev;
0271 
0272     spin_lock_init(&wdt->lock);
0273     watchdog_set_nowayout(&wdt->wdd, nowayout);
0274     watchdog_set_drvdata(&wdt->wdd, wdt);
0275     watchdog_set_restart_priority(&wdt->wdd, 128);
0276     watchdog_stop_on_unregister(&wdt->wdd);
0277 
0278     /*
0279      * If 'timeout-sec' devicetree property is specified, use that.
0280      * Otherwise, use DEFAULT_TIMEOUT
0281      */
0282     wdt->wdd.timeout = DEFAULT_TIMEOUT;
0283     watchdog_init_timeout(&wdt->wdd, 0, &adev->dev);
0284     wdt_setload(&wdt->wdd, wdt->wdd.timeout);
0285 
0286     /*
0287      * If HW is already running, enable/reset the wdt and set the running
0288      * bit to tell the wdt subsystem
0289      */
0290     if (wdt_is_running(&wdt->wdd)) {
0291         wdt_enable(&wdt->wdd);
0292         set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
0293     }
0294 
0295     watchdog_stop_on_reboot(&wdt->wdd);
0296     ret = watchdog_register_device(&wdt->wdd);
0297     if (ret)
0298         goto err;
0299     amba_set_drvdata(adev, wdt);
0300 
0301     dev_info(&adev->dev, "registration successful\n");
0302     return 0;
0303 
0304 err:
0305     dev_err(&adev->dev, "Probe Failed!!!\n");
0306     return ret;
0307 }
0308 
0309 static void sp805_wdt_remove(struct amba_device *adev)
0310 {
0311     struct sp805_wdt *wdt = amba_get_drvdata(adev);
0312 
0313     watchdog_unregister_device(&wdt->wdd);
0314     watchdog_set_drvdata(&wdt->wdd, NULL);
0315 }
0316 
0317 static int __maybe_unused sp805_wdt_suspend(struct device *dev)
0318 {
0319     struct sp805_wdt *wdt = dev_get_drvdata(dev);
0320 
0321     if (watchdog_active(&wdt->wdd))
0322         return wdt_disable(&wdt->wdd);
0323 
0324     return 0;
0325 }
0326 
0327 static int __maybe_unused sp805_wdt_resume(struct device *dev)
0328 {
0329     struct sp805_wdt *wdt = dev_get_drvdata(dev);
0330 
0331     if (watchdog_active(&wdt->wdd))
0332         return wdt_enable(&wdt->wdd);
0333 
0334     return 0;
0335 }
0336 
0337 static SIMPLE_DEV_PM_OPS(sp805_wdt_dev_pm_ops, sp805_wdt_suspend,
0338         sp805_wdt_resume);
0339 
0340 static const struct amba_id sp805_wdt_ids[] = {
0341     {
0342         .id = 0x00141805,
0343         .mask   = 0x00ffffff,
0344     },
0345     {
0346         .id     = 0x001bb824,
0347         .mask   = 0x00ffffff,
0348     },
0349     { 0, 0 },
0350 };
0351 
0352 MODULE_DEVICE_TABLE(amba, sp805_wdt_ids);
0353 
0354 static struct amba_driver sp805_wdt_driver = {
0355     .drv = {
0356         .name   = MODULE_NAME,
0357         .pm = &sp805_wdt_dev_pm_ops,
0358     },
0359     .id_table   = sp805_wdt_ids,
0360     .probe      = sp805_wdt_probe,
0361     .remove = sp805_wdt_remove,
0362 };
0363 
0364 module_amba_driver(sp805_wdt_driver);
0365 
0366 MODULE_AUTHOR("Viresh Kumar <vireshk@kernel.org>");
0367 MODULE_DESCRIPTION("ARM SP805 Watchdog Driver");
0368 MODULE_LICENSE("GPL");