diff options
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/omap_wdt.c | 283 | ||||
-rw-r--r-- | drivers/watchdog/omap_wdt.h | 28 |
2 files changed, 190 insertions, 121 deletions
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 3a11dadfd8e7..7de16a3f6849 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/watchdog/omap_wdt.c | 2 | * omap_wdt.c |
3 | * | 3 | * |
4 | * Watchdog driver for the TI OMAP 16xx & 24xx 32KHz (non-secure) watchdog | 4 | * Watchdog driver for the TI OMAP 16xx & 24xx/34xx 32KHz (non-secure) watchdog |
5 | * | 5 | * |
6 | * Author: MontaVista Software, Inc. | 6 | * Author: MontaVista Software, Inc. |
7 | * <gdavis@mvista.com> or <source@mvista.com> | 7 | * <gdavis@mvista.com> or <source@mvista.com> |
@@ -47,50 +47,63 @@ | |||
47 | 47 | ||
48 | #include "omap_wdt.h" | 48 | #include "omap_wdt.h" |
49 | 49 | ||
50 | static struct platform_device *omap_wdt_dev; | ||
51 | |||
50 | static unsigned timer_margin; | 52 | static unsigned timer_margin; |
51 | module_param(timer_margin, uint, 0); | 53 | module_param(timer_margin, uint, 0); |
52 | MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)"); | 54 | MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)"); |
53 | 55 | ||
54 | static int omap_wdt_users; | ||
55 | static struct clk *armwdt_ck; | ||
56 | static struct clk *mpu_wdt_ick; | ||
57 | static struct clk *mpu_wdt_fck; | ||
58 | |||
59 | static unsigned int wdt_trgr_pattern = 0x1234; | 56 | static unsigned int wdt_trgr_pattern = 0x1234; |
60 | static spinlock_t wdt_lock; | 57 | static spinlock_t wdt_lock; |
61 | 58 | ||
62 | static void omap_wdt_ping(void) | 59 | struct omap_wdt_dev { |
60 | void __iomem *base; /* physical */ | ||
61 | struct device *dev; | ||
62 | int omap_wdt_users; | ||
63 | struct clk *armwdt_ck; | ||
64 | struct clk *mpu_wdt_ick; | ||
65 | struct clk *mpu_wdt_fck; | ||
66 | struct resource *mem; | ||
67 | struct miscdevice omap_wdt_miscdev; | ||
68 | }; | ||
69 | |||
70 | static void omap_wdt_ping(struct omap_wdt_dev *wdev) | ||
63 | { | 71 | { |
72 | void __iomem *base = wdev->base; | ||
64 | /* wait for posted write to complete */ | 73 | /* wait for posted write to complete */ |
65 | while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08) | 74 | while ((omap_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) |
66 | cpu_relax(); | 75 | cpu_relax(); |
67 | wdt_trgr_pattern = ~wdt_trgr_pattern; | 76 | wdt_trgr_pattern = ~wdt_trgr_pattern; |
68 | omap_writel(wdt_trgr_pattern, (OMAP_WATCHDOG_TGR)); | 77 | omap_writel(wdt_trgr_pattern, (base + OMAP_WATCHDOG_TGR)); |
69 | /* wait for posted write to complete */ | 78 | /* wait for posted write to complete */ |
70 | while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08) | 79 | while ((omap_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) |
71 | cpu_relax(); | 80 | cpu_relax(); |
72 | /* reloaded WCRR from WLDR */ | 81 | /* reloaded WCRR from WLDR */ |
73 | } | 82 | } |
74 | 83 | ||
75 | static void omap_wdt_enable(void) | 84 | static void omap_wdt_enable(struct omap_wdt_dev *wdev) |
76 | { | 85 | { |
86 | void __iomem *base; | ||
87 | base = wdev->base; | ||
77 | /* Sequence to enable the watchdog */ | 88 | /* Sequence to enable the watchdog */ |
78 | omap_writel(0xBBBB, OMAP_WATCHDOG_SPR); | 89 | omap_writel(0xBBBB, base + OMAP_WATCHDOG_SPR); |
79 | while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10) | 90 | while ((omap_readl(base + OMAP_WATCHDOG_WPS)) & 0x10) |
80 | cpu_relax(); | 91 | cpu_relax(); |
81 | omap_writel(0x4444, OMAP_WATCHDOG_SPR); | 92 | omap_writel(0x4444, base + OMAP_WATCHDOG_SPR); |
82 | while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10) | 93 | while ((omap_readl(base + OMAP_WATCHDOG_WPS)) & 0x10) |
83 | cpu_relax(); | 94 | cpu_relax(); |
84 | } | 95 | } |
85 | 96 | ||
86 | static void omap_wdt_disable(void) | 97 | static void omap_wdt_disable(struct omap_wdt_dev *wdev) |
87 | { | 98 | { |
99 | void __iomem *base; | ||
100 | base = wdev->base; | ||
88 | /* sequence required to disable watchdog */ | 101 | /* sequence required to disable watchdog */ |
89 | omap_writel(0xAAAA, OMAP_WATCHDOG_SPR); /* TIMER_MODE */ | 102 | omap_writel(0xAAAA, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */ |
90 | while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10) | 103 | while (omap_readl(base + OMAP_WATCHDOG_WPS) & 0x10) |
91 | cpu_relax(); | 104 | cpu_relax(); |
92 | omap_writel(0x5555, OMAP_WATCHDOG_SPR); /* TIMER_MODE */ | 105 | omap_writel(0x5555, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */ |
93 | while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10) | 106 | while (omap_readl(base + OMAP_WATCHDOG_WPS) & 0x10) |
94 | cpu_relax(); | 107 | cpu_relax(); |
95 | } | 108 | } |
96 | 109 | ||
@@ -103,15 +116,17 @@ static void omap_wdt_adjust_timeout(unsigned new_timeout) | |||
103 | timer_margin = new_timeout; | 116 | timer_margin = new_timeout; |
104 | } | 117 | } |
105 | 118 | ||
106 | static void omap_wdt_set_timeout(void) | 119 | static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) |
107 | { | 120 | { |
108 | u32 pre_margin = GET_WLDR_VAL(timer_margin); | 121 | u32 pre_margin = GET_WLDR_VAL(timer_margin); |
122 | void __iomem *base; | ||
123 | base = wdev->base; | ||
109 | 124 | ||
110 | /* just count up at 32 KHz */ | 125 | /* just count up at 32 KHz */ |
111 | while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04) | 126 | while (omap_readl(base + OMAP_WATCHDOG_WPS) & 0x04) |
112 | cpu_relax(); | 127 | cpu_relax(); |
113 | omap_writel(pre_margin, OMAP_WATCHDOG_LDR); | 128 | omap_writel(pre_margin, base + OMAP_WATCHDOG_LDR); |
114 | while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04) | 129 | while (omap_readl(base + OMAP_WATCHDOG_WPS) & 0x04) |
115 | cpu_relax(); | 130 | cpu_relax(); |
116 | } | 131 | } |
117 | 132 | ||
@@ -121,65 +136,69 @@ static void omap_wdt_set_timeout(void) | |||
121 | 136 | ||
122 | static int omap_wdt_open(struct inode *inode, struct file *file) | 137 | static int omap_wdt_open(struct inode *inode, struct file *file) |
123 | { | 138 | { |
124 | if (test_and_set_bit(1, (unsigned long *)&omap_wdt_users)) | 139 | struct omap_wdt_dev *wdev; |
140 | void __iomem *base; | ||
141 | wdev = platform_get_drvdata(omap_wdt_dev); | ||
142 | base = wdev->base; | ||
143 | if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users))) | ||
125 | return -EBUSY; | 144 | return -EBUSY; |
126 | 145 | ||
127 | if (cpu_is_omap16xx()) | 146 | if (cpu_is_omap16xx()) |
128 | clk_enable(armwdt_ck); /* Enable the clock */ | 147 | clk_enable(wdev->armwdt_ck); /* Enable the clock */ |
129 | 148 | ||
130 | if (cpu_is_omap24xx()) { | 149 | if (cpu_is_omap24xx() || cpu_is_omap34xx()) { |
131 | clk_enable(mpu_wdt_ick); /* Enable the interface clock */ | 150 | clk_enable(wdev->mpu_wdt_ick); /* Enable the interface clock */ |
132 | clk_enable(mpu_wdt_fck); /* Enable the functional clock */ | 151 | clk_enable(wdev->mpu_wdt_fck); /* Enable the functional clock */ |
133 | } | 152 | } |
134 | 153 | ||
135 | /* initialize prescaler */ | 154 | /* initialize prescaler */ |
136 | while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01) | 155 | while (omap_readl(base + OMAP_WATCHDOG_WPS) & 0x01) |
137 | cpu_relax(); | 156 | cpu_relax(); |
138 | omap_writel((1 << 5) | (PTV << 2), OMAP_WATCHDOG_CNTRL); | 157 | omap_writel((1 << 5) | (PTV << 2), base + OMAP_WATCHDOG_CNTRL); |
139 | while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01) | 158 | while (omap_readl(base + OMAP_WATCHDOG_WPS) & 0x01) |
140 | cpu_relax(); | 159 | cpu_relax(); |
141 | 160 | ||
142 | omap_wdt_set_timeout(); | 161 | file->private_data = (void *) wdev; |
143 | omap_wdt_enable(); | 162 | |
163 | omap_wdt_set_timeout(wdev); | ||
164 | omap_wdt_enable(wdev); | ||
144 | return nonseekable_open(inode, file); | 165 | return nonseekable_open(inode, file); |
145 | } | 166 | } |
146 | 167 | ||
147 | static int omap_wdt_release(struct inode *inode, struct file *file) | 168 | static int omap_wdt_release(struct inode *inode, struct file *file) |
148 | { | 169 | { |
170 | struct omap_wdt_dev *wdev; | ||
171 | wdev = file->private_data; | ||
149 | /* | 172 | /* |
150 | * Shut off the timer unless NOWAYOUT is defined. | 173 | * Shut off the timer unless NOWAYOUT is defined. |
151 | */ | 174 | */ |
152 | #ifndef CONFIG_WATCHDOG_NOWAYOUT | 175 | #ifndef CONFIG_WATCHDOG_NOWAYOUT |
153 | omap_wdt_disable(); | ||
154 | 176 | ||
155 | if (cpu_is_omap16xx()) { | 177 | omap_wdt_disable(wdev); |
156 | clk_disable(armwdt_ck); /* Disable the clock */ | ||
157 | clk_put(armwdt_ck); | ||
158 | armwdt_ck = NULL; | ||
159 | } | ||
160 | 178 | ||
161 | if (cpu_is_omap24xx()) { | 179 | if (cpu_is_omap16xx()) |
162 | clk_disable(mpu_wdt_ick); /* Disable the clock */ | 180 | clk_disable(wdev->armwdt_ck); /* Disable the clock */ |
163 | clk_disable(mpu_wdt_fck); /* Disable the clock */ | 181 | |
164 | clk_put(mpu_wdt_ick); | 182 | if (cpu_is_omap24xx() || cpu_is_omap34xx()) { |
165 | clk_put(mpu_wdt_fck); | 183 | clk_disable(wdev->mpu_wdt_ick); /* Disable the clock */ |
166 | mpu_wdt_ick = NULL; | 184 | clk_disable(wdev->mpu_wdt_fck); /* Disable the clock */ |
167 | mpu_wdt_fck = NULL; | ||
168 | } | 185 | } |
169 | #else | 186 | #else |
170 | printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n"); | 187 | printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n"); |
171 | #endif | 188 | #endif |
172 | omap_wdt_users = 0; | 189 | wdev->omap_wdt_users = 0; |
173 | return 0; | 190 | return 0; |
174 | } | 191 | } |
175 | 192 | ||
176 | static ssize_t omap_wdt_write(struct file *file, const char __user *data, | 193 | static ssize_t omap_wdt_write(struct file *file, const char __user *data, |
177 | size_t len, loff_t *ppos) | 194 | size_t len, loff_t *ppos) |
178 | { | 195 | { |
196 | struct omap_wdt_dev *wdev; | ||
197 | wdev = file->private_data; | ||
179 | /* Refresh LOAD_TIME. */ | 198 | /* Refresh LOAD_TIME. */ |
180 | if (len) { | 199 | if (len) { |
181 | spin_lock(&wdt_lock); | 200 | spin_lock(&wdt_lock); |
182 | omap_wdt_ping(); | 201 | omap_wdt_ping(wdev); |
183 | spin_unlock(&wdt_lock); | 202 | spin_unlock(&wdt_lock); |
184 | } | 203 | } |
185 | return len; | 204 | return len; |
@@ -188,12 +207,14 @@ static ssize_t omap_wdt_write(struct file *file, const char __user *data, | |||
188 | static long omap_wdt_ioctl(struct file *file, unsigned int cmd, | 207 | static long omap_wdt_ioctl(struct file *file, unsigned int cmd, |
189 | unsigned long arg) | 208 | unsigned long arg) |
190 | { | 209 | { |
210 | struct omap_wdt_dev *wdev; | ||
191 | int new_margin; | 211 | int new_margin; |
192 | static const struct watchdog_info ident = { | 212 | static const struct watchdog_info ident = { |
193 | .identity = "OMAP Watchdog", | 213 | .identity = "OMAP Watchdog", |
194 | .options = WDIOF_SETTIMEOUT, | 214 | .options = WDIOF_SETTIMEOUT, |
195 | .firmware_version = 0, | 215 | .firmware_version = 0, |
196 | }; | 216 | }; |
217 | wdev = file->private_data; | ||
197 | 218 | ||
198 | switch (cmd) { | 219 | switch (cmd) { |
199 | case WDIOC_GETSUPPORT: | 220 | case WDIOC_GETSUPPORT: |
@@ -210,7 +231,7 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, | |||
210 | (int __user *)arg); | 231 | (int __user *)arg); |
211 | case WDIOC_KEEPALIVE: | 232 | case WDIOC_KEEPALIVE: |
212 | spin_lock(&wdt_lock); | 233 | spin_lock(&wdt_lock); |
213 | omap_wdt_ping(); | 234 | omap_wdt_ping(wdev); |
214 | spin_unlock(&wdt_lock); | 235 | spin_unlock(&wdt_lock); |
215 | return 0; | 236 | return 0; |
216 | case WDIOC_SETTIMEOUT: | 237 | case WDIOC_SETTIMEOUT: |
@@ -219,11 +240,11 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, | |||
219 | omap_wdt_adjust_timeout(new_margin); | 240 | omap_wdt_adjust_timeout(new_margin); |
220 | 241 | ||
221 | spin_lock(&wdt_lock); | 242 | spin_lock(&wdt_lock); |
222 | omap_wdt_disable(); | 243 | omap_wdt_disable(wdev); |
223 | omap_wdt_set_timeout(); | 244 | omap_wdt_set_timeout(wdev); |
224 | omap_wdt_enable(); | 245 | omap_wdt_enable(wdev); |
225 | 246 | ||
226 | omap_wdt_ping(); | 247 | omap_wdt_ping(wdev); |
227 | spin_unlock(&wdt_lock); | 248 | spin_unlock(&wdt_lock); |
228 | /* Fall */ | 249 | /* Fall */ |
229 | case WDIOC_GETTIMEOUT: | 250 | case WDIOC_GETTIMEOUT: |
@@ -241,96 +262,150 @@ static const struct file_operations omap_wdt_fops = { | |||
241 | .release = omap_wdt_release, | 262 | .release = omap_wdt_release, |
242 | }; | 263 | }; |
243 | 264 | ||
244 | static struct miscdevice omap_wdt_miscdev = { | ||
245 | .minor = WATCHDOG_MINOR, | ||
246 | .name = "watchdog", | ||
247 | .fops = &omap_wdt_fops, | ||
248 | }; | ||
249 | 265 | ||
250 | static int __init omap_wdt_probe(struct platform_device *pdev) | 266 | static int __init omap_wdt_probe(struct platform_device *pdev) |
251 | { | 267 | { |
252 | struct resource *res, *mem; | 268 | struct resource *res, *mem; |
253 | int ret; | 269 | int ret; |
270 | struct omap_wdt_dev *wdev; | ||
254 | 271 | ||
255 | /* reserve static register mappings */ | 272 | /* reserve static register mappings */ |
256 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 273 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
257 | if (!res) | 274 | if (!res) |
258 | return -ENOENT; | 275 | return -ENOENT; |
259 | 276 | ||
277 | if (omap_wdt_dev) | ||
278 | return -EBUSY; | ||
279 | |||
260 | mem = request_mem_region(res->start, res->end - res->start + 1, | 280 | mem = request_mem_region(res->start, res->end - res->start + 1, |
261 | pdev->name); | 281 | pdev->name); |
262 | if (mem == NULL) | 282 | if (mem == NULL) |
263 | return -EBUSY; | 283 | return -EBUSY; |
264 | 284 | ||
265 | platform_set_drvdata(pdev, mem); | 285 | wdev = kzalloc(sizeof(struct omap_wdt_dev), GFP_KERNEL); |
266 | 286 | if (!wdev) { | |
267 | omap_wdt_users = 0; | 287 | ret = -ENOMEM; |
288 | goto fail; | ||
289 | } | ||
290 | wdev->omap_wdt_users = 0; | ||
291 | wdev->mem = mem; | ||
268 | 292 | ||
269 | if (cpu_is_omap16xx()) { | 293 | if (cpu_is_omap16xx()) { |
270 | armwdt_ck = clk_get(&pdev->dev, "armwdt_ck"); | 294 | wdev->armwdt_ck = clk_get(&pdev->dev, "armwdt_ck"); |
271 | if (IS_ERR(armwdt_ck)) { | 295 | if (IS_ERR(wdev->armwdt_ck)) { |
272 | ret = PTR_ERR(armwdt_ck); | 296 | ret = PTR_ERR(wdev->armwdt_ck); |
273 | armwdt_ck = NULL; | 297 | wdev->armwdt_ck = NULL; |
274 | goto fail; | 298 | goto fail; |
275 | } | 299 | } |
276 | } | 300 | } |
277 | 301 | ||
278 | if (cpu_is_omap24xx()) { | 302 | if (cpu_is_omap24xx()) { |
279 | mpu_wdt_ick = clk_get(&pdev->dev, "mpu_wdt_ick"); | 303 | wdev->mpu_wdt_ick = clk_get(&pdev->dev, "mpu_wdt_ick"); |
280 | if (IS_ERR(mpu_wdt_ick)) { | 304 | if (IS_ERR(wdev->mpu_wdt_ick)) { |
281 | ret = PTR_ERR(mpu_wdt_ick); | 305 | ret = PTR_ERR(wdev->mpu_wdt_ick); |
282 | mpu_wdt_ick = NULL; | 306 | wdev->mpu_wdt_ick = NULL; |
307 | goto fail; | ||
308 | } | ||
309 | wdev->mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck"); | ||
310 | if (IS_ERR(wdev->mpu_wdt_fck)) { | ||
311 | ret = PTR_ERR(wdev->mpu_wdt_fck); | ||
312 | wdev->mpu_wdt_fck = NULL; | ||
313 | goto fail; | ||
314 | } | ||
315 | } | ||
316 | |||
317 | if (cpu_is_omap34xx()) { | ||
318 | wdev->mpu_wdt_ick = clk_get(&pdev->dev, "wdt2_ick"); | ||
319 | if (IS_ERR(wdev->mpu_wdt_ick)) { | ||
320 | ret = PTR_ERR(wdev->mpu_wdt_ick); | ||
321 | wdev->mpu_wdt_ick = NULL; | ||
283 | goto fail; | 322 | goto fail; |
284 | } | 323 | } |
285 | mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck"); | 324 | wdev->mpu_wdt_fck = clk_get(&pdev->dev, "wdt2_fck"); |
286 | if (IS_ERR(mpu_wdt_fck)) { | 325 | if (IS_ERR(wdev->mpu_wdt_fck)) { |
287 | ret = PTR_ERR(mpu_wdt_fck); | 326 | ret = PTR_ERR(wdev->mpu_wdt_fck); |
288 | mpu_wdt_fck = NULL; | 327 | wdev->mpu_wdt_fck = NULL; |
289 | goto fail; | 328 | goto fail; |
290 | } | 329 | } |
291 | } | 330 | } |
331 | wdev->base = (void __iomem *) (mem->start); | ||
332 | platform_set_drvdata(pdev, wdev); | ||
292 | 333 | ||
293 | omap_wdt_disable(); | 334 | omap_wdt_disable(wdev); |
294 | omap_wdt_adjust_timeout(timer_margin); | 335 | omap_wdt_adjust_timeout(timer_margin); |
295 | 336 | ||
296 | omap_wdt_miscdev.parent = &pdev->dev; | 337 | wdev->omap_wdt_miscdev.parent = &pdev->dev; |
297 | ret = misc_register(&omap_wdt_miscdev); | 338 | wdev->omap_wdt_miscdev.minor = WATCHDOG_MINOR; |
339 | wdev->omap_wdt_miscdev.name = "watchdog"; | ||
340 | wdev->omap_wdt_miscdev.fops = &omap_wdt_fops; | ||
341 | |||
342 | ret = misc_register(&(wdev->omap_wdt_miscdev)); | ||
298 | if (ret) | 343 | if (ret) |
299 | goto fail; | 344 | goto fail; |
300 | 345 | ||
301 | pr_info("OMAP Watchdog Timer: initial timeout %d sec\n", timer_margin); | 346 | pr_info("OMAP Watchdog Timer Rev 0x%02x: initial timeout %d sec\n", |
347 | omap_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF, | ||
348 | timer_margin); | ||
302 | 349 | ||
303 | /* autogate OCP interface clock */ | 350 | /* autogate OCP interface clock */ |
304 | omap_writel(0x01, OMAP_WATCHDOG_SYS_CONFIG); | 351 | omap_writel(0x01, wdev->base + OMAP_WATCHDOG_SYS_CONFIG); |
352 | |||
353 | omap_wdt_dev = pdev; | ||
354 | |||
305 | return 0; | 355 | return 0; |
306 | 356 | ||
307 | fail: | 357 | fail: |
308 | if (armwdt_ck) | 358 | if (wdev) { |
309 | clk_put(armwdt_ck); | 359 | platform_set_drvdata(pdev, NULL); |
310 | if (mpu_wdt_ick) | 360 | if (wdev->armwdt_ck) |
311 | clk_put(mpu_wdt_ick); | 361 | clk_put(wdev->armwdt_ck); |
312 | if (mpu_wdt_fck) | 362 | if (wdev->mpu_wdt_ick) |
313 | clk_put(mpu_wdt_fck); | 363 | clk_put(wdev->mpu_wdt_ick); |
314 | release_resource(mem); | 364 | if (wdev->mpu_wdt_fck) |
365 | clk_put(wdev->mpu_wdt_fck); | ||
366 | kfree(wdev); | ||
367 | } | ||
368 | if (mem) { | ||
369 | release_mem_region(res->start, res->end - res->start + 1); | ||
370 | } | ||
315 | return ret; | 371 | return ret; |
316 | } | 372 | } |
317 | 373 | ||
318 | static void omap_wdt_shutdown(struct platform_device *pdev) | 374 | static void omap_wdt_shutdown(struct platform_device *pdev) |
319 | { | 375 | { |
320 | omap_wdt_disable(); | 376 | struct omap_wdt_dev *wdev; |
377 | wdev = platform_get_drvdata(pdev); | ||
378 | |||
379 | if (wdev->omap_wdt_users) | ||
380 | omap_wdt_disable(wdev); | ||
321 | } | 381 | } |
322 | 382 | ||
323 | static int omap_wdt_remove(struct platform_device *pdev) | 383 | static int omap_wdt_remove(struct platform_device *pdev) |
324 | { | 384 | { |
325 | struct resource *mem = platform_get_drvdata(pdev); | 385 | struct omap_wdt_dev *wdev; |
326 | misc_deregister(&omap_wdt_miscdev); | 386 | wdev = platform_get_drvdata(pdev); |
327 | release_resource(mem); | 387 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
328 | if (armwdt_ck) | 388 | |
329 | clk_put(armwdt_ck); | 389 | if (!res) |
330 | if (mpu_wdt_ick) | 390 | return -ENOENT; |
331 | clk_put(mpu_wdt_ick); | 391 | |
332 | if (mpu_wdt_fck) | 392 | misc_deregister(&(wdev->omap_wdt_miscdev)); |
333 | clk_put(mpu_wdt_fck); | 393 | release_mem_region(res->start, res->end - res->start + 1); |
394 | platform_set_drvdata(pdev, NULL); | ||
395 | if (wdev->armwdt_ck) { | ||
396 | clk_put(wdev->armwdt_ck); | ||
397 | wdev->armwdt_ck = NULL; | ||
398 | } | ||
399 | if (wdev->mpu_wdt_ick) { | ||
400 | clk_put(wdev->mpu_wdt_ick); | ||
401 | wdev->mpu_wdt_ick = NULL; | ||
402 | } | ||
403 | if (wdev->mpu_wdt_fck) { | ||
404 | clk_put(wdev->mpu_wdt_fck); | ||
405 | wdev->mpu_wdt_fck = NULL; | ||
406 | } | ||
407 | kfree(wdev); | ||
408 | omap_wdt_dev = NULL; | ||
334 | return 0; | 409 | return 0; |
335 | } | 410 | } |
336 | 411 | ||
@@ -344,16 +419,20 @@ static int omap_wdt_remove(struct platform_device *pdev) | |||
344 | 419 | ||
345 | static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) | 420 | static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) |
346 | { | 421 | { |
347 | if (omap_wdt_users) | 422 | struct omap_wdt_dev *wdev; |
348 | omap_wdt_disable(); | 423 | wdev = platform_get_drvdata(pdev); |
424 | if (wdev->omap_wdt_users) | ||
425 | omap_wdt_disable(wdev); | ||
349 | return 0; | 426 | return 0; |
350 | } | 427 | } |
351 | 428 | ||
352 | static int omap_wdt_resume(struct platform_device *pdev) | 429 | static int omap_wdt_resume(struct platform_device *pdev) |
353 | { | 430 | { |
354 | if (omap_wdt_users) { | 431 | struct omap_wdt_dev *wdev; |
355 | omap_wdt_enable(); | 432 | wdev = platform_get_drvdata(pdev); |
356 | omap_wdt_ping(); | 433 | if (wdev->omap_wdt_users) { |
434 | omap_wdt_enable(wdev); | ||
435 | omap_wdt_ping(wdev); | ||
357 | } | 436 | } |
358 | return 0; | 437 | return 0; |
359 | } | 438 | } |
diff --git a/drivers/watchdog/omap_wdt.h b/drivers/watchdog/omap_wdt.h index 52a532a5114a..fc02ec6a0386 100644 --- a/drivers/watchdog/omap_wdt.h +++ b/drivers/watchdog/omap_wdt.h | |||
@@ -30,25 +30,15 @@ | |||
30 | #ifndef _OMAP_WATCHDOG_H | 30 | #ifndef _OMAP_WATCHDOG_H |
31 | #define _OMAP_WATCHDOG_H | 31 | #define _OMAP_WATCHDOG_H |
32 | 32 | ||
33 | #define OMAP1610_WATCHDOG_BASE 0xfffeb000 | 33 | #define OMAP_WATCHDOG_REV (0x00) |
34 | #define OMAP2420_WATCHDOG_BASE 0x48022000 /*WDT Timer 2 */ | 34 | #define OMAP_WATCHDOG_SYS_CONFIG (0x10) |
35 | 35 | #define OMAP_WATCHDOG_STATUS (0x14) | |
36 | #ifdef CONFIG_ARCH_OMAP24XX | 36 | #define OMAP_WATCHDOG_CNTRL (0x24) |
37 | #define OMAP_WATCHDOG_BASE OMAP2420_WATCHDOG_BASE | 37 | #define OMAP_WATCHDOG_CRR (0x28) |
38 | #else | 38 | #define OMAP_WATCHDOG_LDR (0x2c) |
39 | #define OMAP_WATCHDOG_BASE OMAP1610_WATCHDOG_BASE | 39 | #define OMAP_WATCHDOG_TGR (0x30) |
40 | #define RM_RSTST_WKUP 0 | 40 | #define OMAP_WATCHDOG_WPS (0x34) |
41 | #endif | 41 | #define OMAP_WATCHDOG_SPR (0x48) |
42 | |||
43 | #define OMAP_WATCHDOG_REV (OMAP_WATCHDOG_BASE + 0x00) | ||
44 | #define OMAP_WATCHDOG_SYS_CONFIG (OMAP_WATCHDOG_BASE + 0x10) | ||
45 | #define OMAP_WATCHDOG_STATUS (OMAP_WATCHDOG_BASE + 0x14) | ||
46 | #define OMAP_WATCHDOG_CNTRL (OMAP_WATCHDOG_BASE + 0x24) | ||
47 | #define OMAP_WATCHDOG_CRR (OMAP_WATCHDOG_BASE + 0x28) | ||
48 | #define OMAP_WATCHDOG_LDR (OMAP_WATCHDOG_BASE + 0x2c) | ||
49 | #define OMAP_WATCHDOG_TGR (OMAP_WATCHDOG_BASE + 0x30) | ||
50 | #define OMAP_WATCHDOG_WPS (OMAP_WATCHDOG_BASE + 0x34) | ||
51 | #define OMAP_WATCHDOG_SPR (OMAP_WATCHDOG_BASE + 0x48) | ||
52 | 42 | ||
53 | /* Using the prescaler, the OMAP watchdog could go for many | 43 | /* Using the prescaler, the OMAP watchdog could go for many |
54 | * months before firing. These limits work without scaling, | 44 | * months before firing. These limits work without scaling, |