Merge tag 'h8300-for-linus-20190617' of git://git.sourceforge.jp/gitroot/uclinux...
[linux-2.6-block.git] / drivers / watchdog / i6300esb.c
CommitLineData
2874c5fd 1// SPDX-License-Identifier: GPL-2.0-or-later
cc90ef0f 2/*
abda5c8b 3 * i6300esb: Watchdog timer driver for Intel 6300ESB chipset
cc90ef0f
DH
4 *
5 * (c) Copyright 2004 Google Inc.
96de0e25 6 * (c) Copyright 2005 David Härdeman <david@2gen.com>
cc90ef0f 7 *
7944d3a5 8 * based on i810-tco.c which is in turn based on softdog.c
cc90ef0f 9 *
7944d3a5
WVS
10 * The timer is implemented in the following I/O controller hubs:
11 * (See the intel documentation on http://developer.intel.com.)
0426fd0d 12 * 6300ESB chip : document number 300641-004
cc90ef0f
DH
13 *
14 * 2004YYZZ Ross Biro
15 * Initial version 0.01
16 * 2004YYZZ Ross Biro
7944d3a5 17 * Version 0.02
96de0e25 18 * 20050210 David Härdeman <david@2gen.com>
7944d3a5 19 * Ported driver to kernel 2.6
7af4ac87
RR
20 * 20171016 Radu Rendec <rrendec@arista.com>
21 * Change driver to use the watchdog subsystem
cf73120b 22 * Add support for multiple 6300ESB devices
cc90ef0f
DH
23 */
24
25/*
26 * Includes, defines, variables, module parameters, ...
27 */
28
29#include <linux/module.h>
30#include <linux/types.h>
31#include <linux/kernel.h>
32#include <linux/fs.h>
33#include <linux/mm.h>
34#include <linux/miscdevice.h>
35#include <linux/watchdog.h>
cc90ef0f
DH
36#include <linux/pci.h>
37#include <linux/ioport.h>
0829291e
AC
38#include <linux/uaccess.h>
39#include <linux/io.h>
cc90ef0f 40
cc90ef0f 41/* Module and version information */
cc90ef0f 42#define ESB_MODULE_NAME "i6300ESB timer"
cc90ef0f 43
abda5c8b
DH
44/* PCI configuration registers */
45#define ESB_CONFIG_REG 0x60 /* Config register */
46#define ESB_LOCK_REG 0x68 /* WDT lock register */
47
48/* Memory mapped registers */
cf73120b
RR
49#define ESB_TIMER1_REG(w) ((w)->base + 0x00)/* Timer1 value after each reset */
50#define ESB_TIMER2_REG(w) ((w)->base + 0x04)/* Timer2 value after each reset */
51#define ESB_GINTSR_REG(w) ((w)->base + 0x08)/* General Interrupt Status Reg */
52#define ESB_RELOAD_REG(w) ((w)->base + 0x0c)/* Reload register */
abda5c8b
DH
53
54/* Lock register bits */
0829291e
AC
55#define ESB_WDT_FUNC (0x01 << 2) /* Watchdog functionality */
56#define ESB_WDT_ENABLE (0x01 << 1) /* Enable WDT */
57#define ESB_WDT_LOCK (0x01 << 0) /* Lock (nowayout) */
abda5c8b
DH
58
59/* Config register bits */
0829291e
AC
60#define ESB_WDT_REBOOT (0x01 << 5) /* Enable reboot on timeout */
61#define ESB_WDT_FREQ (0x01 << 2) /* Decrement frequency */
39f3be72 62#define ESB_WDT_INTTYPE (0x03 << 0) /* Interrupt type on timer1 timeout */
abda5c8b
DH
63
64/* Reload register bits */
31838d9d 65#define ESB_WDT_TIMEOUT (0x01 << 9) /* Watchdog timed out */
0829291e 66#define ESB_WDT_RELOAD (0x01 << 8) /* prevent timeout */
abda5c8b
DH
67
68/* Magic constants */
69#define ESB_UNLOCK1 0x80 /* Step 1 to unlock reset registers */
70#define ESB_UNLOCK2 0x86 /* Step 2 to unlock reset registers */
71
cc90ef0f 72/* module parameters */
0829291e 73/* 30 sec default heartbeat (1 < heartbeat < 2*1023) */
568d6015
RR
74#define ESB_HEARTBEAT_MIN 1
75#define ESB_HEARTBEAT_MAX 2046
76#define ESB_HEARTBEAT_DEFAULT 30
77#define ESB_HEARTBEAT_RANGE __MODULE_STRING(ESB_HEARTBEAT_MIN) \
78 "<heartbeat<" __MODULE_STRING(ESB_HEARTBEAT_MAX)
7af4ac87 79static int heartbeat; /* in seconds */
cc90ef0f 80module_param(heartbeat, int, 0);
0829291e 81MODULE_PARM_DESC(heartbeat,
568d6015
RR
82 "Watchdog heartbeat in seconds. (" ESB_HEARTBEAT_RANGE
83 ", default=" __MODULE_STRING(ESB_HEARTBEAT_DEFAULT) ")");
cc90ef0f 84
86a1e189
WVS
85static bool nowayout = WATCHDOG_NOWAYOUT;
86module_param(nowayout, bool, 0);
0829291e
AC
87MODULE_PARM_DESC(nowayout,
88 "Watchdog cannot be stopped once started (default="
89 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
cc90ef0f 90
cf73120b
RR
91/* internal variables */
92struct esb_dev {
93 struct watchdog_device wdd;
94 void __iomem *base;
95 struct pci_dev *pdev;
96};
97
98#define to_esb_dev(wptr) container_of(wptr, struct esb_dev, wdd)
99
cc90ef0f
DH
100/*
101 * Some i6300ESB specific functions
102 */
103
104/*
105 * Prepare for reloading the timer by unlocking the proper registers.
106 * This is performed by first writing 0x80 followed by 0x86 to the
107 * reload register. After this the appropriate registers can be written
108 * to once before they need to be unlocked again.
109 */
cf73120b 110static inline void esb_unlock_registers(struct esb_dev *edev)
7944d3a5 111{
cf73120b
RR
112 writew(ESB_UNLOCK1, ESB_RELOAD_REG(edev));
113 writew(ESB_UNLOCK2, ESB_RELOAD_REG(edev));
cc90ef0f
DH
114}
115
7af4ac87 116static int esb_timer_start(struct watchdog_device *wdd)
cc90ef0f 117{
cf73120b 118 struct esb_dev *edev = to_esb_dev(wdd);
7af4ac87 119 int _wdd_nowayout = test_bit(WDOG_NO_WAY_OUT, &wdd->status);
cc90ef0f
DH
120 u8 val;
121
cf73120b
RR
122 esb_unlock_registers(edev);
123 writew(ESB_WDT_RELOAD, ESB_RELOAD_REG(edev));
cc90ef0f 124 /* Enable or Enable + Lock? */
7af4ac87 125 val = ESB_WDT_ENABLE | (_wdd_nowayout ? ESB_WDT_LOCK : 0x00);
cf73120b 126 pci_write_config_byte(edev->pdev, ESB_LOCK_REG, val);
3b9d49ee 127 return 0;
cc90ef0f
DH
128}
129
7af4ac87 130static int esb_timer_stop(struct watchdog_device *wdd)
cc90ef0f 131{
cf73120b 132 struct esb_dev *edev = to_esb_dev(wdd);
cc90ef0f
DH
133 u8 val;
134
cc90ef0f 135 /* First, reset timers as suggested by the docs */
cf73120b
RR
136 esb_unlock_registers(edev);
137 writew(ESB_WDT_RELOAD, ESB_RELOAD_REG(edev));
cc90ef0f 138 /* Then disable the WDT */
cf73120b
RR
139 pci_write_config_byte(edev->pdev, ESB_LOCK_REG, 0x0);
140 pci_read_config_byte(edev->pdev, ESB_LOCK_REG, &val);
cc90ef0f
DH
141
142 /* Returns 0 if the timer was disabled, non-zero otherwise */
fc8a9d83 143 return val & ESB_WDT_ENABLE;
cc90ef0f
DH
144}
145
7af4ac87 146static int esb_timer_keepalive(struct watchdog_device *wdd)
cc90ef0f 147{
cf73120b
RR
148 struct esb_dev *edev = to_esb_dev(wdd);
149
150 esb_unlock_registers(edev);
151 writew(ESB_WDT_RELOAD, ESB_RELOAD_REG(edev));
0829291e 152 /* FIXME: Do we need to flush anything here? */
7af4ac87 153 return 0;
cc90ef0f
DH
154}
155
7af4ac87
RR
156static int esb_timer_set_heartbeat(struct watchdog_device *wdd,
157 unsigned int time)
cc90ef0f 158{
cf73120b 159 struct esb_dev *edev = to_esb_dev(wdd);
cc90ef0f
DH
160 u32 val;
161
cc90ef0f
DH
162 /* We shift by 9, so if we are passed a value of 1 sec,
163 * val will be 1 << 9 = 512, then write that to two
164 * timers => 2 * 512 = 1024 (which is decremented at 1KHz)
165 */
166 val = time << 9;
167
168 /* Write timer 1 */
cf73120b
RR
169 esb_unlock_registers(edev);
170 writel(val, ESB_TIMER1_REG(edev));
cc90ef0f
DH
171
172 /* Write timer 2 */
cf73120b
RR
173 esb_unlock_registers(edev);
174 writel(val, ESB_TIMER2_REG(edev));
cc90ef0f 175
0829291e 176 /* Reload */
cf73120b
RR
177 esb_unlock_registers(edev);
178 writew(ESB_WDT_RELOAD, ESB_RELOAD_REG(edev));
cc90ef0f
DH
179
180 /* FIXME: Do we need to flush everything out? */
181
182 /* Done */
7af4ac87 183 wdd->timeout = time;
cc90ef0f
DH
184 return 0;
185}
186
cc90ef0f 187/*
7af4ac87 188 * Watchdog Subsystem Interfaces
cc90ef0f
DH
189 */
190
7af4ac87
RR
191static struct watchdog_info esb_info = {
192 .identity = ESB_MODULE_NAME,
193 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
194};
cc90ef0f 195
7af4ac87 196static const struct watchdog_ops esb_ops = {
0829291e 197 .owner = THIS_MODULE,
7af4ac87
RR
198 .start = esb_timer_start,
199 .stop = esb_timer_stop,
200 .set_timeout = esb_timer_set_heartbeat,
201 .ping = esb_timer_keepalive,
cc90ef0f
DH
202};
203
cc90ef0f
DH
204/*
205 * Data for PCI driver interface
cc90ef0f 206 */
bc17f9dc 207static const struct pci_device_id esb_pci_tbl[] = {
0829291e
AC
208 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), },
209 { 0, }, /* End of list */
cc90ef0f 210};
0829291e 211MODULE_DEVICE_TABLE(pci, esb_pci_tbl);
cc90ef0f
DH
212
213/*
214 * Init & exit routines
215 */
216
cf73120b 217static unsigned char esb_getdevice(struct esb_dev *edev)
cc90ef0f 218{
cf73120b
RR
219 if (pci_enable_device(edev->pdev)) {
220 dev_err(&edev->pdev->dev, "failed to enable device\n");
fc8a9d83
WVS
221 goto err_devput;
222 }
cc90ef0f 223
cf73120b
RR
224 if (pci_request_region(edev->pdev, 0, ESB_MODULE_NAME)) {
225 dev_err(&edev->pdev->dev, "failed to request region\n");
fc8a9d83
WVS
226 goto err_disable;
227 }
cc90ef0f 228
cf73120b
RR
229 edev->base = pci_ioremap_bar(edev->pdev, 0);
230 if (edev->base == NULL) {
fc8a9d83 231 /* Something's wrong here, BASEADDR has to be set */
cf73120b 232 dev_err(&edev->pdev->dev, "failed to get BASEADDR\n");
fc8a9d83
WVS
233 goto err_release;
234 }
235
236 /* Done */
cf73120b 237 dev_set_drvdata(&edev->pdev->dev, edev);
fc8a9d83 238 return 1;
cc90ef0f
DH
239
240err_release:
cf73120b 241 pci_release_region(edev->pdev, 0);
cc90ef0f 242err_disable:
cf73120b 243 pci_disable_device(edev->pdev);
811f9991 244err_devput:
cc90ef0f
DH
245 return 0;
246}
247
cf73120b 248static void esb_initdevice(struct esb_dev *edev)
fc8a9d83
WVS
249{
250 u8 val1;
251 u16 val2;
252
253 /*
254 * Config register:
255 * Bit 5 : 0 = Enable WDT_OUTPUT
256 * Bit 2 : 0 = set the timer frequency to the PCI clock
257 * divided by 2^15 (approx 1KHz).
258 * Bits 1:0 : 11 = WDT_INT_TYPE Disabled.
259 * The watchdog has two timers, it can be setup so that the
260 * expiry of timer1 results in an interrupt and the expiry of
261 * timer2 results in a reboot. We set it to not generate
262 * any interrupts as there is not much we can do with it
263 * right now.
264 */
cf73120b 265 pci_write_config_word(edev->pdev, ESB_CONFIG_REG, 0x0003);
fc8a9d83
WVS
266
267 /* Check that the WDT isn't already locked */
cf73120b 268 pci_read_config_byte(edev->pdev, ESB_LOCK_REG, &val1);
fc8a9d83 269 if (val1 & ESB_WDT_LOCK)
cf73120b 270 dev_warn(&edev->pdev->dev, "nowayout already set\n");
fc8a9d83
WVS
271
272 /* Set the timer to watchdog mode and disable it for now */
cf73120b 273 pci_write_config_byte(edev->pdev, ESB_LOCK_REG, 0x00);
fc8a9d83
WVS
274
275 /* Check if the watchdog was previously triggered */
cf73120b
RR
276 esb_unlock_registers(edev);
277 val2 = readw(ESB_RELOAD_REG(edev));
fc8a9d83 278 if (val2 & ESB_WDT_TIMEOUT)
cf73120b 279 edev->wdd.bootstatus = WDIOF_CARDRESET;
fc8a9d83
WVS
280
281 /* Reset WDT_TIMEOUT flag and timers */
cf73120b
RR
282 esb_unlock_registers(edev);
283 writew((ESB_WDT_TIMEOUT | ESB_WDT_RELOAD), ESB_RELOAD_REG(edev));
fc8a9d83
WVS
284
285 /* And set the correct timeout value */
cf73120b 286 esb_timer_set_heartbeat(&edev->wdd, edev->wdd.timeout);
fc8a9d83
WVS
287}
288
2d991a16 289static int esb_probe(struct pci_dev *pdev,
2786095a 290 const struct pci_device_id *ent)
cc90ef0f 291{
cf73120b 292 struct esb_dev *edev;
0829291e
AC
293 int ret;
294
cf73120b
RR
295 edev = devm_kzalloc(&pdev->dev, sizeof(*edev), GFP_KERNEL);
296 if (!edev)
297 return -ENOMEM;
2786095a 298
0829291e 299 /* Check whether or not the hardware watchdog is there */
cf73120b
RR
300 edev->pdev = pdev;
301 if (!esb_getdevice(edev))
0829291e
AC
302 return -ENODEV;
303
fc8a9d83 304 /* Initialize the watchdog and make sure it does not run */
cf73120b
RR
305 edev->wdd.info = &esb_info;
306 edev->wdd.ops = &esb_ops;
568d6015
RR
307 edev->wdd.min_timeout = ESB_HEARTBEAT_MIN;
308 edev->wdd.max_timeout = ESB_HEARTBEAT_MAX;
309 edev->wdd.timeout = ESB_HEARTBEAT_DEFAULT;
89bd0ed8 310 watchdog_init_timeout(&edev->wdd, heartbeat, NULL);
cf73120b
RR
311 watchdog_set_nowayout(&edev->wdd, nowayout);
312 watchdog_stop_on_reboot(&edev->wdd);
313 watchdog_stop_on_unregister(&edev->wdd);
314 esb_initdevice(edev);
fc8a9d83
WVS
315
316 /* Register the watchdog so that userspace has access to it */
cf73120b 317 ret = watchdog_register_device(&edev->wdd);
0829291e 318 if (ret != 0) {
7af4ac87
RR
319 dev_err(&pdev->dev,
320 "cannot register watchdog device (err=%d)\n", ret);
0426fd0d 321 goto err_unmap;
0829291e 322 }
7af4ac87 323 dev_info(&pdev->dev,
f6cc8b35
MC
324 "initialized. heartbeat=%d sec (nowayout=%d)\n",
325 edev->wdd.timeout, nowayout);
0829291e 326 return 0;
cc90ef0f 327
cc90ef0f 328err_unmap:
cf73120b
RR
329 iounmap(edev->base);
330 pci_release_region(edev->pdev, 0);
331 pci_disable_device(edev->pdev);
0829291e 332 return ret;
cc90ef0f
DH
333}
334
4b12b896 335static void esb_remove(struct pci_dev *pdev)
cc90ef0f 336{
cf73120b
RR
337 struct esb_dev *edev = dev_get_drvdata(&pdev->dev);
338
339 watchdog_unregister_device(&edev->wdd);
340 iounmap(edev->base);
341 pci_release_region(edev->pdev, 0);
342 pci_disable_device(edev->pdev);
0426fd0d
WVS
343}
344
2786095a
WVS
345static struct pci_driver esb_driver = {
346 .name = ESB_MODULE_NAME,
347 .id_table = esb_pci_tbl,
0426fd0d 348 .probe = esb_probe,
82268714 349 .remove = esb_remove,
0426fd0d
WVS
350};
351
5ce9c371 352module_pci_driver(esb_driver);
cc90ef0f 353
96de0e25 354MODULE_AUTHOR("Ross Biro and David Härdeman");
cc90ef0f
DH
355MODULE_DESCRIPTION("Watchdog driver for Intel 6300ESB chipsets");
356MODULE_LICENSE("GPL");