diff options
author | Jonathan McDowell <noodles@earth.li> | 2011-04-14 15:02:39 -0400 |
---|---|---|
committer | Wim Van Sebroeck <wim@iguana.be> | 2011-07-22 04:56:41 -0400 |
commit | 7ccdb9467bbb10d4afd87770f5eaeccd08551a46 (patch) | |
tree | 13ee0972f50ff5412205588d3b559ce997e7873b /drivers/watchdog/pc87413_wdt.c | |
parent | 97b08a62219d98a2bb9094e321b4ee7ccb41aa63 (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.c | 96 |
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 | ||
58 | static int io = IO_DEFAULT; | 58 | static int io = IO_DEFAULT; |
59 | static int swc_base_addr = -1; | ||
59 | 60 | ||
60 | static int timeout = DEFAULT_TIMEOUT; /* timeout value */ | 61 | static int timeout = DEFAULT_TIMEOUT; /* timeout value */ |
61 | static unsigned long timer_enabled; /* is the timer enabled? */ | 62 | static 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 | ||
119 | static inline unsigned int pc87413_get_swc_base(void) | 120 | static 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 | ||
144 | static inline void pc87413_swc_bank3(unsigned int swc_base_addr) | 143 | static 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 | ||
155 | static inline void pc87413_programm_wdto(unsigned int swc_base_addr, | 154 | static 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 | ||
167 | static inline void pc87413_enable_wden(unsigned int swc_base_addr) | 165 | static 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 */ |
177 | static inline void pc87413_enable_sw_wd_tren(unsigned int swc_base_addr) | 175 | static 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 | ||
188 | static inline void pc87413_disable_sw_wd_tren(unsigned int swc_base_addr) | 186 | static 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 | ||
199 | static inline void pc87413_enable_sw_wd_trg(unsigned int swc_base_addr) | 197 | static 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 | ||
210 | static inline void pc87413_disable_sw_wd_trg(unsigned int swc_base_addr) | 208 | static 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 | ||
223 | static void pc87413_enable(void) | 221 | static 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 | ||
243 | static void pc87413_disable(void) | 236 | static 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 | ||
262 | static void pc87413_refresh(void) | 250 | static 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 | |||
548 | misc_unreg: | ||
549 | misc_deregister(&pc87413_miscdev); | ||
550 | reboot_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 | } |