root/drivers/watchdog/ux500_wdt.c

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

DEFINITIONS

This source file includes following definitions.
  1. ux500_wdt_start
  2. ux500_wdt_stop
  3. ux500_wdt_keepalive
  4. ux500_wdt_set_timeout
  5. ux500_wdt_probe
  6. ux500_wdt_suspend
  7. ux500_wdt_resume

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) ST-Ericsson SA 2011-2013
   4  *
   5  * Author: Mathieu Poirier <mathieu.poirier@linaro.org> for ST-Ericsson
   6  * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
   7  */
   8 
   9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  10 
  11 #include <linux/module.h>
  12 #include <linux/kernel.h>
  13 #include <linux/moduleparam.h>
  14 #include <linux/err.h>
  15 #include <linux/uaccess.h>
  16 #include <linux/watchdog.h>
  17 #include <linux/platform_device.h>
  18 #include <linux/platform_data/ux500_wdt.h>
  19 
  20 #include <linux/mfd/dbx500-prcmu.h>
  21 
  22 #define WATCHDOG_TIMEOUT 600 /* 10 minutes */
  23 
  24 #define WATCHDOG_MIN    0
  25 #define WATCHDOG_MAX28  268435  /* 28 bit resolution in ms == 268435.455 s */
  26 #define WATCHDOG_MAX32  4294967 /* 32 bit resolution in ms == 4294967.295 s */
  27 
  28 static unsigned int timeout = WATCHDOG_TIMEOUT;
  29 module_param(timeout, uint, 0);
  30 MODULE_PARM_DESC(timeout,
  31         "Watchdog timeout in seconds. default="
  32                                 __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
  33 
  34 static bool nowayout = WATCHDOG_NOWAYOUT;
  35 module_param(nowayout, bool, 0);
  36 MODULE_PARM_DESC(nowayout,
  37         "Watchdog cannot be stopped once started (default="
  38                                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
  39 
  40 static int ux500_wdt_start(struct watchdog_device *wdd)
  41 {
  42         return prcmu_enable_a9wdog(PRCMU_WDOG_ALL);
  43 }
  44 
  45 static int ux500_wdt_stop(struct watchdog_device *wdd)
  46 {
  47         return prcmu_disable_a9wdog(PRCMU_WDOG_ALL);
  48 }
  49 
  50 static int ux500_wdt_keepalive(struct watchdog_device *wdd)
  51 {
  52         return prcmu_kick_a9wdog(PRCMU_WDOG_ALL);
  53 }
  54 
  55 static int ux500_wdt_set_timeout(struct watchdog_device *wdd,
  56                                  unsigned int timeout)
  57 {
  58         ux500_wdt_stop(wdd);
  59         prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
  60         ux500_wdt_start(wdd);
  61 
  62         return 0;
  63 }
  64 
  65 static const struct watchdog_info ux500_wdt_info = {
  66         .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
  67         .identity = "Ux500 WDT",
  68         .firmware_version = 1,
  69 };
  70 
  71 static const struct watchdog_ops ux500_wdt_ops = {
  72         .owner = THIS_MODULE,
  73         .start = ux500_wdt_start,
  74         .stop  = ux500_wdt_stop,
  75         .ping  = ux500_wdt_keepalive,
  76         .set_timeout = ux500_wdt_set_timeout,
  77 };
  78 
  79 static struct watchdog_device ux500_wdt = {
  80         .info = &ux500_wdt_info,
  81         .ops = &ux500_wdt_ops,
  82         .min_timeout = WATCHDOG_MIN,
  83         .max_timeout = WATCHDOG_MAX32,
  84 };
  85 
  86 static int ux500_wdt_probe(struct platform_device *pdev)
  87 {
  88         struct device *dev = &pdev->dev;
  89         int ret;
  90         struct ux500_wdt_data *pdata = dev_get_platdata(dev);
  91 
  92         if (pdata) {
  93                 if (pdata->timeout > 0)
  94                         timeout = pdata->timeout;
  95                 if (pdata->has_28_bits_resolution)
  96                         ux500_wdt.max_timeout = WATCHDOG_MAX28;
  97         }
  98 
  99         ux500_wdt.parent = dev;
 100         watchdog_set_nowayout(&ux500_wdt, nowayout);
 101 
 102         /* disable auto off on sleep */
 103         prcmu_config_a9wdog(PRCMU_WDOG_CPU1, false);
 104 
 105         /* set HW initial value */
 106         prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
 107 
 108         ret = devm_watchdog_register_device(dev, &ux500_wdt);
 109         if (ret)
 110                 return ret;
 111 
 112         dev_info(dev, "initialized\n");
 113 
 114         return 0;
 115 }
 116 
 117 #ifdef CONFIG_PM
 118 static int ux500_wdt_suspend(struct platform_device *pdev,
 119                              pm_message_t state)
 120 {
 121         if (watchdog_active(&ux500_wdt)) {
 122                 ux500_wdt_stop(&ux500_wdt);
 123                 prcmu_config_a9wdog(PRCMU_WDOG_CPU1, true);
 124 
 125                 prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
 126                 ux500_wdt_start(&ux500_wdt);
 127         }
 128         return 0;
 129 }
 130 
 131 static int ux500_wdt_resume(struct platform_device *pdev)
 132 {
 133         if (watchdog_active(&ux500_wdt)) {
 134                 ux500_wdt_stop(&ux500_wdt);
 135                 prcmu_config_a9wdog(PRCMU_WDOG_CPU1, false);
 136 
 137                 prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
 138                 ux500_wdt_start(&ux500_wdt);
 139         }
 140         return 0;
 141 }
 142 #else
 143 #define ux500_wdt_suspend NULL
 144 #define ux500_wdt_resume NULL
 145 #endif
 146 
 147 static struct platform_driver ux500_wdt_driver = {
 148         .probe          = ux500_wdt_probe,
 149         .suspend        = ux500_wdt_suspend,
 150         .resume         = ux500_wdt_resume,
 151         .driver         = {
 152                 .name   = "ux500_wdt",
 153         },
 154 };
 155 
 156 module_platform_driver(ux500_wdt_driver);
 157 
 158 MODULE_AUTHOR("Jonas Aaberg <jonas.aberg@stericsson.com>");
 159 MODULE_DESCRIPTION("Ux500 Watchdog Driver");
 160 MODULE_LICENSE("GPL");
 161 MODULE_ALIAS("platform:ux500_wdt");

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