root/drivers/watchdog/booke_wdt.c

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

DEFINITIONS

This source file includes following definitions.
  1. period_to_sec
  2. sec_to_period
  3. period_to_sec
  4. sec_to_period
  5. __booke_wdt_set
  6. booke_wdt_set
  7. __booke_wdt_ping
  8. booke_wdt_ping
  9. __booke_wdt_enable
  10. __booke_wdt_disable
  11. booke_wdt_start
  12. booke_wdt_stop
  13. booke_wdt_set_timeout
  14. booke_wdt_exit
  15. booke_wdt_init

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Watchdog timer for PowerPC Book-E systems
   4  *
   5  * Author: Matthew McClintock
   6  * Maintainer: Kumar Gala <galak@kernel.crashing.org>
   7  *
   8  * Copyright 2005, 2008, 2010-2011 Freescale Semiconductor Inc.
   9  */
  10 
  11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  12 
  13 #include <linux/module.h>
  14 #include <linux/smp.h>
  15 #include <linux/watchdog.h>
  16 
  17 #include <asm/reg_booke.h>
  18 #include <asm/time.h>
  19 #include <asm/div64.h>
  20 
  21 /* If the kernel parameter wdt=1, the watchdog will be enabled at boot.
  22  * Also, the wdt_period sets the watchdog timer period timeout.
  23  * For E500 cpus the wdt_period sets which bit changing from 0->1 will
  24  * trigger a watchdog timeout. This watchdog timeout will occur 3 times, the
  25  * first time nothing will happen, the second time a watchdog exception will
  26  * occur, and the final time the board will reset.
  27  */
  28 
  29 
  30 #ifdef  CONFIG_PPC_FSL_BOOK3E
  31 #define WDTP(x)         ((((x)&0x3)<<30)|(((x)&0x3c)<<15))
  32 #define WDTP_MASK       (WDTP(0x3f))
  33 #else
  34 #define WDTP(x)         (TCR_WP(x))
  35 #define WDTP_MASK       (TCR_WP_MASK)
  36 #endif
  37 
  38 static bool booke_wdt_enabled;
  39 module_param(booke_wdt_enabled, bool, 0);
  40 static int  booke_wdt_period = CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT;
  41 module_param(booke_wdt_period, int, 0);
  42 
  43 #ifdef CONFIG_PPC_FSL_BOOK3E
  44 
  45 /* For the specified period, determine the number of seconds
  46  * corresponding to the reset time.  There will be a watchdog
  47  * exception at approximately 3/5 of this time.
  48  *
  49  * The formula to calculate this is given by:
  50  * 2.5 * (2^(63-period+1)) / timebase_freq
  51  *
  52  * In order to simplify things, we assume that period is
  53  * at least 1.  This will still result in a very long timeout.
  54  */
  55 static unsigned long long period_to_sec(unsigned int period)
  56 {
  57         unsigned long long tmp = 1ULL << (64 - period);
  58         unsigned long tmp2 = ppc_tb_freq;
  59 
  60         /* tmp may be a very large number and we don't want to overflow,
  61          * so divide the timebase freq instead of multiplying tmp
  62          */
  63         tmp2 = tmp2 / 5 * 2;
  64 
  65         do_div(tmp, tmp2);
  66         return tmp;
  67 }
  68 
  69 /*
  70  * This procedure will find the highest period which will give a timeout
  71  * greater than the one required. e.g. for a bus speed of 66666666 and
  72  * and a parameter of 2 secs, then this procedure will return a value of 38.
  73  */
  74 static unsigned int sec_to_period(unsigned int secs)
  75 {
  76         unsigned int period;
  77         for (period = 63; period > 0; period--) {
  78                 if (period_to_sec(period) >= secs)
  79                         return period;
  80         }
  81         return 0;
  82 }
  83 
  84 #define MAX_WDT_TIMEOUT         period_to_sec(1)
  85 
  86 #else /* CONFIG_PPC_FSL_BOOK3E */
  87 
  88 static unsigned long long period_to_sec(unsigned int period)
  89 {
  90         return period;
  91 }
  92 
  93 static unsigned int sec_to_period(unsigned int secs)
  94 {
  95         return secs;
  96 }
  97 
  98 #define MAX_WDT_TIMEOUT         3       /* from Kconfig */
  99 
 100 #endif /* !CONFIG_PPC_FSL_BOOK3E */
 101 
 102 static void __booke_wdt_set(void *data)
 103 {
 104         u32 val;
 105         struct watchdog_device *wdog = data;
 106 
 107         val = mfspr(SPRN_TCR);
 108         val &= ~WDTP_MASK;
 109         val |= WDTP(sec_to_period(wdog->timeout));
 110 
 111         mtspr(SPRN_TCR, val);
 112 }
 113 
 114 static void booke_wdt_set(void *data)
 115 {
 116         on_each_cpu(__booke_wdt_set, data, 0);
 117 }
 118 
 119 static void __booke_wdt_ping(void *data)
 120 {
 121         mtspr(SPRN_TSR, TSR_ENW|TSR_WIS);
 122 }
 123 
 124 static int booke_wdt_ping(struct watchdog_device *wdog)
 125 {
 126         on_each_cpu(__booke_wdt_ping, NULL, 0);
 127 
 128         return 0;
 129 }
 130 
 131 static void __booke_wdt_enable(void *data)
 132 {
 133         u32 val;
 134         struct watchdog_device *wdog = data;
 135 
 136         /* clear status before enabling watchdog */
 137         __booke_wdt_ping(NULL);
 138         val = mfspr(SPRN_TCR);
 139         val &= ~WDTP_MASK;
 140         val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(sec_to_period(wdog->timeout)));
 141 
 142         mtspr(SPRN_TCR, val);
 143 }
 144 
 145 /**
 146  * booke_wdt_disable - disable the watchdog on the given CPU
 147  *
 148  * This function is called on each CPU.  It disables the watchdog on that CPU.
 149  *
 150  * TCR[WRC] cannot be changed once it has been set to non-zero, but we can
 151  * effectively disable the watchdog by setting its period to the maximum value.
 152  */
 153 static void __booke_wdt_disable(void *data)
 154 {
 155         u32 val;
 156 
 157         val = mfspr(SPRN_TCR);
 158         val &= ~(TCR_WIE | WDTP_MASK);
 159         mtspr(SPRN_TCR, val);
 160 
 161         /* clear status to make sure nothing is pending */
 162         __booke_wdt_ping(NULL);
 163 
 164 }
 165 
 166 static int booke_wdt_start(struct watchdog_device *wdog)
 167 {
 168         on_each_cpu(__booke_wdt_enable, wdog, 0);
 169         pr_debug("watchdog enabled (timeout = %u sec)\n", wdog->timeout);
 170 
 171         return 0;
 172 }
 173 
 174 static int booke_wdt_stop(struct watchdog_device *wdog)
 175 {
 176         on_each_cpu(__booke_wdt_disable, NULL, 0);
 177         pr_debug("watchdog disabled\n");
 178 
 179         return 0;
 180 }
 181 
 182 static int booke_wdt_set_timeout(struct watchdog_device *wdt_dev,
 183                                  unsigned int timeout)
 184 {
 185         wdt_dev->timeout = timeout;
 186         booke_wdt_set(wdt_dev);
 187 
 188         return 0;
 189 }
 190 
 191 static struct watchdog_info booke_wdt_info __ro_after_init = {
 192         .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
 193         .identity = "PowerPC Book-E Watchdog",
 194 };
 195 
 196 static const struct watchdog_ops booke_wdt_ops = {
 197         .owner = THIS_MODULE,
 198         .start = booke_wdt_start,
 199         .stop = booke_wdt_stop,
 200         .ping = booke_wdt_ping,
 201         .set_timeout = booke_wdt_set_timeout,
 202 };
 203 
 204 static struct watchdog_device booke_wdt_dev = {
 205         .info = &booke_wdt_info,
 206         .ops = &booke_wdt_ops,
 207         .min_timeout = 1,
 208 };
 209 
 210 static void __exit booke_wdt_exit(void)
 211 {
 212         watchdog_unregister_device(&booke_wdt_dev);
 213 }
 214 
 215 static int __init booke_wdt_init(void)
 216 {
 217         int ret = 0;
 218         bool nowayout = WATCHDOG_NOWAYOUT;
 219 
 220         pr_info("powerpc book-e watchdog driver loaded\n");
 221         booke_wdt_info.firmware_version = cur_cpu_spec->pvr_value;
 222         booke_wdt_set_timeout(&booke_wdt_dev,
 223                               period_to_sec(booke_wdt_period));
 224         watchdog_set_nowayout(&booke_wdt_dev, nowayout);
 225         booke_wdt_dev.max_timeout = MAX_WDT_TIMEOUT;
 226         if (booke_wdt_enabled)
 227                 booke_wdt_start(&booke_wdt_dev);
 228 
 229         ret = watchdog_register_device(&booke_wdt_dev);
 230 
 231         return ret;
 232 }
 233 
 234 module_init(booke_wdt_init);
 235 module_exit(booke_wdt_exit);
 236 
 237 MODULE_ALIAS("booke_wdt");
 238 MODULE_DESCRIPTION("PowerPC Book-E watchdog driver");
 239 MODULE_LICENSE("GPL");

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