8f07dd4bd94a67385d3c44093a8a9f5c75e8f960
[cascardo/linux.git] / drivers / watchdog / via_wdt.c
1 /*
2  * VIA Chipset Watchdog Driver
3  *
4  * Copyright (C) 2011 Sigfox
5  * License terms: GNU General Public License (GPL) version 2
6  * Author: Marc Vertes <marc.vertes@sigfox.com>
7  * Based on a preliminary version from Harald Welte <HaraldWelte@viatech.com>
8  * Timer code by Wim Van Sebroeck <wim@iguana.be>
9  *
10  * Caveat: PnP must be enabled in BIOS to allow full access to watchdog
11  * control registers. If not, the watchdog must be configured in BIOS manually.
12  */
13 #include <linux/device.h>
14 #include <linux/io.h>
15 #include <linux/jiffies.h>
16 #include <linux/module.h>
17 #include <linux/pci.h>
18 #include <linux/timer.h>
19 #include <linux/watchdog.h>
20
21 /* Configuration registers relative to the pci device */
22 #define VIA_WDT_MMIO_BASE       0xe8    /* MMIO region base address */
23 #define VIA_WDT_CONF            0xec    /* watchdog enable state */
24
25 /* Relevant bits for the VIA_WDT_CONF register */
26 #define VIA_WDT_CONF_ENABLE     0x01    /* 1: enable watchdog */
27 #define VIA_WDT_CONF_MMIO       0x02    /* 1: enable watchdog MMIO */
28
29 /*
30  * The MMIO region contains the watchog control register and the
31  * hardware timer counter.
32  */
33 #define VIA_WDT_MMIO_LEN        8       /* MMIO region length in bytes */
34 #define VIA_WDT_CTL             0       /* MMIO addr+0: state/control reg. */
35 #define VIA_WDT_COUNT           4       /* MMIO addr+4: timer counter reg. */
36
37 /* Bits for the VIA_WDT_CTL register */
38 #define VIA_WDT_RUNNING         0x01    /* 0: stop, 1: running */
39 #define VIA_WDT_FIRED           0x02    /* 1: restarted by expired watchdog */
40 #define VIA_WDT_PWROFF          0x04    /* 0: reset, 1: poweroff */
41 #define VIA_WDT_DISABLED        0x08    /* 1: timer is disabled */
42 #define VIA_WDT_TRIGGER         0x80    /* 1: start a new countdown */
43
44 /* Hardware heartbeat in seconds */
45 #define WDT_HW_HEARTBEAT 1
46
47 /* Timer heartbeat (500ms) */
48 #define WDT_HEARTBEAT   (HZ/2)  /* should be <= ((WDT_HW_HEARTBEAT*HZ)/2) */
49
50 /* User space timeout in seconds */
51 #define WDT_TIMEOUT_MAX 1023    /* approx. 17 min. */
52 #define WDT_TIMEOUT     60
53 static int timeout = WDT_TIMEOUT;
54 module_param(timeout, int, 0);
55 MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, between 1 and 1023 "
56         "(default = " __MODULE_STRING(WDT_TIMEOUT) ")");
57
58 static int nowayout = WATCHDOG_NOWAYOUT;
59 module_param(nowayout, int, 0);
60 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
61         "(default = " __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
62
63 static struct watchdog_device wdt_dev;
64 static struct resource wdt_res;
65 static void __iomem *wdt_mem;
66 static unsigned int mmio;
67 static void wdt_timer_tick(unsigned long data);
68 static DEFINE_TIMER(timer, wdt_timer_tick, 0, 0);
69                                         /* The timer that pings the watchdog */
70 static unsigned long next_heartbeat;    /* the next_heartbeat for the timer */
71
72 static inline void wdt_reset(void)
73 {
74         unsigned int ctl = readl(wdt_mem);
75
76         writel(ctl | VIA_WDT_TRIGGER, wdt_mem);
77 }
78
79 /*
80  * Timer tick: the timer will make sure that the watchdog timer hardware
81  * is being reset in time. The conditions to do this are:
82  *  1) the watchog timer has been started and /dev/watchdog is open
83  *     and there is still time left before userspace should send the
84  *     next heartbeat/ping. (note: the internal heartbeat is much smaller
85  *     then the external/userspace heartbeat).
86  *  2) the watchdog timer has been stopped by userspace.
87  */
88 static void wdt_timer_tick(unsigned long data)
89 {
90         if (time_before(jiffies, next_heartbeat) ||
91            (!test_bit(WDOG_ACTIVE, &wdt_dev.status))) {
92                 wdt_reset();
93                 mod_timer(&timer, jiffies + WDT_HEARTBEAT);
94         } else
95                 pr_crit("I will reboot your machine !\n");
96 }
97
98 static int wdt_ping(struct watchdog_device *wdd)
99 {
100         /* calculate when the next userspace timeout will be */
101         next_heartbeat = jiffies + timeout * HZ;
102         return 0;
103 }
104
105 static int wdt_start(struct watchdog_device *wdd)
106 {
107         unsigned int ctl = readl(wdt_mem);
108
109         writel(timeout, wdt_mem + VIA_WDT_COUNT);
110         writel(ctl | VIA_WDT_RUNNING | VIA_WDT_TRIGGER, wdt_mem);
111         wdt_ping(wdd);
112         mod_timer(&timer, jiffies + WDT_HEARTBEAT);
113         return 0;
114 }
115
116 static int wdt_stop(struct watchdog_device *wdd)
117 {
118         unsigned int ctl = readl(wdt_mem);
119
120         writel(ctl & ~VIA_WDT_RUNNING, wdt_mem);
121         return 0;
122 }
123
124 static int wdt_set_timeout(struct watchdog_device *wdd,
125                            unsigned int new_timeout)
126 {
127         writel(new_timeout, wdt_mem + VIA_WDT_COUNT);
128         timeout = new_timeout;
129         return 0;
130 }
131
132 static const struct watchdog_info wdt_info = {
133         .identity =     "VIA watchdog",
134         .options =      WDIOF_CARDRESET |
135                         WDIOF_SETTIMEOUT |
136                         WDIOF_MAGICCLOSE |
137                         WDIOF_KEEPALIVEPING,
138 };
139
140 static const struct watchdog_ops wdt_ops = {
141         .owner =        THIS_MODULE,
142         .start =        wdt_start,
143         .stop =         wdt_stop,
144         .ping =         wdt_ping,
145         .set_timeout =  wdt_set_timeout,
146 };
147
148 static struct watchdog_device wdt_dev = {
149         .info =         &wdt_info,
150         .ops =          &wdt_ops,
151         .min_timeout =  1,
152         .max_timeout =  WDT_TIMEOUT_MAX,
153 };
154
155 static int __devinit wdt_probe(struct pci_dev *pdev,
156                                const struct pci_device_id *ent)
157 {
158         unsigned char conf;
159         int ret = -ENODEV;
160
161         if (pci_enable_device(pdev)) {
162                 dev_err(&pdev->dev, "cannot enable PCI device\n");
163                 return -ENODEV;
164         }
165
166         /*
167          * Allocate a MMIO region which contains watchdog control register
168          * and counter, then configure the watchdog to use this region.
169          * This is possible only if PnP is properly enabled in BIOS.
170          * If not, the watchdog must be configured in BIOS manually.
171          */
172         if (allocate_resource(&iomem_resource, &wdt_res, VIA_WDT_MMIO_LEN,
173                               0xf0000000, 0xffffff00, 0xff, NULL, NULL)) {
174                 dev_err(&pdev->dev, "MMIO allocation failed\n");
175                 goto err_out_disable_device;
176         }
177
178         pci_write_config_dword(pdev, VIA_WDT_MMIO_BASE, wdt_res.start);
179         pci_read_config_byte(pdev, VIA_WDT_CONF, &conf);
180         conf |= VIA_WDT_CONF_ENABLE | VIA_WDT_CONF_MMIO;
181         pci_write_config_byte(pdev, VIA_WDT_CONF, conf);
182
183         pci_read_config_dword(pdev, VIA_WDT_MMIO_BASE, &mmio);
184         if (mmio) {
185                 dev_info(&pdev->dev, "VIA Chipset watchdog MMIO: %x\n", mmio);
186         } else {
187                 dev_err(&pdev->dev, "MMIO setting failed. Check BIOS.\n");
188                 goto err_out_resource;
189         }
190
191         if (!request_mem_region(mmio, VIA_WDT_MMIO_LEN, "via_wdt")) {
192                 dev_err(&pdev->dev, "MMIO region busy\n");
193                 goto err_out_resource;
194         }
195
196         wdt_mem = ioremap(mmio, VIA_WDT_MMIO_LEN);
197         if (wdt_mem == NULL) {
198                 dev_err(&pdev->dev, "cannot remap VIA wdt MMIO registers\n");
199                 goto err_out_release;
200         }
201
202         wdt_dev.timeout = timeout;
203         watchdog_set_nowayout(&wdt_dev, nowayout);
204         if (readl(wdt_mem) & VIA_WDT_FIRED)
205                 wdt_dev.bootstatus |= WDIOF_CARDRESET;
206
207         ret = watchdog_register_device(&wdt_dev);
208         if (ret)
209                 goto err_out_iounmap;
210
211         /* start triggering, in case of watchdog already enabled by BIOS */
212         mod_timer(&timer, jiffies + WDT_HEARTBEAT);
213         return 0;
214
215 err_out_iounmap:
216         iounmap(wdt_mem);
217 err_out_release:
218         release_mem_region(mmio, VIA_WDT_MMIO_LEN);
219 err_out_resource:
220         release_resource(&wdt_res);
221 err_out_disable_device:
222         pci_disable_device(pdev);
223         return ret;
224 }
225
226 static void __devexit wdt_remove(struct pci_dev *pdev)
227 {
228         watchdog_unregister_device(&wdt_dev);
229         del_timer(&timer);
230         iounmap(wdt_mem);
231         release_mem_region(mmio, VIA_WDT_MMIO_LEN);
232         release_resource(&wdt_res);
233         pci_disable_device(pdev);
234 }
235
236 static DEFINE_PCI_DEVICE_TABLE(wdt_pci_table) = {
237         { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700) },
238         { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX800) },
239         { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) },
240         { 0 }
241 };
242
243 static struct pci_driver wdt_driver = {
244         .name           = "via_wdt",
245         .id_table       = wdt_pci_table,
246         .probe          = wdt_probe,
247         .remove         = __devexit_p(wdt_remove),
248 };
249
250 static int __init wdt_init(void)
251 {
252         if (timeout < 1 || timeout > WDT_TIMEOUT_MAX)
253                 timeout = WDT_TIMEOUT;
254         return pci_register_driver(&wdt_driver);
255 }
256
257 static void __exit wdt_exit(void)
258 {
259         pci_unregister_driver(&wdt_driver);
260 }
261
262 module_init(wdt_init);
263 module_exit(wdt_exit);
264
265 MODULE_AUTHOR("Marc Vertes");
266 MODULE_DESCRIPTION("Driver for watchdog timer on VIA chipset");
267 MODULE_LICENSE("GPL");