Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
wm831x_wdt.c
Go to the documentation of this file.
1 /*
2  * Watchdog driver for the wm831x PMICs
3  *
4  * Copyright (C) 2009 Wolfson Microelectronics
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation
9  */
10 
11 #include <linux/module.h>
12 #include <linux/moduleparam.h>
13 #include <linux/types.h>
14 #include <linux/kernel.h>
15 #include <linux/slab.h>
16 #include <linux/platform_device.h>
17 #include <linux/watchdog.h>
18 #include <linux/uaccess.h>
19 #include <linux/gpio.h>
20 
21 #include <linux/mfd/wm831x/core.h>
22 #include <linux/mfd/wm831x/pdata.h>
24 
25 static bool nowayout = WATCHDOG_NOWAYOUT;
26 module_param(nowayout, bool, 0);
27 MODULE_PARM_DESC(nowayout,
28  "Watchdog cannot be stopped once started (default="
30 
33  struct wm831x *wm831x;
34  struct mutex lock;
37 };
38 
39 /* We can't use the sub-second values here but they're included
40  * for completeness. */
41 static struct {
42  unsigned int time; /* Seconds */
43  u16 val; /* WDOG_TO value */
44 } wm831x_wdt_cfgs[] = {
45  { 1, 2 },
46  { 2, 3 },
47  { 4, 4 },
48  { 8, 5 },
49  { 16, 6 },
50  { 32, 7 },
51  { 33, 7 }, /* Actually 32.768s so include both, others round down */
52 };
53 
54 static int wm831x_wdt_start(struct watchdog_device *wdt_dev)
55 {
56  struct wm831x_wdt_drvdata *driver_data = watchdog_get_drvdata(wdt_dev);
57  struct wm831x *wm831x = driver_data->wm831x;
58  int ret;
59 
60  mutex_lock(&driver_data->lock);
61 
62  ret = wm831x_reg_unlock(wm831x);
63  if (ret == 0) {
64  ret = wm831x_set_bits(wm831x, WM831X_WATCHDOG,
66  wm831x_reg_lock(wm831x);
67  } else {
68  dev_err(wm831x->dev, "Failed to unlock security key: %d\n",
69  ret);
70  }
71 
72  mutex_unlock(&driver_data->lock);
73 
74  return ret;
75 }
76 
77 static int wm831x_wdt_stop(struct watchdog_device *wdt_dev)
78 {
79  struct wm831x_wdt_drvdata *driver_data = watchdog_get_drvdata(wdt_dev);
80  struct wm831x *wm831x = driver_data->wm831x;
81  int ret;
82 
83  mutex_lock(&driver_data->lock);
84 
85  ret = wm831x_reg_unlock(wm831x);
86  if (ret == 0) {
87  ret = wm831x_set_bits(wm831x, WM831X_WATCHDOG,
88  WM831X_WDOG_ENA, 0);
89  wm831x_reg_lock(wm831x);
90  } else {
91  dev_err(wm831x->dev, "Failed to unlock security key: %d\n",
92  ret);
93  }
94 
95  mutex_unlock(&driver_data->lock);
96 
97  return ret;
98 }
99 
100 static int wm831x_wdt_ping(struct watchdog_device *wdt_dev)
101 {
102  struct wm831x_wdt_drvdata *driver_data = watchdog_get_drvdata(wdt_dev);
103  struct wm831x *wm831x = driver_data->wm831x;
104  int ret;
105  u16 reg;
106 
107  mutex_lock(&driver_data->lock);
108 
109  if (driver_data->update_gpio) {
111  driver_data->update_state);
112  driver_data->update_state = !driver_data->update_state;
113  ret = 0;
114  goto out;
115  }
116 
117  reg = wm831x_reg_read(wm831x, WM831X_WATCHDOG);
118 
119  if (!(reg & WM831X_WDOG_RST_SRC)) {
120  dev_err(wm831x->dev, "Hardware watchdog update unsupported\n");
121  ret = -EINVAL;
122  goto out;
123  }
124 
125  reg |= WM831X_WDOG_RESET;
126 
127  ret = wm831x_reg_unlock(wm831x);
128  if (ret == 0) {
129  ret = wm831x_reg_write(wm831x, WM831X_WATCHDOG, reg);
130  wm831x_reg_lock(wm831x);
131  } else {
132  dev_err(wm831x->dev, "Failed to unlock security key: %d\n",
133  ret);
134  }
135 
136 out:
137  mutex_unlock(&driver_data->lock);
138 
139  return ret;
140 }
141 
142 static int wm831x_wdt_set_timeout(struct watchdog_device *wdt_dev,
143  unsigned int timeout)
144 {
145  struct wm831x_wdt_drvdata *driver_data = watchdog_get_drvdata(wdt_dev);
146  struct wm831x *wm831x = driver_data->wm831x;
147  int ret, i;
148 
149  for (i = 0; i < ARRAY_SIZE(wm831x_wdt_cfgs); i++)
150  if (wm831x_wdt_cfgs[i].time == timeout)
151  break;
152  if (i == ARRAY_SIZE(wm831x_wdt_cfgs))
153  return -EINVAL;
154 
155  ret = wm831x_reg_unlock(wm831x);
156  if (ret == 0) {
157  ret = wm831x_set_bits(wm831x, WM831X_WATCHDOG,
159  wm831x_wdt_cfgs[i].val);
160  wm831x_reg_lock(wm831x);
161  } else {
162  dev_err(wm831x->dev, "Failed to unlock security key: %d\n",
163  ret);
164  }
165 
166  wdt_dev->timeout = timeout;
167 
168  return ret;
169 }
170 
171 static const struct watchdog_info wm831x_wdt_info = {
173  .identity = "WM831x Watchdog",
174 };
175 
176 static const struct watchdog_ops wm831x_wdt_ops = {
177  .owner = THIS_MODULE,
178  .start = wm831x_wdt_start,
179  .stop = wm831x_wdt_stop,
180  .ping = wm831x_wdt_ping,
181  .set_timeout = wm831x_wdt_set_timeout,
182 };
183 
184 static int __devinit wm831x_wdt_probe(struct platform_device *pdev)
185 {
186  struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
187  struct wm831x_pdata *chip_pdata;
189  struct wm831x_wdt_drvdata *driver_data;
190  struct watchdog_device *wm831x_wdt;
191  int reg, ret, i;
192 
193  ret = wm831x_reg_read(wm831x, WM831X_WATCHDOG);
194  if (ret < 0) {
195  dev_err(wm831x->dev, "Failed to read watchdog status: %d\n",
196  ret);
197  goto err;
198  }
199  reg = ret;
200 
201  if (reg & WM831X_WDOG_DEBUG)
202  dev_warn(wm831x->dev, "Watchdog is paused\n");
203 
204  driver_data = devm_kzalloc(&pdev->dev, sizeof(*driver_data),
205  GFP_KERNEL);
206  if (!driver_data) {
207  dev_err(wm831x->dev, "Unable to alloacate watchdog device\n");
208  ret = -ENOMEM;
209  goto err;
210  }
211 
212  mutex_init(&driver_data->lock);
213  driver_data->wm831x = wm831x;
214 
215  wm831x_wdt = &driver_data->wdt;
216 
217  wm831x_wdt->info = &wm831x_wdt_info;
218  wm831x_wdt->ops = &wm831x_wdt_ops;
219  watchdog_set_nowayout(wm831x_wdt, nowayout);
220  watchdog_set_drvdata(wm831x_wdt, driver_data);
221 
222  reg = wm831x_reg_read(wm831x, WM831X_WATCHDOG);
223  reg &= WM831X_WDOG_TO_MASK;
224  for (i = 0; i < ARRAY_SIZE(wm831x_wdt_cfgs); i++)
225  if (wm831x_wdt_cfgs[i].val == reg)
226  break;
227  if (i == ARRAY_SIZE(wm831x_wdt_cfgs))
228  dev_warn(wm831x->dev,
229  "Unknown watchdog timeout: %x\n", reg);
230  else
231  wm831x_wdt->timeout = wm831x_wdt_cfgs[i].time;
232 
233  /* Apply any configuration */
234  if (pdev->dev.parent->platform_data) {
235  chip_pdata = pdev->dev.parent->platform_data;
236  pdata = chip_pdata->watchdog;
237  } else {
238  pdata = NULL;
239  }
240 
241  if (pdata) {
244 
245  reg |= pdata->primary << WM831X_WDOG_PRIMACT_SHIFT;
246  reg |= pdata->secondary << WM831X_WDOG_SECACT_SHIFT;
247  reg |= pdata->software << WM831X_WDOG_RST_SRC_SHIFT;
248 
249  if (pdata->update_gpio) {
250  ret = gpio_request_one(pdata->update_gpio,
252  "Watchdog update");
253  if (ret < 0) {
254  dev_err(wm831x->dev,
255  "Failed to request update GPIO: %d\n",
256  ret);
257  goto err;
258  }
259 
260  driver_data->update_gpio = pdata->update_gpio;
261 
262  /* Make sure the watchdog takes hardware updates */
263  reg |= WM831X_WDOG_RST_SRC;
264  }
265 
266  ret = wm831x_reg_unlock(wm831x);
267  if (ret == 0) {
268  ret = wm831x_reg_write(wm831x, WM831X_WATCHDOG, reg);
269  wm831x_reg_lock(wm831x);
270  } else {
271  dev_err(wm831x->dev,
272  "Failed to unlock security key: %d\n", ret);
273  goto err_gpio;
274  }
275  }
276 
277  ret = watchdog_register_device(&driver_data->wdt);
278  if (ret != 0) {
279  dev_err(wm831x->dev, "watchdog_register_device() failed: %d\n",
280  ret);
281  goto err_gpio;
282  }
283 
284  dev_set_drvdata(&pdev->dev, driver_data);
285 
286  return 0;
287 
288 err_gpio:
289  if (driver_data->update_gpio)
290  gpio_free(driver_data->update_gpio);
291 err:
292  return ret;
293 }
294 
295 static int __devexit wm831x_wdt_remove(struct platform_device *pdev)
296 {
297  struct wm831x_wdt_drvdata *driver_data = dev_get_drvdata(&pdev->dev);
298 
299  watchdog_unregister_device(&driver_data->wdt);
300 
301  if (driver_data->update_gpio)
302  gpio_free(driver_data->update_gpio);
303 
304  return 0;
305 }
306 
307 static struct platform_driver wm831x_wdt_driver = {
308  .probe = wm831x_wdt_probe,
309  .remove = __devexit_p(wm831x_wdt_remove),
310  .driver = {
311  .name = "wm831x-watchdog",
312  },
313 };
314 
315 module_platform_driver(wm831x_wdt_driver);
316 
317 MODULE_AUTHOR("Mark Brown");
318 MODULE_DESCRIPTION("WM831x Watchdog");
319 MODULE_LICENSE("GPL");
320 MODULE_ALIAS("platform:wm831x-watchdog");