0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0012
0013 #include <linux/module.h>
0014 #include <linux/smp.h>
0015 #include <linux/watchdog.h>
0016
0017 #include <asm/reg_booke.h>
0018 #include <asm/time.h>
0019 #include <asm/div64.h>
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 #ifdef CONFIG_PPC_FSL_BOOK3E
0031 #define WDTP(x) ((((x)&0x3)<<30)|(((x)&0x3c)<<15))
0032 #define WDTP_MASK (WDTP(0x3f))
0033 #else
0034 #define WDTP(x) (TCR_WP(x))
0035 #define WDTP_MASK (TCR_WP_MASK)
0036 #endif
0037
0038 static bool booke_wdt_enabled;
0039 module_param(booke_wdt_enabled, bool, 0);
0040 static int booke_wdt_period = CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT;
0041 module_param(booke_wdt_period, int, 0);
0042 static bool nowayout = WATCHDOG_NOWAYOUT;
0043 module_param(nowayout, bool, 0);
0044 MODULE_PARM_DESC(nowayout,
0045 "Watchdog cannot be stopped once started (default="
0046 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
0047
0048 #ifdef CONFIG_PPC_FSL_BOOK3E
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060 static unsigned long long period_to_sec(unsigned int period)
0061 {
0062 unsigned long long tmp = 1ULL << (64 - period);
0063 unsigned long tmp2 = ppc_tb_freq;
0064
0065
0066
0067
0068 tmp2 = tmp2 / 5 * 2;
0069
0070 do_div(tmp, tmp2);
0071 return tmp;
0072 }
0073
0074
0075
0076
0077
0078
0079 static unsigned int sec_to_period(unsigned int secs)
0080 {
0081 unsigned int period;
0082 for (period = 63; period > 0; period--) {
0083 if (period_to_sec(period) >= secs)
0084 return period;
0085 }
0086 return 0;
0087 }
0088
0089 #define MAX_WDT_TIMEOUT period_to_sec(1)
0090
0091 #else
0092
0093 static unsigned long long period_to_sec(unsigned int period)
0094 {
0095 return period;
0096 }
0097
0098 static unsigned int sec_to_period(unsigned int secs)
0099 {
0100 return secs;
0101 }
0102
0103 #define MAX_WDT_TIMEOUT 3
0104
0105 #endif
0106
0107 static void __booke_wdt_set(void *data)
0108 {
0109 u32 val;
0110 struct watchdog_device *wdog = data;
0111
0112 val = mfspr(SPRN_TCR);
0113 val &= ~WDTP_MASK;
0114 val |= WDTP(sec_to_period(wdog->timeout));
0115
0116 mtspr(SPRN_TCR, val);
0117 }
0118
0119 static void booke_wdt_set(void *data)
0120 {
0121 on_each_cpu(__booke_wdt_set, data, 0);
0122 }
0123
0124 static void __booke_wdt_ping(void *data)
0125 {
0126 mtspr(SPRN_TSR, TSR_ENW|TSR_WIS);
0127 }
0128
0129 static int booke_wdt_ping(struct watchdog_device *wdog)
0130 {
0131 on_each_cpu(__booke_wdt_ping, NULL, 0);
0132
0133 return 0;
0134 }
0135
0136 static void __booke_wdt_enable(void *data)
0137 {
0138 u32 val;
0139 struct watchdog_device *wdog = data;
0140
0141
0142 __booke_wdt_ping(NULL);
0143 val = mfspr(SPRN_TCR);
0144 val &= ~WDTP_MASK;
0145 val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(sec_to_period(wdog->timeout)));
0146
0147 mtspr(SPRN_TCR, val);
0148 }
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158 static void __booke_wdt_disable(void *data)
0159 {
0160 u32 val;
0161
0162 val = mfspr(SPRN_TCR);
0163 val &= ~(TCR_WIE | WDTP_MASK);
0164 mtspr(SPRN_TCR, val);
0165
0166
0167 __booke_wdt_ping(NULL);
0168
0169 }
0170
0171 static int booke_wdt_start(struct watchdog_device *wdog)
0172 {
0173 on_each_cpu(__booke_wdt_enable, wdog, 0);
0174 pr_debug("watchdog enabled (timeout = %u sec)\n", wdog->timeout);
0175
0176 return 0;
0177 }
0178
0179 static int booke_wdt_stop(struct watchdog_device *wdog)
0180 {
0181 on_each_cpu(__booke_wdt_disable, NULL, 0);
0182 pr_debug("watchdog disabled\n");
0183
0184 return 0;
0185 }
0186
0187 static int booke_wdt_set_timeout(struct watchdog_device *wdt_dev,
0188 unsigned int timeout)
0189 {
0190 wdt_dev->timeout = timeout;
0191 booke_wdt_set(wdt_dev);
0192
0193 return 0;
0194 }
0195
0196 static struct watchdog_info booke_wdt_info __ro_after_init = {
0197 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
0198 .identity = "PowerPC Book-E Watchdog",
0199 };
0200
0201 static const struct watchdog_ops booke_wdt_ops = {
0202 .owner = THIS_MODULE,
0203 .start = booke_wdt_start,
0204 .stop = booke_wdt_stop,
0205 .ping = booke_wdt_ping,
0206 .set_timeout = booke_wdt_set_timeout,
0207 };
0208
0209 static struct watchdog_device booke_wdt_dev = {
0210 .info = &booke_wdt_info,
0211 .ops = &booke_wdt_ops,
0212 .min_timeout = 1,
0213 };
0214
0215 static void __exit booke_wdt_exit(void)
0216 {
0217 watchdog_unregister_device(&booke_wdt_dev);
0218 }
0219
0220 static int __init booke_wdt_init(void)
0221 {
0222 int ret = 0;
0223
0224 pr_info("powerpc book-e watchdog driver loaded\n");
0225 booke_wdt_info.firmware_version = cur_cpu_spec->pvr_value;
0226 booke_wdt_set_timeout(&booke_wdt_dev,
0227 period_to_sec(booke_wdt_period));
0228 watchdog_set_nowayout(&booke_wdt_dev, nowayout);
0229 booke_wdt_dev.max_timeout = MAX_WDT_TIMEOUT;
0230 if (booke_wdt_enabled)
0231 booke_wdt_start(&booke_wdt_dev);
0232
0233 ret = watchdog_register_device(&booke_wdt_dev);
0234
0235 return ret;
0236 }
0237
0238 module_init(booke_wdt_init);
0239 module_exit(booke_wdt_exit);
0240
0241 MODULE_ALIAS("booke_wdt");
0242 MODULE_DESCRIPTION("PowerPC Book-E watchdog driver");
0243 MODULE_LICENSE("GPL");