diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-12 11:45:53 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-12 11:45:53 -0400 |
commit | 24ba40588fe50adce2a99e026fc0026872ebeb85 (patch) | |
tree | 20f940860987d0e84588b9681bce6a2564764fea /drivers/watchdog | |
parent | b9b42eeb88d36cc7400925302f1587aaaa348905 (diff) | |
parent | bd5cc119ef6bbe8ad64a303542c436c7a82498b7 (diff) |
Merge git://www.linux-watchdog.org/linux-watchdog
Pull watchdog updates from Wim Van Sebroeck:
- New watchdog driver for Allwinner A10/A13
- some devm_ioremap_resource simplifications
- a s3c2410_wdt change that removes the global variables
* git://www.linux-watchdog.org/linux-watchdog:
watchdog: s3c2410_wdt: simplify use of devm_ioremap_resource
watchdog: simplify platform_get_resource_byname/devm_ioremap_resource
watchdog: ts72xx_wdt: simplify use of devm_ioremap_resource
watchdog: nuc900_wdt.c: simplify use of devm_ioremap_resource
watchdog: sunxi: New watchdog driver for Allwinner A10/A13
watchdog: s3c2410_wdt: remove the global variables
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/Kconfig | 10 | ||||
-rw-r--r-- | drivers/watchdog/Makefile | 1 | ||||
-rw-r--r-- | drivers/watchdog/ar7_wdt.c | 5 | ||||
-rw-r--r-- | drivers/watchdog/nuc900_wdt.c | 5 | ||||
-rw-r--r-- | drivers/watchdog/s3c2410_wdt.c | 228 | ||||
-rw-r--r-- | drivers/watchdog/sunxi_wdt.c | 237 | ||||
-rw-r--r-- | drivers/watchdog/ts72xx_wdt.c | 10 |
7 files changed, 377 insertions, 119 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 362085d7ad8f..d1d53f301de7 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
@@ -290,6 +290,16 @@ config ORION_WATCHDOG | |||
290 | To compile this driver as a module, choose M here: the | 290 | To compile this driver as a module, choose M here: the |
291 | module will be called orion_wdt. | 291 | module will be called orion_wdt. |
292 | 292 | ||
293 | config SUNXI_WATCHDOG | ||
294 | tristate "Allwinner SoCs watchdog support" | ||
295 | depends on ARCH_SUNXI | ||
296 | select WATCHDOG_CORE | ||
297 | help | ||
298 | Say Y here to include support for the watchdog timer | ||
299 | in Allwinner SoCs. | ||
300 | To compile this driver as a module, choose M here: the | ||
301 | module will be called sunxi_wdt. | ||
302 | |||
293 | config COH901327_WATCHDOG | 303 | config COH901327_WATCHDOG |
294 | bool "ST-Ericsson COH 901 327 watchdog" | 304 | bool "ST-Ericsson COH 901 327 watchdog" |
295 | depends on ARCH_U300 | 305 | depends on ARCH_U300 |
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 2f26a0b47ddc..6c5bb274d3cd 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile | |||
@@ -46,6 +46,7 @@ obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o | |||
46 | obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o | 46 | obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o |
47 | obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o | 47 | obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o |
48 | obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o | 48 | obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o |
49 | obj-$(CONFIG_SUNXI_WATCHDOG) += sunxi_wdt.o | ||
49 | obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o | 50 | obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o |
50 | obj-$(CONFIG_STMP3XXX_RTC_WATCHDOG) += stmp3xxx_rtc_wdt.o | 51 | obj-$(CONFIG_STMP3XXX_RTC_WATCHDOG) += stmp3xxx_rtc_wdt.o |
51 | obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o | 52 | obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o |
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c index 2f3cc8fb471a..b3709f9cf5be 100644 --- a/drivers/watchdog/ar7_wdt.c +++ b/drivers/watchdog/ar7_wdt.c | |||
@@ -280,11 +280,6 @@ static int ar7_wdt_probe(struct platform_device *pdev) | |||
280 | 280 | ||
281 | ar7_regs_wdt = | 281 | ar7_regs_wdt = |
282 | platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); | 282 | platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); |
283 | if (!ar7_regs_wdt) { | ||
284 | pr_err("could not get registers resource\n"); | ||
285 | return -ENODEV; | ||
286 | } | ||
287 | |||
288 | ar7_wdt = devm_ioremap_resource(&pdev->dev, ar7_regs_wdt); | 283 | ar7_wdt = devm_ioremap_resource(&pdev->dev, ar7_regs_wdt); |
289 | if (IS_ERR(ar7_wdt)) | 284 | if (IS_ERR(ar7_wdt)) |
290 | return PTR_ERR(ar7_wdt); | 285 | return PTR_ERR(ar7_wdt); |
diff --git a/drivers/watchdog/nuc900_wdt.c b/drivers/watchdog/nuc900_wdt.c index e2b6d2cf5c9d..b15b6efd91a1 100644 --- a/drivers/watchdog/nuc900_wdt.c +++ b/drivers/watchdog/nuc900_wdt.c | |||
@@ -256,11 +256,6 @@ static int nuc900wdt_probe(struct platform_device *pdev) | |||
256 | spin_lock_init(&nuc900_wdt->wdt_lock); | 256 | spin_lock_init(&nuc900_wdt->wdt_lock); |
257 | 257 | ||
258 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 258 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
259 | if (res == NULL) { | ||
260 | dev_err(&pdev->dev, "no memory resource specified\n"); | ||
261 | return -ENOENT; | ||
262 | } | ||
263 | |||
264 | nuc900_wdt->wdt_base = devm_ioremap_resource(&pdev->dev, res); | 259 | nuc900_wdt->wdt_base = devm_ioremap_resource(&pdev->dev, res); |
265 | if (IS_ERR(nuc900_wdt->wdt_base)) | 260 | if (IS_ERR(nuc900_wdt->wdt_base)) |
266 | return PTR_ERR(nuc900_wdt->wdt_base); | 261 | return PTR_ERR(nuc900_wdt->wdt_base); |
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 6a22cf5d35bd..23aad7c6bf5d 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c | |||
@@ -84,13 +84,17 @@ MODULE_PARM_DESC(soft_noboot, "Watchdog action, set to 1 to ignore reboots, " | |||
84 | "0 to reboot (default 0)"); | 84 | "0 to reboot (default 0)"); |
85 | MODULE_PARM_DESC(debug, "Watchdog debug, set to >1 for debug (default 0)"); | 85 | MODULE_PARM_DESC(debug, "Watchdog debug, set to >1 for debug (default 0)"); |
86 | 86 | ||
87 | static struct device *wdt_dev; /* platform device attached to */ | 87 | struct s3c2410_wdt { |
88 | static struct resource *wdt_mem; | 88 | struct device *dev; |
89 | static struct resource *wdt_irq; | 89 | struct clk *clock; |
90 | static struct clk *wdt_clock; | 90 | void __iomem *reg_base; |
91 | static void __iomem *wdt_base; | 91 | unsigned int count; |
92 | static unsigned int wdt_count; | 92 | spinlock_t lock; |
93 | static DEFINE_SPINLOCK(wdt_lock); | 93 | unsigned long wtcon_save; |
94 | unsigned long wtdat_save; | ||
95 | struct watchdog_device wdt_device; | ||
96 | struct notifier_block freq_transition; | ||
97 | }; | ||
94 | 98 | ||
95 | /* watchdog control routines */ | 99 | /* watchdog control routines */ |
96 | 100 | ||
@@ -102,29 +106,38 @@ do { \ | |||
102 | 106 | ||
103 | /* functions */ | 107 | /* functions */ |
104 | 108 | ||
109 | static inline struct s3c2410_wdt *freq_to_wdt(struct notifier_block *nb) | ||
110 | { | ||
111 | return container_of(nb, struct s3c2410_wdt, freq_transition); | ||
112 | } | ||
113 | |||
105 | static int s3c2410wdt_keepalive(struct watchdog_device *wdd) | 114 | static int s3c2410wdt_keepalive(struct watchdog_device *wdd) |
106 | { | 115 | { |
107 | spin_lock(&wdt_lock); | 116 | struct s3c2410_wdt *wdt = watchdog_get_drvdata(wdd); |
108 | writel(wdt_count, wdt_base + S3C2410_WTCNT); | 117 | |
109 | spin_unlock(&wdt_lock); | 118 | spin_lock(&wdt->lock); |
119 | writel(wdt->count, wdt->reg_base + S3C2410_WTCNT); | ||
120 | spin_unlock(&wdt->lock); | ||
110 | 121 | ||
111 | return 0; | 122 | return 0; |
112 | } | 123 | } |
113 | 124 | ||
114 | static void __s3c2410wdt_stop(void) | 125 | static void __s3c2410wdt_stop(struct s3c2410_wdt *wdt) |
115 | { | 126 | { |
116 | unsigned long wtcon; | 127 | unsigned long wtcon; |
117 | 128 | ||
118 | wtcon = readl(wdt_base + S3C2410_WTCON); | 129 | wtcon = readl(wdt->reg_base + S3C2410_WTCON); |
119 | wtcon &= ~(S3C2410_WTCON_ENABLE | S3C2410_WTCON_RSTEN); | 130 | wtcon &= ~(S3C2410_WTCON_ENABLE | S3C2410_WTCON_RSTEN); |
120 | writel(wtcon, wdt_base + S3C2410_WTCON); | 131 | writel(wtcon, wdt->reg_base + S3C2410_WTCON); |
121 | } | 132 | } |
122 | 133 | ||
123 | static int s3c2410wdt_stop(struct watchdog_device *wdd) | 134 | static int s3c2410wdt_stop(struct watchdog_device *wdd) |
124 | { | 135 | { |
125 | spin_lock(&wdt_lock); | 136 | struct s3c2410_wdt *wdt = watchdog_get_drvdata(wdd); |
126 | __s3c2410wdt_stop(); | 137 | |
127 | spin_unlock(&wdt_lock); | 138 | spin_lock(&wdt->lock); |
139 | __s3c2410wdt_stop(wdt); | ||
140 | spin_unlock(&wdt->lock); | ||
128 | 141 | ||
129 | return 0; | 142 | return 0; |
130 | } | 143 | } |
@@ -132,12 +145,13 @@ static int s3c2410wdt_stop(struct watchdog_device *wdd) | |||
132 | static int s3c2410wdt_start(struct watchdog_device *wdd) | 145 | static int s3c2410wdt_start(struct watchdog_device *wdd) |
133 | { | 146 | { |
134 | unsigned long wtcon; | 147 | unsigned long wtcon; |
148 | struct s3c2410_wdt *wdt = watchdog_get_drvdata(wdd); | ||
135 | 149 | ||
136 | spin_lock(&wdt_lock); | 150 | spin_lock(&wdt->lock); |
137 | 151 | ||
138 | __s3c2410wdt_stop(); | 152 | __s3c2410wdt_stop(wdt); |
139 | 153 | ||
140 | wtcon = readl(wdt_base + S3C2410_WTCON); | 154 | wtcon = readl(wdt->reg_base + S3C2410_WTCON); |
141 | wtcon |= S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128; | 155 | wtcon |= S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128; |
142 | 156 | ||
143 | if (soft_noboot) { | 157 | if (soft_noboot) { |
@@ -148,25 +162,26 @@ static int s3c2410wdt_start(struct watchdog_device *wdd) | |||
148 | wtcon |= S3C2410_WTCON_RSTEN; | 162 | wtcon |= S3C2410_WTCON_RSTEN; |
149 | } | 163 | } |
150 | 164 | ||
151 | DBG("%s: wdt_count=0x%08x, wtcon=%08lx\n", | 165 | DBG("%s: count=0x%08x, wtcon=%08lx\n", |
152 | __func__, wdt_count, wtcon); | 166 | __func__, wdt->count, wtcon); |
153 | 167 | ||
154 | writel(wdt_count, wdt_base + S3C2410_WTDAT); | 168 | writel(wdt->count, wdt->reg_base + S3C2410_WTDAT); |
155 | writel(wdt_count, wdt_base + S3C2410_WTCNT); | 169 | writel(wdt->count, wdt->reg_base + S3C2410_WTCNT); |
156 | writel(wtcon, wdt_base + S3C2410_WTCON); | 170 | writel(wtcon, wdt->reg_base + S3C2410_WTCON); |
157 | spin_unlock(&wdt_lock); | 171 | spin_unlock(&wdt->lock); |
158 | 172 | ||
159 | return 0; | 173 | return 0; |
160 | } | 174 | } |
161 | 175 | ||
162 | static inline int s3c2410wdt_is_running(void) | 176 | static inline int s3c2410wdt_is_running(struct s3c2410_wdt *wdt) |
163 | { | 177 | { |
164 | return readl(wdt_base + S3C2410_WTCON) & S3C2410_WTCON_ENABLE; | 178 | return readl(wdt->reg_base + S3C2410_WTCON) & S3C2410_WTCON_ENABLE; |
165 | } | 179 | } |
166 | 180 | ||
167 | static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd, unsigned timeout) | 181 | static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd, unsigned timeout) |
168 | { | 182 | { |
169 | unsigned long freq = clk_get_rate(wdt_clock); | 183 | struct s3c2410_wdt *wdt = watchdog_get_drvdata(wdd); |
184 | unsigned long freq = clk_get_rate(wdt->clock); | ||
170 | unsigned int count; | 185 | unsigned int count; |
171 | unsigned int divisor = 1; | 186 | unsigned int divisor = 1; |
172 | unsigned long wtcon; | 187 | unsigned long wtcon; |
@@ -192,7 +207,7 @@ static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd, unsigned timeou | |||
192 | } | 207 | } |
193 | 208 | ||
194 | if ((count / divisor) >= 0x10000) { | 209 | if ((count / divisor) >= 0x10000) { |
195 | dev_err(wdt_dev, "timeout %d too big\n", timeout); | 210 | dev_err(wdt->dev, "timeout %d too big\n", timeout); |
196 | return -EINVAL; | 211 | return -EINVAL; |
197 | } | 212 | } |
198 | } | 213 | } |
@@ -201,15 +216,15 @@ static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd, unsigned timeou | |||
201 | __func__, timeout, divisor, count, count/divisor); | 216 | __func__, timeout, divisor, count, count/divisor); |
202 | 217 | ||
203 | count /= divisor; | 218 | count /= divisor; |
204 | wdt_count = count; | 219 | wdt->count = count; |
205 | 220 | ||
206 | /* update the pre-scaler */ | 221 | /* update the pre-scaler */ |
207 | wtcon = readl(wdt_base + S3C2410_WTCON); | 222 | wtcon = readl(wdt->reg_base + S3C2410_WTCON); |
208 | wtcon &= ~S3C2410_WTCON_PRESCALE_MASK; | 223 | wtcon &= ~S3C2410_WTCON_PRESCALE_MASK; |
209 | wtcon |= S3C2410_WTCON_PRESCALE(divisor-1); | 224 | wtcon |= S3C2410_WTCON_PRESCALE(divisor-1); |
210 | 225 | ||
211 | writel(count, wdt_base + S3C2410_WTDAT); | 226 | writel(count, wdt->reg_base + S3C2410_WTDAT); |
212 | writel(wtcon, wdt_base + S3C2410_WTCON); | 227 | writel(wtcon, wdt->reg_base + S3C2410_WTCON); |
213 | 228 | ||
214 | wdd->timeout = (count * divisor) / freq; | 229 | wdd->timeout = (count * divisor) / freq; |
215 | 230 | ||
@@ -242,21 +257,23 @@ static struct watchdog_device s3c2410_wdd = { | |||
242 | 257 | ||
243 | static irqreturn_t s3c2410wdt_irq(int irqno, void *param) | 258 | static irqreturn_t s3c2410wdt_irq(int irqno, void *param) |
244 | { | 259 | { |
245 | dev_info(wdt_dev, "watchdog timer expired (irq)\n"); | 260 | struct s3c2410_wdt *wdt = platform_get_drvdata(param); |
261 | |||
262 | dev_info(wdt->dev, "watchdog timer expired (irq)\n"); | ||
246 | 263 | ||
247 | s3c2410wdt_keepalive(&s3c2410_wdd); | 264 | s3c2410wdt_keepalive(&wdt->wdt_device); |
248 | return IRQ_HANDLED; | 265 | return IRQ_HANDLED; |
249 | } | 266 | } |
250 | 267 | ||
251 | |||
252 | #ifdef CONFIG_CPU_FREQ | 268 | #ifdef CONFIG_CPU_FREQ |
253 | 269 | ||
254 | static int s3c2410wdt_cpufreq_transition(struct notifier_block *nb, | 270 | static int s3c2410wdt_cpufreq_transition(struct notifier_block *nb, |
255 | unsigned long val, void *data) | 271 | unsigned long val, void *data) |
256 | { | 272 | { |
257 | int ret; | 273 | int ret; |
274 | struct s3c2410_wdt *wdt = freq_to_wdt(nb); | ||
258 | 275 | ||
259 | if (!s3c2410wdt_is_running()) | 276 | if (!s3c2410wdt_is_running(wdt)) |
260 | goto done; | 277 | goto done; |
261 | 278 | ||
262 | if (val == CPUFREQ_PRECHANGE) { | 279 | if (val == CPUFREQ_PRECHANGE) { |
@@ -265,14 +282,15 @@ static int s3c2410wdt_cpufreq_transition(struct notifier_block *nb, | |||
265 | * the watchdog is running. | 282 | * the watchdog is running. |
266 | */ | 283 | */ |
267 | 284 | ||
268 | s3c2410wdt_keepalive(&s3c2410_wdd); | 285 | s3c2410wdt_keepalive(&wdt->wdt_device); |
269 | } else if (val == CPUFREQ_POSTCHANGE) { | 286 | } else if (val == CPUFREQ_POSTCHANGE) { |
270 | s3c2410wdt_stop(&s3c2410_wdd); | 287 | s3c2410wdt_stop(&wdt->wdt_device); |
271 | 288 | ||
272 | ret = s3c2410wdt_set_heartbeat(&s3c2410_wdd, s3c2410_wdd.timeout); | 289 | ret = s3c2410wdt_set_heartbeat(&wdt->wdt_device, |
290 | wdt->wdt_device.timeout); | ||
273 | 291 | ||
274 | if (ret >= 0) | 292 | if (ret >= 0) |
275 | s3c2410wdt_start(&s3c2410_wdd); | 293 | s3c2410wdt_start(&wdt->wdt_device); |
276 | else | 294 | else |
277 | goto err; | 295 | goto err; |
278 | } | 296 | } |
@@ -281,34 +299,35 @@ done: | |||
281 | return 0; | 299 | return 0; |
282 | 300 | ||
283 | err: | 301 | err: |
284 | dev_err(wdt_dev, "cannot set new value for timeout %d\n", | 302 | dev_err(wdt->dev, "cannot set new value for timeout %d\n", |
285 | s3c2410_wdd.timeout); | 303 | wdt->wdt_device.timeout); |
286 | return ret; | 304 | return ret; |
287 | } | 305 | } |
288 | 306 | ||
289 | static struct notifier_block s3c2410wdt_cpufreq_transition_nb = { | 307 | static inline int s3c2410wdt_cpufreq_register(struct s3c2410_wdt *wdt) |
290 | .notifier_call = s3c2410wdt_cpufreq_transition, | ||
291 | }; | ||
292 | |||
293 | static inline int s3c2410wdt_cpufreq_register(void) | ||
294 | { | 308 | { |
295 | return cpufreq_register_notifier(&s3c2410wdt_cpufreq_transition_nb, | 309 | wdt->freq_transition.notifier_call = s3c2410wdt_cpufreq_transition; |
310 | |||
311 | return cpufreq_register_notifier(&wdt->freq_transition, | ||
296 | CPUFREQ_TRANSITION_NOTIFIER); | 312 | CPUFREQ_TRANSITION_NOTIFIER); |
297 | } | 313 | } |
298 | 314 | ||
299 | static inline void s3c2410wdt_cpufreq_deregister(void) | 315 | static inline void s3c2410wdt_cpufreq_deregister(struct s3c2410_wdt *wdt) |
300 | { | 316 | { |
301 | cpufreq_unregister_notifier(&s3c2410wdt_cpufreq_transition_nb, | 317 | wdt->freq_transition.notifier_call = s3c2410wdt_cpufreq_transition; |
318 | |||
319 | cpufreq_unregister_notifier(&wdt->freq_transition, | ||
302 | CPUFREQ_TRANSITION_NOTIFIER); | 320 | CPUFREQ_TRANSITION_NOTIFIER); |
303 | } | 321 | } |
304 | 322 | ||
305 | #else | 323 | #else |
306 | static inline int s3c2410wdt_cpufreq_register(void) | 324 | |
325 | static inline int s3c2410wdt_cpufreq_register(struct s3c2410_wdt *wdt) | ||
307 | { | 326 | { |
308 | return 0; | 327 | return 0; |
309 | } | 328 | } |
310 | 329 | ||
311 | static inline void s3c2410wdt_cpufreq_deregister(void) | 330 | static inline void s3c2410wdt_cpufreq_deregister(struct s3c2410_wdt *wdt) |
312 | { | 331 | { |
313 | } | 332 | } |
314 | #endif | 333 | #endif |
@@ -316,6 +335,9 @@ static inline void s3c2410wdt_cpufreq_deregister(void) | |||
316 | static int s3c2410wdt_probe(struct platform_device *pdev) | 335 | static int s3c2410wdt_probe(struct platform_device *pdev) |
317 | { | 336 | { |
318 | struct device *dev; | 337 | struct device *dev; |
338 | struct s3c2410_wdt *wdt; | ||
339 | struct resource *wdt_mem; | ||
340 | struct resource *wdt_irq; | ||
319 | unsigned int wtcon; | 341 | unsigned int wtcon; |
320 | int started = 0; | 342 | int started = 0; |
321 | int ret; | 343 | int ret; |
@@ -323,13 +345,14 @@ static int s3c2410wdt_probe(struct platform_device *pdev) | |||
323 | DBG("%s: probe=%p\n", __func__, pdev); | 345 | DBG("%s: probe=%p\n", __func__, pdev); |
324 | 346 | ||
325 | dev = &pdev->dev; | 347 | dev = &pdev->dev; |
326 | wdt_dev = &pdev->dev; | ||
327 | 348 | ||
328 | wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 349 | wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); |
329 | if (wdt_mem == NULL) { | 350 | if (!wdt) |
330 | dev_err(dev, "no memory resource specified\n"); | 351 | return -ENOMEM; |
331 | return -ENOENT; | 352 | |
332 | } | 353 | wdt->dev = &pdev->dev; |
354 | spin_lock_init(&wdt->lock); | ||
355 | wdt->wdt_device = s3c2410_wdd; | ||
333 | 356 | ||
334 | wdt_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 357 | wdt_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
335 | if (wdt_irq == NULL) { | 358 | if (wdt_irq == NULL) { |
@@ -339,35 +362,40 @@ static int s3c2410wdt_probe(struct platform_device *pdev) | |||
339 | } | 362 | } |
340 | 363 | ||
341 | /* get the memory region for the watchdog timer */ | 364 | /* get the memory region for the watchdog timer */ |
342 | wdt_base = devm_ioremap_resource(dev, wdt_mem); | 365 | wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
343 | if (IS_ERR(wdt_base)) { | 366 | wdt->reg_base = devm_ioremap_resource(dev, wdt_mem); |
344 | ret = PTR_ERR(wdt_base); | 367 | if (IS_ERR(wdt->reg_base)) { |
368 | ret = PTR_ERR(wdt->reg_base); | ||
345 | goto err; | 369 | goto err; |
346 | } | 370 | } |
347 | 371 | ||
348 | DBG("probe: mapped wdt_base=%p\n", wdt_base); | 372 | DBG("probe: mapped reg_base=%p\n", wdt->reg_base); |
349 | 373 | ||
350 | wdt_clock = devm_clk_get(dev, "watchdog"); | 374 | wdt->clock = devm_clk_get(dev, "watchdog"); |
351 | if (IS_ERR(wdt_clock)) { | 375 | if (IS_ERR(wdt->clock)) { |
352 | dev_err(dev, "failed to find watchdog clock source\n"); | 376 | dev_err(dev, "failed to find watchdog clock source\n"); |
353 | ret = PTR_ERR(wdt_clock); | 377 | ret = PTR_ERR(wdt->clock); |
354 | goto err; | 378 | goto err; |
355 | } | 379 | } |
356 | 380 | ||
357 | clk_prepare_enable(wdt_clock); | 381 | clk_prepare_enable(wdt->clock); |
358 | 382 | ||
359 | ret = s3c2410wdt_cpufreq_register(); | 383 | ret = s3c2410wdt_cpufreq_register(wdt); |
360 | if (ret < 0) { | 384 | if (ret < 0) { |
361 | dev_err(dev, "failed to register cpufreq\n"); | 385 | dev_err(dev, "failed to register cpufreq\n"); |
362 | goto err_clk; | 386 | goto err_clk; |
363 | } | 387 | } |
364 | 388 | ||
389 | watchdog_set_drvdata(&wdt->wdt_device, wdt); | ||
390 | |||
365 | /* see if we can actually set the requested timer margin, and if | 391 | /* see if we can actually set the requested timer margin, and if |
366 | * not, try the default value */ | 392 | * not, try the default value */ |
367 | 393 | ||
368 | watchdog_init_timeout(&s3c2410_wdd, tmr_margin, &pdev->dev); | 394 | watchdog_init_timeout(&wdt->wdt_device, tmr_margin, &pdev->dev); |
369 | if (s3c2410wdt_set_heartbeat(&s3c2410_wdd, s3c2410_wdd.timeout)) { | 395 | ret = s3c2410wdt_set_heartbeat(&wdt->wdt_device, |
370 | started = s3c2410wdt_set_heartbeat(&s3c2410_wdd, | 396 | wdt->wdt_device.timeout); |
397 | if (ret) { | ||
398 | started = s3c2410wdt_set_heartbeat(&wdt->wdt_device, | ||
371 | CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME); | 399 | CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME); |
372 | 400 | ||
373 | if (started == 0) | 401 | if (started == 0) |
@@ -386,9 +414,9 @@ static int s3c2410wdt_probe(struct platform_device *pdev) | |||
386 | goto err_cpufreq; | 414 | goto err_cpufreq; |
387 | } | 415 | } |
388 | 416 | ||
389 | watchdog_set_nowayout(&s3c2410_wdd, nowayout); | 417 | watchdog_set_nowayout(&wdt->wdt_device, nowayout); |
390 | 418 | ||
391 | ret = watchdog_register_device(&s3c2410_wdd); | 419 | ret = watchdog_register_device(&wdt->wdt_device); |
392 | if (ret) { | 420 | if (ret) { |
393 | dev_err(dev, "cannot register watchdog (%d)\n", ret); | 421 | dev_err(dev, "cannot register watchdog (%d)\n", ret); |
394 | goto err_cpufreq; | 422 | goto err_cpufreq; |
@@ -396,18 +424,20 @@ static int s3c2410wdt_probe(struct platform_device *pdev) | |||
396 | 424 | ||
397 | if (tmr_atboot && started == 0) { | 425 | if (tmr_atboot && started == 0) { |
398 | dev_info(dev, "starting watchdog timer\n"); | 426 | dev_info(dev, "starting watchdog timer\n"); |
399 | s3c2410wdt_start(&s3c2410_wdd); | 427 | s3c2410wdt_start(&wdt->wdt_device); |
400 | } else if (!tmr_atboot) { | 428 | } else if (!tmr_atboot) { |
401 | /* if we're not enabling the watchdog, then ensure it is | 429 | /* if we're not enabling the watchdog, then ensure it is |
402 | * disabled if it has been left running from the bootloader | 430 | * disabled if it has been left running from the bootloader |
403 | * or other source */ | 431 | * or other source */ |
404 | 432 | ||
405 | s3c2410wdt_stop(&s3c2410_wdd); | 433 | s3c2410wdt_stop(&wdt->wdt_device); |
406 | } | 434 | } |
407 | 435 | ||
436 | platform_set_drvdata(pdev, wdt); | ||
437 | |||
408 | /* print out a statement of readiness */ | 438 | /* print out a statement of readiness */ |
409 | 439 | ||
410 | wtcon = readl(wdt_base + S3C2410_WTCON); | 440 | wtcon = readl(wdt->reg_base + S3C2410_WTCON); |
411 | 441 | ||
412 | dev_info(dev, "watchdog %sactive, reset %sabled, irq %sabled\n", | 442 | dev_info(dev, "watchdog %sactive, reset %sabled, irq %sabled\n", |
413 | (wtcon & S3C2410_WTCON_ENABLE) ? "" : "in", | 443 | (wtcon & S3C2410_WTCON_ENABLE) ? "" : "in", |
@@ -417,64 +447,64 @@ static int s3c2410wdt_probe(struct platform_device *pdev) | |||
417 | return 0; | 447 | return 0; |
418 | 448 | ||
419 | err_cpufreq: | 449 | err_cpufreq: |
420 | s3c2410wdt_cpufreq_deregister(); | 450 | s3c2410wdt_cpufreq_deregister(wdt); |
421 | 451 | ||
422 | err_clk: | 452 | err_clk: |
423 | clk_disable_unprepare(wdt_clock); | 453 | clk_disable_unprepare(wdt->clock); |
424 | wdt_clock = NULL; | 454 | wdt->clock = NULL; |
425 | 455 | ||
426 | err: | 456 | err: |
427 | wdt_irq = NULL; | ||
428 | wdt_mem = NULL; | ||
429 | return ret; | 457 | return ret; |
430 | } | 458 | } |
431 | 459 | ||
432 | static int s3c2410wdt_remove(struct platform_device *dev) | 460 | static int s3c2410wdt_remove(struct platform_device *dev) |
433 | { | 461 | { |
434 | watchdog_unregister_device(&s3c2410_wdd); | 462 | struct s3c2410_wdt *wdt = platform_get_drvdata(dev); |
435 | 463 | ||
436 | s3c2410wdt_cpufreq_deregister(); | 464 | watchdog_unregister_device(&wdt->wdt_device); |
437 | 465 | ||
438 | clk_disable_unprepare(wdt_clock); | 466 | s3c2410wdt_cpufreq_deregister(wdt); |
439 | wdt_clock = NULL; | 467 | |
468 | clk_disable_unprepare(wdt->clock); | ||
469 | wdt->clock = NULL; | ||
440 | 470 | ||
441 | wdt_irq = NULL; | ||
442 | wdt_mem = NULL; | ||
443 | return 0; | 471 | return 0; |
444 | } | 472 | } |
445 | 473 | ||
446 | static void s3c2410wdt_shutdown(struct platform_device *dev) | 474 | static void s3c2410wdt_shutdown(struct platform_device *dev) |
447 | { | 475 | { |
448 | s3c2410wdt_stop(&s3c2410_wdd); | 476 | struct s3c2410_wdt *wdt = platform_get_drvdata(dev); |
477 | |||
478 | s3c2410wdt_stop(&wdt->wdt_device); | ||
449 | } | 479 | } |
450 | 480 | ||
451 | #ifdef CONFIG_PM_SLEEP | 481 | #ifdef CONFIG_PM_SLEEP |
452 | 482 | ||
453 | static unsigned long wtcon_save; | ||
454 | static unsigned long wtdat_save; | ||
455 | |||
456 | static int s3c2410wdt_suspend(struct device *dev) | 483 | static int s3c2410wdt_suspend(struct device *dev) |
457 | { | 484 | { |
485 | struct s3c2410_wdt *wdt = dev_get_drvdata(dev); | ||
486 | |||
458 | /* Save watchdog state, and turn it off. */ | 487 | /* Save watchdog state, and turn it off. */ |
459 | wtcon_save = readl(wdt_base + S3C2410_WTCON); | 488 | wdt->wtcon_save = readl(wdt->reg_base + S3C2410_WTCON); |
460 | wtdat_save = readl(wdt_base + S3C2410_WTDAT); | 489 | wdt->wtdat_save = readl(wdt->reg_base + S3C2410_WTDAT); |
461 | 490 | ||
462 | /* Note that WTCNT doesn't need to be saved. */ | 491 | /* Note that WTCNT doesn't need to be saved. */ |
463 | s3c2410wdt_stop(&s3c2410_wdd); | 492 | s3c2410wdt_stop(&wdt->wdt_device); |
464 | 493 | ||
465 | return 0; | 494 | return 0; |
466 | } | 495 | } |
467 | 496 | ||
468 | static int s3c2410wdt_resume(struct device *dev) | 497 | static int s3c2410wdt_resume(struct device *dev) |
469 | { | 498 | { |
470 | /* Restore watchdog state. */ | 499 | struct s3c2410_wdt *wdt = dev_get_drvdata(dev); |
471 | 500 | ||
472 | writel(wtdat_save, wdt_base + S3C2410_WTDAT); | 501 | /* Restore watchdog state. */ |
473 | writel(wtdat_save, wdt_base + S3C2410_WTCNT); /* Reset count */ | 502 | writel(wdt->wtdat_save, wdt->reg_base + S3C2410_WTDAT); |
474 | writel(wtcon_save, wdt_base + S3C2410_WTCON); | 503 | writel(wdt->wtdat_save, wdt->reg_base + S3C2410_WTCNT);/* Reset count */ |
504 | writel(wdt->wtcon_save, wdt->reg_base + S3C2410_WTCON); | ||
475 | 505 | ||
476 | dev_info(dev, "watchdog %sabled\n", | 506 | dev_info(dev, "watchdog %sabled\n", |
477 | (wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis"); | 507 | (wdt->wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis"); |
478 | 508 | ||
479 | return 0; | 509 | return 0; |
480 | } | 510 | } |
diff --git a/drivers/watchdog/sunxi_wdt.c b/drivers/watchdog/sunxi_wdt.c new file mode 100644 index 000000000000..1f94b42764aa --- /dev/null +++ b/drivers/watchdog/sunxi_wdt.c | |||
@@ -0,0 +1,237 @@ | |||
1 | /* | ||
2 | * sunxi Watchdog Driver | ||
3 | * | ||
4 | * Copyright (c) 2013 Carlo Caione | ||
5 | * 2012 Henrik Nordstrom | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * Based on xen_wdt.c | ||
13 | * (c) Copyright 2010 Novell, Inc. | ||
14 | */ | ||
15 | |||
16 | #include <linux/clk.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/io.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/moduleparam.h> | ||
23 | #include <linux/of.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/types.h> | ||
26 | #include <linux/watchdog.h> | ||
27 | |||
28 | #define WDT_MAX_TIMEOUT 16 | ||
29 | #define WDT_MIN_TIMEOUT 1 | ||
30 | #define WDT_MODE_TIMEOUT(n) ((n) << 3) | ||
31 | #define WDT_TIMEOUT_MASK WDT_MODE_TIMEOUT(0x0F) | ||
32 | |||
33 | #define WDT_CTRL 0x00 | ||
34 | #define WDT_CTRL_RELOAD ((1 << 0) | (0x0a57 << 1)) | ||
35 | |||
36 | #define WDT_MODE 0x04 | ||
37 | #define WDT_MODE_EN (1 << 0) | ||
38 | #define WDT_MODE_RST_EN (1 << 1) | ||
39 | |||
40 | #define DRV_NAME "sunxi-wdt" | ||
41 | #define DRV_VERSION "1.0" | ||
42 | |||
43 | static bool nowayout = WATCHDOG_NOWAYOUT; | ||
44 | static unsigned int timeout = WDT_MAX_TIMEOUT; | ||
45 | |||
46 | struct sunxi_wdt_dev { | ||
47 | struct watchdog_device wdt_dev; | ||
48 | void __iomem *wdt_base; | ||
49 | }; | ||
50 | |||
51 | /* | ||
52 | * wdt_timeout_map maps the watchdog timer interval value in seconds to | ||
53 | * the value of the register WDT_MODE bit 3:6 | ||
54 | * | ||
55 | * [timeout seconds] = register value | ||
56 | * | ||
57 | */ | ||
58 | |||
59 | static const int wdt_timeout_map[] = { | ||
60 | [1] = 0b0001, /* 1s */ | ||
61 | [2] = 0b0010, /* 2s */ | ||
62 | [3] = 0b0011, /* 3s */ | ||
63 | [4] = 0b0100, /* 4s */ | ||
64 | [5] = 0b0101, /* 5s */ | ||
65 | [6] = 0b0110, /* 6s */ | ||
66 | [8] = 0b0111, /* 8s */ | ||
67 | [10] = 0b1000, /* 10s */ | ||
68 | [12] = 0b1001, /* 12s */ | ||
69 | [14] = 0b1010, /* 14s */ | ||
70 | [16] = 0b1011, /* 16s */ | ||
71 | }; | ||
72 | |||
73 | static int sunxi_wdt_ping(struct watchdog_device *wdt_dev) | ||
74 | { | ||
75 | struct sunxi_wdt_dev *sunxi_wdt = watchdog_get_drvdata(wdt_dev); | ||
76 | void __iomem *wdt_base = sunxi_wdt->wdt_base; | ||
77 | |||
78 | iowrite32(WDT_CTRL_RELOAD, wdt_base + WDT_CTRL); | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static int sunxi_wdt_set_timeout(struct watchdog_device *wdt_dev, | ||
84 | unsigned int timeout) | ||
85 | { | ||
86 | struct sunxi_wdt_dev *sunxi_wdt = watchdog_get_drvdata(wdt_dev); | ||
87 | void __iomem *wdt_base = sunxi_wdt->wdt_base; | ||
88 | u32 reg; | ||
89 | |||
90 | if (wdt_timeout_map[timeout] == 0) | ||
91 | timeout++; | ||
92 | |||
93 | sunxi_wdt->wdt_dev.timeout = timeout; | ||
94 | |||
95 | reg = ioread32(wdt_base + WDT_MODE); | ||
96 | reg &= ~WDT_TIMEOUT_MASK; | ||
97 | reg |= WDT_MODE_TIMEOUT(wdt_timeout_map[timeout]); | ||
98 | iowrite32(reg, wdt_base + WDT_MODE); | ||
99 | |||
100 | sunxi_wdt_ping(wdt_dev); | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static int sunxi_wdt_stop(struct watchdog_device *wdt_dev) | ||
106 | { | ||
107 | struct sunxi_wdt_dev *sunxi_wdt = watchdog_get_drvdata(wdt_dev); | ||
108 | void __iomem *wdt_base = sunxi_wdt->wdt_base; | ||
109 | |||
110 | iowrite32(0, wdt_base + WDT_MODE); | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static int sunxi_wdt_start(struct watchdog_device *wdt_dev) | ||
116 | { | ||
117 | u32 reg; | ||
118 | struct sunxi_wdt_dev *sunxi_wdt = watchdog_get_drvdata(wdt_dev); | ||
119 | void __iomem *wdt_base = sunxi_wdt->wdt_base; | ||
120 | int ret; | ||
121 | |||
122 | ret = sunxi_wdt_set_timeout(&sunxi_wdt->wdt_dev, | ||
123 | sunxi_wdt->wdt_dev.timeout); | ||
124 | if (ret < 0) | ||
125 | return ret; | ||
126 | |||
127 | reg = ioread32(wdt_base + WDT_MODE); | ||
128 | reg |= (WDT_MODE_RST_EN | WDT_MODE_EN); | ||
129 | iowrite32(reg, wdt_base + WDT_MODE); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static const struct watchdog_info sunxi_wdt_info = { | ||
135 | .identity = DRV_NAME, | ||
136 | .options = WDIOF_SETTIMEOUT | | ||
137 | WDIOF_KEEPALIVEPING | | ||
138 | WDIOF_MAGICCLOSE, | ||
139 | }; | ||
140 | |||
141 | static const struct watchdog_ops sunxi_wdt_ops = { | ||
142 | .owner = THIS_MODULE, | ||
143 | .start = sunxi_wdt_start, | ||
144 | .stop = sunxi_wdt_stop, | ||
145 | .ping = sunxi_wdt_ping, | ||
146 | .set_timeout = sunxi_wdt_set_timeout, | ||
147 | }; | ||
148 | |||
149 | static int __init sunxi_wdt_probe(struct platform_device *pdev) | ||
150 | { | ||
151 | struct sunxi_wdt_dev *sunxi_wdt; | ||
152 | struct resource *res; | ||
153 | int err; | ||
154 | |||
155 | sunxi_wdt = devm_kzalloc(&pdev->dev, sizeof(*sunxi_wdt), GFP_KERNEL); | ||
156 | if (!sunxi_wdt) | ||
157 | return -EINVAL; | ||
158 | |||
159 | platform_set_drvdata(pdev, sunxi_wdt); | ||
160 | |||
161 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
162 | sunxi_wdt->wdt_base = devm_ioremap_resource(&pdev->dev, res); | ||
163 | if (IS_ERR(sunxi_wdt->wdt_base)) | ||
164 | return PTR_ERR(sunxi_wdt->wdt_base); | ||
165 | |||
166 | sunxi_wdt->wdt_dev.info = &sunxi_wdt_info; | ||
167 | sunxi_wdt->wdt_dev.ops = &sunxi_wdt_ops; | ||
168 | sunxi_wdt->wdt_dev.timeout = WDT_MAX_TIMEOUT; | ||
169 | sunxi_wdt->wdt_dev.max_timeout = WDT_MAX_TIMEOUT; | ||
170 | sunxi_wdt->wdt_dev.min_timeout = WDT_MIN_TIMEOUT; | ||
171 | sunxi_wdt->wdt_dev.parent = &pdev->dev; | ||
172 | |||
173 | watchdog_init_timeout(&sunxi_wdt->wdt_dev, timeout, &pdev->dev); | ||
174 | watchdog_set_nowayout(&sunxi_wdt->wdt_dev, nowayout); | ||
175 | |||
176 | watchdog_set_drvdata(&sunxi_wdt->wdt_dev, sunxi_wdt); | ||
177 | |||
178 | sunxi_wdt_stop(&sunxi_wdt->wdt_dev); | ||
179 | |||
180 | err = watchdog_register_device(&sunxi_wdt->wdt_dev); | ||
181 | if (unlikely(err)) | ||
182 | return err; | ||
183 | |||
184 | dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)", | ||
185 | sunxi_wdt->wdt_dev.timeout, nowayout); | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static int __exit sunxi_wdt_remove(struct platform_device *pdev) | ||
191 | { | ||
192 | struct sunxi_wdt_dev *sunxi_wdt = platform_get_drvdata(pdev); | ||
193 | |||
194 | watchdog_unregister_device(&sunxi_wdt->wdt_dev); | ||
195 | watchdog_set_drvdata(&sunxi_wdt->wdt_dev, NULL); | ||
196 | |||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | static void sunxi_wdt_shutdown(struct platform_device *pdev) | ||
201 | { | ||
202 | struct sunxi_wdt_dev *sunxi_wdt = platform_get_drvdata(pdev); | ||
203 | |||
204 | sunxi_wdt_stop(&sunxi_wdt->wdt_dev); | ||
205 | } | ||
206 | |||
207 | static const struct of_device_id sunxi_wdt_dt_ids[] = { | ||
208 | { .compatible = "allwinner,sun4i-wdt" }, | ||
209 | { /* sentinel */ } | ||
210 | }; | ||
211 | MODULE_DEVICE_TABLE(of, sunxi_wdt_dt_ids); | ||
212 | |||
213 | static struct platform_driver sunxi_wdt_driver = { | ||
214 | .probe = sunxi_wdt_probe, | ||
215 | .remove = sunxi_wdt_remove, | ||
216 | .shutdown = sunxi_wdt_shutdown, | ||
217 | .driver = { | ||
218 | .owner = THIS_MODULE, | ||
219 | .name = DRV_NAME, | ||
220 | .of_match_table = of_match_ptr(sunxi_wdt_dt_ids) | ||
221 | }, | ||
222 | }; | ||
223 | |||
224 | module_platform_driver(sunxi_wdt_driver); | ||
225 | |||
226 | module_param(timeout, uint, 0); | ||
227 | MODULE_PARM_DESC(timeout, "Watchdog heartbeat in seconds"); | ||
228 | |||
229 | module_param(nowayout, bool, 0); | ||
230 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " | ||
231 | "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
232 | |||
233 | MODULE_LICENSE("GPL"); | ||
234 | MODULE_AUTHOR("Carlo Caione <carlo.caione@gmail.com>"); | ||
235 | MODULE_AUTHOR("Henrik Nordstrom <henrik@henriknordstrom.net>"); | ||
236 | MODULE_DESCRIPTION("sunxi WatchDog Timer Driver"); | ||
237 | MODULE_VERSION(DRV_VERSION); | ||
diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c index 4da59b4d73f0..42913f131dc2 100644 --- a/drivers/watchdog/ts72xx_wdt.c +++ b/drivers/watchdog/ts72xx_wdt.c | |||
@@ -403,21 +403,11 @@ static int ts72xx_wdt_probe(struct platform_device *pdev) | |||
403 | } | 403 | } |
404 | 404 | ||
405 | r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 405 | r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
406 | if (!r1) { | ||
407 | dev_err(&pdev->dev, "failed to get memory resource\n"); | ||
408 | return -ENODEV; | ||
409 | } | ||
410 | |||
411 | wdt->control_reg = devm_ioremap_resource(&pdev->dev, r1); | 406 | wdt->control_reg = devm_ioremap_resource(&pdev->dev, r1); |
412 | if (IS_ERR(wdt->control_reg)) | 407 | if (IS_ERR(wdt->control_reg)) |
413 | return PTR_ERR(wdt->control_reg); | 408 | return PTR_ERR(wdt->control_reg); |
414 | 409 | ||
415 | r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 410 | r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
416 | if (!r2) { | ||
417 | dev_err(&pdev->dev, "failed to get memory resource\n"); | ||
418 | return -ENODEV; | ||
419 | } | ||
420 | |||
421 | wdt->feed_reg = devm_ioremap_resource(&pdev->dev, r2); | 411 | wdt->feed_reg = devm_ioremap_resource(&pdev->dev, r2); |
422 | if (IS_ERR(wdt->feed_reg)) | 412 | if (IS_ERR(wdt->feed_reg)) |
423 | return PTR_ERR(wdt->feed_reg); | 413 | return PTR_ERR(wdt->feed_reg); |