root/drivers/watchdog/rt2880_wdt.c

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

DEFINITIONS

This source file includes following definitions.
  1. rt_wdt_w32
  2. rt_wdt_r32
  3. rt288x_wdt_ping
  4. rt288x_wdt_start
  5. rt288x_wdt_stop
  6. rt288x_wdt_set_timeout
  7. rt288x_wdt_bootcause
  8. rt288x_wdt_probe

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Ralink RT288x/RT3xxx/MT76xx built-in hardware watchdog timer
   4  *
   5  * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
   6  * Copyright (C) 2013 John Crispin <john@phrozen.org>
   7  *
   8  * This driver was based on: drivers/watchdog/softdog.c
   9  */
  10 
  11 #include <linux/clk.h>
  12 #include <linux/reset.h>
  13 #include <linux/module.h>
  14 #include <linux/kernel.h>
  15 #include <linux/watchdog.h>
  16 #include <linux/moduleparam.h>
  17 #include <linux/platform_device.h>
  18 #include <linux/mod_devicetable.h>
  19 
  20 #include <asm/mach-ralink/ralink_regs.h>
  21 
  22 #define SYSC_RSTSTAT                    0x38
  23 #define WDT_RST_CAUSE                   BIT(1)
  24 
  25 #define RALINK_WDT_TIMEOUT              30
  26 #define RALINK_WDT_PRESCALE             65536
  27 
  28 #define TIMER_REG_TMR1LOAD              0x00
  29 #define TIMER_REG_TMR1CTL               0x08
  30 
  31 #define TMRSTAT_TMR1RST                 BIT(5)
  32 
  33 #define TMR1CTL_ENABLE                  BIT(7)
  34 #define TMR1CTL_MODE_SHIFT              4
  35 #define TMR1CTL_MODE_MASK               0x3
  36 #define TMR1CTL_MODE_FREE_RUNNING       0x0
  37 #define TMR1CTL_MODE_PERIODIC           0x1
  38 #define TMR1CTL_MODE_TIMEOUT            0x2
  39 #define TMR1CTL_MODE_WDT                0x3
  40 #define TMR1CTL_PRESCALE_MASK           0xf
  41 #define TMR1CTL_PRESCALE_65536          0xf
  42 
  43 static struct clk *rt288x_wdt_clk;
  44 static unsigned long rt288x_wdt_freq;
  45 static void __iomem *rt288x_wdt_base;
  46 static struct reset_control *rt288x_wdt_reset;
  47 
  48 static bool nowayout = WATCHDOG_NOWAYOUT;
  49 module_param(nowayout, bool, 0);
  50 MODULE_PARM_DESC(nowayout,
  51                 "Watchdog cannot be stopped once started (default="
  52                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
  53 
  54 static inline void rt_wdt_w32(unsigned reg, u32 val)
  55 {
  56         iowrite32(val, rt288x_wdt_base + reg);
  57 }
  58 
  59 static inline u32 rt_wdt_r32(unsigned reg)
  60 {
  61         return ioread32(rt288x_wdt_base + reg);
  62 }
  63 
  64 static int rt288x_wdt_ping(struct watchdog_device *w)
  65 {
  66         rt_wdt_w32(TIMER_REG_TMR1LOAD, w->timeout * rt288x_wdt_freq);
  67 
  68         return 0;
  69 }
  70 
  71 static int rt288x_wdt_start(struct watchdog_device *w)
  72 {
  73         u32 t;
  74 
  75         t = rt_wdt_r32(TIMER_REG_TMR1CTL);
  76         t &= ~(TMR1CTL_MODE_MASK << TMR1CTL_MODE_SHIFT |
  77                 TMR1CTL_PRESCALE_MASK);
  78         t |= (TMR1CTL_MODE_WDT << TMR1CTL_MODE_SHIFT |
  79                 TMR1CTL_PRESCALE_65536);
  80         rt_wdt_w32(TIMER_REG_TMR1CTL, t);
  81 
  82         rt288x_wdt_ping(w);
  83 
  84         t = rt_wdt_r32(TIMER_REG_TMR1CTL);
  85         t |= TMR1CTL_ENABLE;
  86         rt_wdt_w32(TIMER_REG_TMR1CTL, t);
  87 
  88         return 0;
  89 }
  90 
  91 static int rt288x_wdt_stop(struct watchdog_device *w)
  92 {
  93         u32 t;
  94 
  95         rt288x_wdt_ping(w);
  96 
  97         t = rt_wdt_r32(TIMER_REG_TMR1CTL);
  98         t &= ~TMR1CTL_ENABLE;
  99         rt_wdt_w32(TIMER_REG_TMR1CTL, t);
 100 
 101         return 0;
 102 }
 103 
 104 static int rt288x_wdt_set_timeout(struct watchdog_device *w, unsigned int t)
 105 {
 106         w->timeout = t;
 107         rt288x_wdt_ping(w);
 108 
 109         return 0;
 110 }
 111 
 112 static int rt288x_wdt_bootcause(void)
 113 {
 114         if (rt_sysc_r32(SYSC_RSTSTAT) & WDT_RST_CAUSE)
 115                 return WDIOF_CARDRESET;
 116 
 117         return 0;
 118 }
 119 
 120 static const struct watchdog_info rt288x_wdt_info = {
 121         .identity = "Ralink Watchdog",
 122         .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
 123 };
 124 
 125 static const struct watchdog_ops rt288x_wdt_ops = {
 126         .owner = THIS_MODULE,
 127         .start = rt288x_wdt_start,
 128         .stop = rt288x_wdt_stop,
 129         .ping = rt288x_wdt_ping,
 130         .set_timeout = rt288x_wdt_set_timeout,
 131 };
 132 
 133 static struct watchdog_device rt288x_wdt_dev = {
 134         .info = &rt288x_wdt_info,
 135         .ops = &rt288x_wdt_ops,
 136         .min_timeout = 1,
 137 };
 138 
 139 static int rt288x_wdt_probe(struct platform_device *pdev)
 140 {
 141         struct device *dev = &pdev->dev;
 142         int ret;
 143 
 144         rt288x_wdt_base = devm_platform_ioremap_resource(pdev, 0);
 145         if (IS_ERR(rt288x_wdt_base))
 146                 return PTR_ERR(rt288x_wdt_base);
 147 
 148         rt288x_wdt_clk = devm_clk_get(dev, NULL);
 149         if (IS_ERR(rt288x_wdt_clk))
 150                 return PTR_ERR(rt288x_wdt_clk);
 151 
 152         rt288x_wdt_reset = devm_reset_control_get_exclusive(dev, NULL);
 153         if (!IS_ERR(rt288x_wdt_reset))
 154                 reset_control_deassert(rt288x_wdt_reset);
 155 
 156         rt288x_wdt_freq = clk_get_rate(rt288x_wdt_clk) / RALINK_WDT_PRESCALE;
 157 
 158         rt288x_wdt_dev.bootstatus = rt288x_wdt_bootcause();
 159         rt288x_wdt_dev.max_timeout = (0xfffful / rt288x_wdt_freq);
 160         rt288x_wdt_dev.parent = dev;
 161 
 162         watchdog_init_timeout(&rt288x_wdt_dev, rt288x_wdt_dev.max_timeout,
 163                               dev);
 164         watchdog_set_nowayout(&rt288x_wdt_dev, nowayout);
 165 
 166         watchdog_stop_on_reboot(&rt288x_wdt_dev);
 167         ret = devm_watchdog_register_device(dev, &rt288x_wdt_dev);
 168         if (!ret)
 169                 dev_info(dev, "Initialized\n");
 170 
 171         return 0;
 172 }
 173 
 174 static const struct of_device_id rt288x_wdt_match[] = {
 175         { .compatible = "ralink,rt2880-wdt" },
 176         {},
 177 };
 178 MODULE_DEVICE_TABLE(of, rt288x_wdt_match);
 179 
 180 static struct platform_driver rt288x_wdt_driver = {
 181         .probe          = rt288x_wdt_probe,
 182         .driver         = {
 183                 .name           = KBUILD_MODNAME,
 184                 .of_match_table = rt288x_wdt_match,
 185         },
 186 };
 187 
 188 module_platform_driver(rt288x_wdt_driver);
 189 
 190 MODULE_DESCRIPTION("MediaTek/Ralink RT288x/RT3xxx hardware watchdog driver");
 191 MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org");
 192 MODULE_LICENSE("GPL v2");

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