Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
0004  */
0005 
0006 #include <linux/kernel.h>
0007 #include <linux/module.h>
0008 #include <linux/interrupt.h>
0009 #include <linux/io.h>
0010 #include <linux/of.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/watchdog.h>
0013 
0014 /* minimum and maximum watchdog trigger timeout, in seconds */
0015 #define MIN_WDT_TIMEOUT         1
0016 #define MAX_WDT_TIMEOUT         255
0017 
0018 /*
0019  * Base of the WDT registers, from the timer base address.  There are
0020  * actually 5 watchdogs that can be configured (by pairing with an available
0021  * timer), at bases 0x100 + (WDT ID) * 0x20, where WDT ID is 0 through 4.
0022  * This driver only configures the first watchdog (WDT ID 0).
0023  */
0024 #define WDT_BASE            0x100
0025 #define WDT_ID              0
0026 
0027 /*
0028  * Register base of the timer that's selected for pairing with the watchdog.
0029  * This driver arbitrarily uses timer 5, which is currently unused by
0030  * other drivers (in particular, the Tegra clocksource driver).  If this
0031  * needs to change, take care that the new timer is not used by the
0032  * clocksource driver.
0033  */
0034 #define WDT_TIMER_BASE          0x60
0035 #define WDT_TIMER_ID            5
0036 
0037 /* WDT registers */
0038 #define WDT_CFG             0x0
0039 #define WDT_CFG_PERIOD_SHIFT        4
0040 #define WDT_CFG_PERIOD_MASK     0xff
0041 #define WDT_CFG_INT_EN          (1 << 12)
0042 #define WDT_CFG_PMC2CAR_RST_EN      (1 << 15)
0043 #define WDT_STS             0x4
0044 #define WDT_STS_COUNT_SHIFT     4
0045 #define WDT_STS_COUNT_MASK      0xff
0046 #define WDT_STS_EXP_SHIFT       12
0047 #define WDT_STS_EXP_MASK        0x3
0048 #define WDT_CMD             0x8
0049 #define WDT_CMD_START_COUNTER       (1 << 0)
0050 #define WDT_CMD_DISABLE_COUNTER     (1 << 1)
0051 #define WDT_UNLOCK          (0xc)
0052 #define WDT_UNLOCK_PATTERN      (0xc45a << 0)
0053 
0054 /* Timer registers */
0055 #define TIMER_PTV           0x0
0056 #define TIMER_EN            (1 << 31)
0057 #define TIMER_PERIODIC          (1 << 30)
0058 
0059 struct tegra_wdt {
0060     struct watchdog_device  wdd;
0061     void __iomem        *wdt_regs;
0062     void __iomem        *tmr_regs;
0063 };
0064 
0065 #define WDT_HEARTBEAT 120
0066 static int heartbeat = WDT_HEARTBEAT;
0067 module_param(heartbeat, int, 0);
0068 MODULE_PARM_DESC(heartbeat,
0069     "Watchdog heartbeats in seconds. (default = "
0070     __MODULE_STRING(WDT_HEARTBEAT) ")");
0071 
0072 static bool nowayout = WATCHDOG_NOWAYOUT;
0073 module_param(nowayout, bool, 0);
0074 MODULE_PARM_DESC(nowayout,
0075     "Watchdog cannot be stopped once started (default="
0076     __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
0077 
0078 static int tegra_wdt_start(struct watchdog_device *wdd)
0079 {
0080     struct tegra_wdt *wdt = watchdog_get_drvdata(wdd);
0081     u32 val;
0082 
0083     /*
0084      * This thing has a fixed 1MHz clock.  Normally, we would set the
0085      * period to 1 second by writing 1000000ul, but the watchdog system
0086      * reset actually occurs on the 4th expiration of this counter,
0087      * so we set the period to 1/4 of this amount.
0088      */
0089     val = 1000000ul / 4;
0090     val |= (TIMER_EN | TIMER_PERIODIC);
0091     writel(val, wdt->tmr_regs + TIMER_PTV);
0092 
0093     /*
0094      * Set number of periods and start counter.
0095      *
0096      * Interrupt handler is not required for user space
0097      * WDT accesses, since the caller is responsible to ping the
0098      * WDT to reset the counter before expiration, through ioctls.
0099      */
0100     val = WDT_TIMER_ID |
0101           (wdd->timeout << WDT_CFG_PERIOD_SHIFT) |
0102           WDT_CFG_PMC2CAR_RST_EN;
0103     writel(val, wdt->wdt_regs + WDT_CFG);
0104 
0105     writel(WDT_CMD_START_COUNTER, wdt->wdt_regs + WDT_CMD);
0106 
0107     return 0;
0108 }
0109 
0110 static int tegra_wdt_stop(struct watchdog_device *wdd)
0111 {
0112     struct tegra_wdt *wdt = watchdog_get_drvdata(wdd);
0113 
0114     writel(WDT_UNLOCK_PATTERN, wdt->wdt_regs + WDT_UNLOCK);
0115     writel(WDT_CMD_DISABLE_COUNTER, wdt->wdt_regs + WDT_CMD);
0116     writel(0, wdt->tmr_regs + TIMER_PTV);
0117 
0118     return 0;
0119 }
0120 
0121 static int tegra_wdt_ping(struct watchdog_device *wdd)
0122 {
0123     struct tegra_wdt *wdt = watchdog_get_drvdata(wdd);
0124 
0125     writel(WDT_CMD_START_COUNTER, wdt->wdt_regs + WDT_CMD);
0126 
0127     return 0;
0128 }
0129 
0130 static int tegra_wdt_set_timeout(struct watchdog_device *wdd,
0131                  unsigned int timeout)
0132 {
0133     wdd->timeout = timeout;
0134 
0135     if (watchdog_active(wdd)) {
0136         tegra_wdt_stop(wdd);
0137         return tegra_wdt_start(wdd);
0138     }
0139 
0140     return 0;
0141 }
0142 
0143 static unsigned int tegra_wdt_get_timeleft(struct watchdog_device *wdd)
0144 {
0145     struct tegra_wdt *wdt = watchdog_get_drvdata(wdd);
0146     u32 val;
0147     int count;
0148     int exp;
0149 
0150     val = readl(wdt->wdt_regs + WDT_STS);
0151 
0152     /* Current countdown (from timeout) */
0153     count = (val >> WDT_STS_COUNT_SHIFT) & WDT_STS_COUNT_MASK;
0154 
0155     /* Number of expirations (we are waiting for the 4th expiration) */
0156     exp = (val >> WDT_STS_EXP_SHIFT) & WDT_STS_EXP_MASK;
0157 
0158     /*
0159      * The entire thing is divided by 4 because we are ticking down 4 times
0160      * faster due to needing to wait for the 4th expiration.
0161      */
0162     return (((3 - exp) * wdd->timeout) + count) / 4;
0163 }
0164 
0165 static const struct watchdog_info tegra_wdt_info = {
0166     .options    = WDIOF_SETTIMEOUT |
0167               WDIOF_MAGICCLOSE |
0168               WDIOF_KEEPALIVEPING,
0169     .firmware_version = 0,
0170     .identity   = "Tegra Watchdog",
0171 };
0172 
0173 static const struct watchdog_ops tegra_wdt_ops = {
0174     .owner = THIS_MODULE,
0175     .start = tegra_wdt_start,
0176     .stop = tegra_wdt_stop,
0177     .ping = tegra_wdt_ping,
0178     .set_timeout = tegra_wdt_set_timeout,
0179     .get_timeleft = tegra_wdt_get_timeleft,
0180 };
0181 
0182 static int tegra_wdt_probe(struct platform_device *pdev)
0183 {
0184     struct device *dev = &pdev->dev;
0185     struct watchdog_device *wdd;
0186     struct tegra_wdt *wdt;
0187     void __iomem *regs;
0188     int ret;
0189 
0190     /* This is the timer base. */
0191     regs = devm_platform_ioremap_resource(pdev, 0);
0192     if (IS_ERR(regs))
0193         return PTR_ERR(regs);
0194 
0195     /*
0196      * Allocate our watchdog driver data, which has the
0197      * struct watchdog_device nested within it.
0198      */
0199     wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
0200     if (!wdt)
0201         return -ENOMEM;
0202 
0203     /* Initialize struct tegra_wdt. */
0204     wdt->wdt_regs = regs + WDT_BASE;
0205     wdt->tmr_regs = regs + WDT_TIMER_BASE;
0206 
0207     /* Initialize struct watchdog_device. */
0208     wdd = &wdt->wdd;
0209     wdd->timeout = heartbeat;
0210     wdd->info = &tegra_wdt_info;
0211     wdd->ops = &tegra_wdt_ops;
0212     wdd->min_timeout = MIN_WDT_TIMEOUT;
0213     wdd->max_timeout = MAX_WDT_TIMEOUT;
0214     wdd->parent = dev;
0215 
0216     watchdog_set_drvdata(wdd, wdt);
0217 
0218     watchdog_set_nowayout(wdd, nowayout);
0219 
0220     watchdog_stop_on_unregister(wdd);
0221     ret = devm_watchdog_register_device(dev, wdd);
0222     if (ret)
0223         return ret;
0224 
0225     platform_set_drvdata(pdev, wdt);
0226 
0227     dev_info(dev, "initialized (heartbeat = %d sec, nowayout = %d)\n",
0228          heartbeat, nowayout);
0229 
0230     return 0;
0231 }
0232 
0233 static int tegra_wdt_suspend(struct device *dev)
0234 {
0235     struct tegra_wdt *wdt = dev_get_drvdata(dev);
0236 
0237     if (watchdog_active(&wdt->wdd))
0238         tegra_wdt_stop(&wdt->wdd);
0239 
0240     return 0;
0241 }
0242 
0243 static int tegra_wdt_resume(struct device *dev)
0244 {
0245     struct tegra_wdt *wdt = dev_get_drvdata(dev);
0246 
0247     if (watchdog_active(&wdt->wdd))
0248         tegra_wdt_start(&wdt->wdd);
0249 
0250     return 0;
0251 }
0252 
0253 static const struct of_device_id tegra_wdt_of_match[] = {
0254     { .compatible = "nvidia,tegra30-timer", },
0255     { },
0256 };
0257 MODULE_DEVICE_TABLE(of, tegra_wdt_of_match);
0258 
0259 static DEFINE_SIMPLE_DEV_PM_OPS(tegra_wdt_pm_ops,
0260                 tegra_wdt_suspend, tegra_wdt_resume);
0261 
0262 static struct platform_driver tegra_wdt_driver = {
0263     .probe      = tegra_wdt_probe,
0264     .driver     = {
0265         .name   = "tegra-wdt",
0266         .pm = pm_sleep_ptr(&tegra_wdt_pm_ops),
0267         .of_match_table = tegra_wdt_of_match,
0268     },
0269 };
0270 module_platform_driver(tegra_wdt_driver);
0271 
0272 MODULE_AUTHOR("NVIDIA Corporation");
0273 MODULE_DESCRIPTION("Tegra Watchdog Driver");
0274 MODULE_LICENSE("GPL v2");