Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // Copyright (c) 2018 Nuvoton Technology corporation.
0003 // Copyright (c) 2018 IBM Corp.
0004 
0005 #include <linux/bitops.h>
0006 #include <linux/delay.h>
0007 #include <linux/interrupt.h>
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/of_irq.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/slab.h>
0013 #include <linux/watchdog.h>
0014 
0015 #define NPCM_WTCR   0x1C
0016 
0017 #define NPCM_WTCLK  (BIT(10) | BIT(11)) /* Clock divider */
0018 #define NPCM_WTE    BIT(7)          /* Enable */
0019 #define NPCM_WTIE   BIT(6)          /* Enable irq */
0020 #define NPCM_WTIS   (BIT(4) | BIT(5))   /* Interval selection */
0021 #define NPCM_WTIF   BIT(3)          /* Interrupt flag*/
0022 #define NPCM_WTRF   BIT(2)          /* Reset flag */
0023 #define NPCM_WTRE   BIT(1)          /* Reset enable */
0024 #define NPCM_WTR    BIT(0)          /* Reset counter */
0025 
0026 /*
0027  * Watchdog timeouts
0028  *
0029  * 170     msec:    WTCLK=01 WTIS=00     VAL= 0x400
0030  * 670     msec:    WTCLK=01 WTIS=01     VAL= 0x410
0031  * 1360    msec:    WTCLK=10 WTIS=00     VAL= 0x800
0032  * 2700    msec:    WTCLK=01 WTIS=10     VAL= 0x420
0033  * 5360    msec:    WTCLK=10 WTIS=01     VAL= 0x810
0034  * 10700   msec:    WTCLK=01 WTIS=11     VAL= 0x430
0035  * 21600   msec:    WTCLK=10 WTIS=10     VAL= 0x820
0036  * 43000   msec:    WTCLK=11 WTIS=00     VAL= 0xC00
0037  * 85600   msec:    WTCLK=10 WTIS=11     VAL= 0x830
0038  * 172000  msec:    WTCLK=11 WTIS=01     VAL= 0xC10
0039  * 687000  msec:    WTCLK=11 WTIS=10     VAL= 0xC20
0040  * 2750000 msec:    WTCLK=11 WTIS=11     VAL= 0xC30
0041  */
0042 
0043 struct npcm_wdt {
0044     struct watchdog_device  wdd;
0045     void __iomem        *reg;
0046 };
0047 
0048 static inline struct npcm_wdt *to_npcm_wdt(struct watchdog_device *wdd)
0049 {
0050     return container_of(wdd, struct npcm_wdt, wdd);
0051 }
0052 
0053 static int npcm_wdt_ping(struct watchdog_device *wdd)
0054 {
0055     struct npcm_wdt *wdt = to_npcm_wdt(wdd);
0056     u32 val;
0057 
0058     val = readl(wdt->reg);
0059     writel(val | NPCM_WTR, wdt->reg);
0060 
0061     return 0;
0062 }
0063 
0064 static int npcm_wdt_start(struct watchdog_device *wdd)
0065 {
0066     struct npcm_wdt *wdt = to_npcm_wdt(wdd);
0067     u32 val;
0068 
0069     if (wdd->timeout < 2)
0070         val = 0x800;
0071     else if (wdd->timeout < 3)
0072         val = 0x420;
0073     else if (wdd->timeout < 6)
0074         val = 0x810;
0075     else if (wdd->timeout < 11)
0076         val = 0x430;
0077     else if (wdd->timeout < 22)
0078         val = 0x820;
0079     else if (wdd->timeout < 44)
0080         val = 0xC00;
0081     else if (wdd->timeout < 87)
0082         val = 0x830;
0083     else if (wdd->timeout < 173)
0084         val = 0xC10;
0085     else if (wdd->timeout < 688)
0086         val = 0xC20;
0087     else
0088         val = 0xC30;
0089 
0090     val |= NPCM_WTRE | NPCM_WTE | NPCM_WTR | NPCM_WTIE;
0091 
0092     writel(val, wdt->reg);
0093 
0094     return 0;
0095 }
0096 
0097 static int npcm_wdt_stop(struct watchdog_device *wdd)
0098 {
0099     struct npcm_wdt *wdt = to_npcm_wdt(wdd);
0100 
0101     writel(0, wdt->reg);
0102 
0103     return 0;
0104 }
0105 
0106 static int npcm_wdt_set_timeout(struct watchdog_device *wdd,
0107                 unsigned int timeout)
0108 {
0109     if (timeout < 2)
0110         wdd->timeout = 1;
0111     else if (timeout < 3)
0112         wdd->timeout = 2;
0113     else if (timeout < 6)
0114         wdd->timeout = 5;
0115     else if (timeout < 11)
0116         wdd->timeout = 10;
0117     else if (timeout < 22)
0118         wdd->timeout = 21;
0119     else if (timeout < 44)
0120         wdd->timeout = 43;
0121     else if (timeout < 87)
0122         wdd->timeout = 86;
0123     else if (timeout < 173)
0124         wdd->timeout = 172;
0125     else if (timeout < 688)
0126         wdd->timeout = 687;
0127     else
0128         wdd->timeout = 2750;
0129 
0130     if (watchdog_active(wdd))
0131         npcm_wdt_start(wdd);
0132 
0133     return 0;
0134 }
0135 
0136 static irqreturn_t npcm_wdt_interrupt(int irq, void *data)
0137 {
0138     struct npcm_wdt *wdt = data;
0139 
0140     watchdog_notify_pretimeout(&wdt->wdd);
0141 
0142     return IRQ_HANDLED;
0143 }
0144 
0145 static int npcm_wdt_restart(struct watchdog_device *wdd,
0146                 unsigned long action, void *data)
0147 {
0148     struct npcm_wdt *wdt = to_npcm_wdt(wdd);
0149 
0150     writel(NPCM_WTR | NPCM_WTRE | NPCM_WTE, wdt->reg);
0151     udelay(1000);
0152 
0153     return 0;
0154 }
0155 
0156 static bool npcm_is_running(struct watchdog_device *wdd)
0157 {
0158     struct npcm_wdt *wdt = to_npcm_wdt(wdd);
0159 
0160     return readl(wdt->reg) & NPCM_WTE;
0161 }
0162 
0163 static const struct watchdog_info npcm_wdt_info = {
0164     .identity   = KBUILD_MODNAME,
0165     .options    = WDIOF_SETTIMEOUT
0166             | WDIOF_KEEPALIVEPING
0167             | WDIOF_MAGICCLOSE,
0168 };
0169 
0170 static const struct watchdog_ops npcm_wdt_ops = {
0171     .owner = THIS_MODULE,
0172     .start = npcm_wdt_start,
0173     .stop = npcm_wdt_stop,
0174     .ping = npcm_wdt_ping,
0175     .set_timeout = npcm_wdt_set_timeout,
0176     .restart = npcm_wdt_restart,
0177 };
0178 
0179 static int npcm_wdt_probe(struct platform_device *pdev)
0180 {
0181     struct device *dev = &pdev->dev;
0182     struct npcm_wdt *wdt;
0183     int irq;
0184     int ret;
0185 
0186     wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
0187     if (!wdt)
0188         return -ENOMEM;
0189 
0190     wdt->reg = devm_platform_ioremap_resource(pdev, 0);
0191     if (IS_ERR(wdt->reg))
0192         return PTR_ERR(wdt->reg);
0193 
0194     irq = platform_get_irq(pdev, 0);
0195     if (irq < 0)
0196         return irq;
0197 
0198     wdt->wdd.info = &npcm_wdt_info;
0199     wdt->wdd.ops = &npcm_wdt_ops;
0200     wdt->wdd.min_timeout = 1;
0201     wdt->wdd.max_timeout = 2750;
0202     wdt->wdd.parent = dev;
0203 
0204     wdt->wdd.timeout = 86;
0205     watchdog_init_timeout(&wdt->wdd, 0, dev);
0206 
0207     /* Ensure timeout is able to be represented by the hardware */
0208     npcm_wdt_set_timeout(&wdt->wdd, wdt->wdd.timeout);
0209 
0210     if (npcm_is_running(&wdt->wdd)) {
0211         /* Restart with the default or device-tree specified timeout */
0212         npcm_wdt_start(&wdt->wdd);
0213         set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
0214     }
0215 
0216     ret = devm_request_irq(dev, irq, npcm_wdt_interrupt, 0, "watchdog",
0217                    wdt);
0218     if (ret)
0219         return ret;
0220 
0221     ret = devm_watchdog_register_device(dev, &wdt->wdd);
0222     if (ret)
0223         return ret;
0224 
0225     dev_info(dev, "NPCM watchdog driver enabled\n");
0226 
0227     return 0;
0228 }
0229 
0230 #ifdef CONFIG_OF
0231 static const struct of_device_id npcm_wdt_match[] = {
0232     {.compatible = "nuvoton,wpcm450-wdt"},
0233     {.compatible = "nuvoton,npcm750-wdt"},
0234     {},
0235 };
0236 MODULE_DEVICE_TABLE(of, npcm_wdt_match);
0237 #endif
0238 
0239 static struct platform_driver npcm_wdt_driver = {
0240     .probe      = npcm_wdt_probe,
0241     .driver     = {
0242         .name   = "npcm-wdt",
0243         .of_match_table = of_match_ptr(npcm_wdt_match),
0244     },
0245 };
0246 module_platform_driver(npcm_wdt_driver);
0247 
0248 MODULE_AUTHOR("Joel Stanley");
0249 MODULE_DESCRIPTION("Watchdog driver for NPCM");
0250 MODULE_LICENSE("GPL v2");