aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog/pc87413_wdt.c
diff options
context:
space:
mode:
authorJonathan McDowell <noodles@earth.li>2011-04-14 15:02:39 -0400
committerWim Van Sebroeck <wim@iguana.be>2011-07-22 04:56:41 -0400
commit7ccdb9467bbb10d4afd87770f5eaeccd08551a46 (patch)
tree13ee0972f50ff5412205588d3b559ce997e7873b /drivers/watchdog/pc87413_wdt.c
parent97b08a62219d98a2bb9094e321b4ee7ccb41aa63 (diff)
watchdog: pc87413_wdt: Cleanup pc87413 watchdog driver to use
Inspired by Nat Gurumoorthy's recent patches for cleaning up the it87 drivers to use request_muxed_region for accessing the SuperIO area on these chips, and the fact I have a GPIO driver for the pc8741x basically ready for submission, here is a patch to cleanup the pc87413 watchdog driver to use request_muxed_region for accessing the SuperIO area. It also pulls out the details about the SWC IO area on initial driver load, and properly does a request_region for that area - there's no requirement to touch the SuperIO area after doing the initial watchdog enable and IO base retrieval. While I have hardware with a pc87413 on it it is not wired in a way that allows the watchdog to reboot the machine, so I have not been able to fully test these changes - I have checked that the driver correctly initialises itself still and requests the SWC io region ok. Signed-Off-By: Jonathan McDowell <noodles@earth.li> Signed-Off-By: Wim Van Sebroeck <wim@iguana.be>
Diffstat (limited to 'drivers/watchdog/pc87413_wdt.c')
-rw-r--r--drivers/watchdog/pc87413_wdt.c96
1 files changed, 50 insertions, 46 deletions
diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c
index b7c139051575..e78d89986768 100644
--- a/drivers/watchdog/pc87413_wdt.c
+++ b/drivers/watchdog/pc87413_wdt.c
@@ -56,6 +56,7 @@
56#define IO_DEFAULT 0x2E /* Address used on Portwell Boards */ 56#define IO_DEFAULT 0x2E /* Address used on Portwell Boards */
57 57
58static int io = IO_DEFAULT; 58static int io = IO_DEFAULT;
59static int swc_base_addr = -1;
59 60
60static int timeout = DEFAULT_TIMEOUT; /* timeout value */ 61static int timeout = DEFAULT_TIMEOUT; /* timeout value */
61static unsigned long timer_enabled; /* is the timer enabled? */ 62static unsigned long timer_enabled; /* is the timer enabled? */
@@ -116,9 +117,8 @@ static inline void pc87413_enable_swc(void)
116 117
117/* Read SWC I/O base address */ 118/* Read SWC I/O base address */
118 119
119static inline unsigned int pc87413_get_swc_base(void) 120static void pc87413_get_swc_base_addr(void)
120{ 121{
121 unsigned int swc_base_addr = 0;
122 unsigned char addr_l, addr_h = 0; 122 unsigned char addr_l, addr_h = 0;
123 123
124 /* Step 3: Read SWC I/O Base Address */ 124 /* Step 3: Read SWC I/O Base Address */
@@ -136,12 +136,11 @@ static inline unsigned int pc87413_get_swc_base(void)
136 "Read SWC I/O Base Address: low %d, high %d, res %d\n", 136 "Read SWC I/O Base Address: low %d, high %d, res %d\n",
137 addr_l, addr_h, swc_base_addr); 137 addr_l, addr_h, swc_base_addr);
138#endif 138#endif
139 return swc_base_addr;
140} 139}
141 140
142/* Select Bank 3 of SWC */ 141/* Select Bank 3 of SWC */
143 142
144static inline void pc87413_swc_bank3(unsigned int swc_base_addr) 143static inline void pc87413_swc_bank3(void)
145{ 144{
146 /* Step 4: Select Bank3 of SWC */ 145 /* Step 4: Select Bank3 of SWC */
147 outb_p(inb(swc_base_addr + 0x0f) | 0x03, swc_base_addr + 0x0f); 146 outb_p(inb(swc_base_addr + 0x0f) | 0x03, swc_base_addr + 0x0f);
@@ -152,8 +151,7 @@ static inline void pc87413_swc_bank3(unsigned int swc_base_addr)
152 151
153/* Set watchdog timeout to x minutes */ 152/* Set watchdog timeout to x minutes */
154 153
155static inline void pc87413_programm_wdto(unsigned int swc_base_addr, 154static inline void pc87413_programm_wdto(char pc87413_time)
156 char pc87413_time)
157{ 155{
158 /* Step 5: Programm WDTO, Twd. */ 156 /* Step 5: Programm WDTO, Twd. */
159 outb_p(pc87413_time, swc_base_addr + WDTO); 157 outb_p(pc87413_time, swc_base_addr + WDTO);
@@ -164,7 +162,7 @@ static inline void pc87413_programm_wdto(unsigned int swc_base_addr,
164 162
165/* Enable WDEN */ 163/* Enable WDEN */
166 164
167static inline void pc87413_enable_wden(unsigned int swc_base_addr) 165static inline void pc87413_enable_wden(void)
168{ 166{
169 /* Step 6: Enable WDEN */ 167 /* Step 6: Enable WDEN */
170 outb_p(inb(swc_base_addr + WDCTL) | 0x01, swc_base_addr + WDCTL); 168 outb_p(inb(swc_base_addr + WDCTL) | 0x01, swc_base_addr + WDCTL);
@@ -174,7 +172,7 @@ static inline void pc87413_enable_wden(unsigned int swc_base_addr)
174} 172}
175 173
176/* Enable SW_WD_TREN */ 174/* Enable SW_WD_TREN */
177static inline void pc87413_enable_sw_wd_tren(unsigned int swc_base_addr) 175static inline void pc87413_enable_sw_wd_tren(void)
178{ 176{
179 /* Enable SW_WD_TREN */ 177 /* Enable SW_WD_TREN */
180 outb_p(inb(swc_base_addr + WDCFG) | 0x80, swc_base_addr + WDCFG); 178 outb_p(inb(swc_base_addr + WDCFG) | 0x80, swc_base_addr + WDCFG);
@@ -185,7 +183,7 @@ static inline void pc87413_enable_sw_wd_tren(unsigned int swc_base_addr)
185 183
186/* Disable SW_WD_TREN */ 184/* Disable SW_WD_TREN */
187 185
188static inline void pc87413_disable_sw_wd_tren(unsigned int swc_base_addr) 186static inline void pc87413_disable_sw_wd_tren(void)
189{ 187{
190 /* Disable SW_WD_TREN */ 188 /* Disable SW_WD_TREN */
191 outb_p(inb(swc_base_addr + WDCFG) & 0x7f, swc_base_addr + WDCFG); 189 outb_p(inb(swc_base_addr + WDCFG) & 0x7f, swc_base_addr + WDCFG);
@@ -196,7 +194,7 @@ static inline void pc87413_disable_sw_wd_tren(unsigned int swc_base_addr)
196 194
197/* Enable SW_WD_TRG */ 195/* Enable SW_WD_TRG */
198 196
199static inline void pc87413_enable_sw_wd_trg(unsigned int swc_base_addr) 197static inline void pc87413_enable_sw_wd_trg(void)
200{ 198{
201 /* Enable SW_WD_TRG */ 199 /* Enable SW_WD_TRG */
202 outb_p(inb(swc_base_addr + WDCTL) | 0x80, swc_base_addr + WDCTL); 200 outb_p(inb(swc_base_addr + WDCTL) | 0x80, swc_base_addr + WDCTL);
@@ -207,7 +205,7 @@ static inline void pc87413_enable_sw_wd_trg(unsigned int swc_base_addr)
207 205
208/* Disable SW_WD_TRG */ 206/* Disable SW_WD_TRG */
209 207
210static inline void pc87413_disable_sw_wd_trg(unsigned int swc_base_addr) 208static inline void pc87413_disable_sw_wd_trg(void)
211{ 209{
212 /* Disable SW_WD_TRG */ 210 /* Disable SW_WD_TRG */
213 outb_p(inb(swc_base_addr + WDCTL) & 0x7f, swc_base_addr + WDCTL); 211 outb_p(inb(swc_base_addr + WDCTL) & 0x7f, swc_base_addr + WDCTL);
@@ -222,18 +220,13 @@ static inline void pc87413_disable_sw_wd_trg(unsigned int swc_base_addr)
222 220
223static void pc87413_enable(void) 221static void pc87413_enable(void)
224{ 222{
225 unsigned int swc_base_addr;
226
227 spin_lock(&io_lock); 223 spin_lock(&io_lock);
228 224
229 pc87413_select_wdt_out(); 225 pc87413_swc_bank3();
230 pc87413_enable_swc(); 226 pc87413_programm_wdto(timeout);
231 swc_base_addr = pc87413_get_swc_base(); 227 pc87413_enable_wden();
232 pc87413_swc_bank3(swc_base_addr); 228 pc87413_enable_sw_wd_tren();
233 pc87413_programm_wdto(swc_base_addr, timeout); 229 pc87413_enable_sw_wd_trg();
234 pc87413_enable_wden(swc_base_addr);
235 pc87413_enable_sw_wd_tren(swc_base_addr);
236 pc87413_enable_sw_wd_trg(swc_base_addr);
237 230
238 spin_unlock(&io_lock); 231 spin_unlock(&io_lock);
239} 232}
@@ -242,17 +235,12 @@ static void pc87413_enable(void)
242 235
243static void pc87413_disable(void) 236static void pc87413_disable(void)
244{ 237{
245 unsigned int swc_base_addr;
246
247 spin_lock(&io_lock); 238 spin_lock(&io_lock);
248 239
249 pc87413_select_wdt_out(); 240 pc87413_swc_bank3();
250 pc87413_enable_swc(); 241 pc87413_disable_sw_wd_tren();
251 swc_base_addr = pc87413_get_swc_base(); 242 pc87413_disable_sw_wd_trg();
252 pc87413_swc_bank3(swc_base_addr); 243 pc87413_programm_wdto(0);
253 pc87413_disable_sw_wd_tren(swc_base_addr);
254 pc87413_disable_sw_wd_trg(swc_base_addr);
255 pc87413_programm_wdto(swc_base_addr, 0);
256 244
257 spin_unlock(&io_lock); 245 spin_unlock(&io_lock);
258} 246}
@@ -261,20 +249,15 @@ static void pc87413_disable(void)
261 249
262static void pc87413_refresh(void) 250static void pc87413_refresh(void)
263{ 251{
264 unsigned int swc_base_addr;
265
266 spin_lock(&io_lock); 252 spin_lock(&io_lock);
267 253
268 pc87413_select_wdt_out(); 254 pc87413_swc_bank3();
269 pc87413_enable_swc(); 255 pc87413_disable_sw_wd_tren();
270 swc_base_addr = pc87413_get_swc_base(); 256 pc87413_disable_sw_wd_trg();
271 pc87413_swc_bank3(swc_base_addr); 257 pc87413_programm_wdto(timeout);
272 pc87413_disable_sw_wd_tren(swc_base_addr); 258 pc87413_enable_wden();
273 pc87413_disable_sw_wd_trg(swc_base_addr); 259 pc87413_enable_sw_wd_tren();
274 pc87413_programm_wdto(swc_base_addr, timeout); 260 pc87413_enable_sw_wd_trg();
275 pc87413_enable_wden(swc_base_addr);
276 pc87413_enable_sw_wd_tren(swc_base_addr);
277 pc87413_enable_sw_wd_trg(swc_base_addr);
278 261
279 spin_unlock(&io_lock); 262 spin_unlock(&io_lock);
280} 263}
@@ -528,7 +511,8 @@ static int __init pc87413_init(void)
528 printk(KERN_INFO PFX "Version " VERSION " at io 0x%X\n", 511 printk(KERN_INFO PFX "Version " VERSION " at io 0x%X\n",
529 WDT_INDEX_IO_PORT); 512 WDT_INDEX_IO_PORT);
530 513
531 /* request_region(io, 2, "pc87413"); */ 514 if (!request_muxed_region(io, 2, MODNAME))
515 return -EBUSY;
532 516
533 ret = register_reboot_notifier(&pc87413_notifier); 517 ret = register_reboot_notifier(&pc87413_notifier);
534 if (ret != 0) { 518 if (ret != 0) {
@@ -541,12 +525,32 @@ static int __init pc87413_init(void)
541 printk(KERN_ERR PFX 525 printk(KERN_ERR PFX
542 "cannot register miscdev on minor=%d (err=%d)\n", 526 "cannot register miscdev on minor=%d (err=%d)\n",
543 WATCHDOG_MINOR, ret); 527 WATCHDOG_MINOR, ret);
544 unregister_reboot_notifier(&pc87413_notifier); 528 goto reboot_unreg;
545 return ret;
546 } 529 }
547 printk(KERN_INFO PFX "initialized. timeout=%d min \n", timeout); 530 printk(KERN_INFO PFX "initialized. timeout=%d min \n", timeout);
531
532 pc87413_select_wdt_out();
533 pc87413_enable_swc();
534 pc87413_get_swc_base_addr();
535
536 if (!request_region(swc_base_addr, 0x20, MODNAME)) {
537 printk(KERN_ERR PFX
538 "cannot request SWC region at 0x%x\n", swc_base_addr);
539 ret = -EBUSY;
540 goto misc_unreg;
541 }
542
548 pc87413_enable(); 543 pc87413_enable();
544
545 release_region(io, 2);
549 return 0; 546 return 0;
547
548misc_unreg:
549 misc_deregister(&pc87413_miscdev);
550reboot_unreg:
551 unregister_reboot_notifier(&pc87413_notifier);
552 release_region(io, 2);
553 return ret;
550} 554}
551 555
552/** 556/**
@@ -569,7 +573,7 @@ static void __exit pc87413_exit(void)
569 573
570 misc_deregister(&pc87413_miscdev); 574 misc_deregister(&pc87413_miscdev);
571 unregister_reboot_notifier(&pc87413_notifier); 575 unregister_reboot_notifier(&pc87413_notifier);
572 /* release_region(io, 2); */ 576 release_region(swc_base_addr, 0x20);
573 577
574 printk(KERN_INFO MODNAME " watchdog component driver removed.\n"); 578 printk(KERN_INFO MODNAME " watchdog component driver removed.\n");
575} 579}