diff options
author | Daniel Lezcano <daniel.lezcano@linaro.org> | 2016-06-06 17:28:01 -0400 |
---|---|---|
committer | Daniel Lezcano <daniel.lezcano@linaro.org> | 2016-06-28 04:19:30 -0400 |
commit | 2ef2538bc613af45baf9f2a032c9a8259c4c6672 (patch) | |
tree | f3f7068ae8b1f65c288b345a84626582a2049451 | |
parent | 53186505802c8845d5af4ed40ddb84e221acb92f (diff) |
clocksource/drivers/sp804: Convert init function to return error
The init functions do not return any error. They behave as the following:
- panic, thus leading to a kernel crash while another timer may work and
make the system boot up correctly
or
- print an error and let the caller unaware if the state of the system
Change that by converting the init functions to return an error conforming
to the CLOCKSOURCE_OF_RET prototype.
Proper error handling (rollback, errno value) will be changed later case
by case, thus this change just return back an error or success in the init
function.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
-rw-r--r-- | drivers/clocksource/timer-sp804.c | 90 | ||||
-rw-r--r-- | include/clocksource/timer-sp804.h | 8 |
2 files changed, 63 insertions, 35 deletions
diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c index 5f45b9adef60..3dc47efc9298 100644 --- a/drivers/clocksource/timer-sp804.c +++ b/drivers/clocksource/timer-sp804.c | |||
@@ -77,7 +77,7 @@ void __init sp804_timer_disable(void __iomem *base) | |||
77 | writel(0, base + TIMER_CTRL); | 77 | writel(0, base + TIMER_CTRL); |
78 | } | 78 | } |
79 | 79 | ||
80 | void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base, | 80 | int __init __sp804_clocksource_and_sched_clock_init(void __iomem *base, |
81 | const char *name, | 81 | const char *name, |
82 | struct clk *clk, | 82 | struct clk *clk, |
83 | int use_sched_clock) | 83 | int use_sched_clock) |
@@ -89,14 +89,13 @@ void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base, | |||
89 | if (IS_ERR(clk)) { | 89 | if (IS_ERR(clk)) { |
90 | pr_err("sp804: clock not found: %d\n", | 90 | pr_err("sp804: clock not found: %d\n", |
91 | (int)PTR_ERR(clk)); | 91 | (int)PTR_ERR(clk)); |
92 | return; | 92 | return PTR_ERR(clk); |
93 | } | 93 | } |
94 | } | 94 | } |
95 | 95 | ||
96 | rate = sp804_get_clock_rate(clk); | 96 | rate = sp804_get_clock_rate(clk); |
97 | |||
98 | if (rate < 0) | 97 | if (rate < 0) |
99 | return; | 98 | return -EINVAL; |
100 | 99 | ||
101 | /* setup timer 0 as free-running clocksource */ | 100 | /* setup timer 0 as free-running clocksource */ |
102 | writel(0, base + TIMER_CTRL); | 101 | writel(0, base + TIMER_CTRL); |
@@ -112,6 +111,8 @@ void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base, | |||
112 | sched_clock_base = base; | 111 | sched_clock_base = base; |
113 | sched_clock_register(sp804_read, 32, rate); | 112 | sched_clock_register(sp804_read, 32, rate); |
114 | } | 113 | } |
114 | |||
115 | return 0; | ||
115 | } | 116 | } |
116 | 117 | ||
117 | 118 | ||
@@ -186,7 +187,7 @@ static struct irqaction sp804_timer_irq = { | |||
186 | .dev_id = &sp804_clockevent, | 187 | .dev_id = &sp804_clockevent, |
187 | }; | 188 | }; |
188 | 189 | ||
189 | void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struct clk *clk, const char *name) | 190 | int __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struct clk *clk, const char *name) |
190 | { | 191 | { |
191 | struct clock_event_device *evt = &sp804_clockevent; | 192 | struct clock_event_device *evt = &sp804_clockevent; |
192 | long rate; | 193 | long rate; |
@@ -196,12 +197,12 @@ void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struc | |||
196 | if (IS_ERR(clk)) { | 197 | if (IS_ERR(clk)) { |
197 | pr_err("sp804: %s clock not found: %d\n", name, | 198 | pr_err("sp804: %s clock not found: %d\n", name, |
198 | (int)PTR_ERR(clk)); | 199 | (int)PTR_ERR(clk)); |
199 | return; | 200 | return PTR_ERR(clk); |
200 | } | 201 | } |
201 | 202 | ||
202 | rate = sp804_get_clock_rate(clk); | 203 | rate = sp804_get_clock_rate(clk); |
203 | if (rate < 0) | 204 | if (rate < 0) |
204 | return; | 205 | return -EINVAL; |
205 | 206 | ||
206 | clkevt_base = base; | 207 | clkevt_base = base; |
207 | clkevt_reload = DIV_ROUND_CLOSEST(rate, HZ); | 208 | clkevt_reload = DIV_ROUND_CLOSEST(rate, HZ); |
@@ -213,27 +214,31 @@ void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struc | |||
213 | 214 | ||
214 | setup_irq(irq, &sp804_timer_irq); | 215 | setup_irq(irq, &sp804_timer_irq); |
215 | clockevents_config_and_register(evt, rate, 0xf, 0xffffffff); | 216 | clockevents_config_and_register(evt, rate, 0xf, 0xffffffff); |
217 | |||
218 | return 0; | ||
216 | } | 219 | } |
217 | 220 | ||
218 | static void __init sp804_of_init(struct device_node *np) | 221 | static int __init sp804_of_init(struct device_node *np) |
219 | { | 222 | { |
220 | static bool initialized = false; | 223 | static bool initialized = false; |
221 | void __iomem *base; | 224 | void __iomem *base; |
222 | int irq; | 225 | int irq, ret = -EINVAL; |
223 | u32 irq_num = 0; | 226 | u32 irq_num = 0; |
224 | struct clk *clk1, *clk2; | 227 | struct clk *clk1, *clk2; |
225 | const char *name = of_get_property(np, "compatible", NULL); | 228 | const char *name = of_get_property(np, "compatible", NULL); |
226 | 229 | ||
227 | base = of_iomap(np, 0); | 230 | base = of_iomap(np, 0); |
228 | if (WARN_ON(!base)) | 231 | if (!base) |
229 | return; | 232 | return -ENXIO; |
230 | 233 | ||
231 | /* Ensure timers are disabled */ | 234 | /* Ensure timers are disabled */ |
232 | writel(0, base + TIMER_CTRL); | 235 | writel(0, base + TIMER_CTRL); |
233 | writel(0, base + TIMER_2_BASE + TIMER_CTRL); | 236 | writel(0, base + TIMER_2_BASE + TIMER_CTRL); |
234 | 237 | ||
235 | if (initialized || !of_device_is_available(np)) | 238 | if (initialized || !of_device_is_available(np)) { |
239 | ret = -EINVAL; | ||
236 | goto err; | 240 | goto err; |
241 | } | ||
237 | 242 | ||
238 | clk1 = of_clk_get(np, 0); | 243 | clk1 = of_clk_get(np, 0); |
239 | if (IS_ERR(clk1)) | 244 | if (IS_ERR(clk1)) |
@@ -256,35 +261,53 @@ static void __init sp804_of_init(struct device_node *np) | |||
256 | 261 | ||
257 | of_property_read_u32(np, "arm,sp804-has-irq", &irq_num); | 262 | of_property_read_u32(np, "arm,sp804-has-irq", &irq_num); |
258 | if (irq_num == 2) { | 263 | if (irq_num == 2) { |
259 | __sp804_clockevents_init(base + TIMER_2_BASE, irq, clk2, name); | 264 | |
260 | __sp804_clocksource_and_sched_clock_init(base, name, clk1, 1); | 265 | ret = __sp804_clockevents_init(base + TIMER_2_BASE, irq, clk2, name); |
266 | if (ret) | ||
267 | goto err; | ||
268 | |||
269 | ret = __sp804_clocksource_and_sched_clock_init(base, name, clk1, 1); | ||
270 | if (ret) | ||
271 | goto err; | ||
261 | } else { | 272 | } else { |
262 | __sp804_clockevents_init(base, irq, clk1 , name); | 273 | |
263 | __sp804_clocksource_and_sched_clock_init(base + TIMER_2_BASE, | 274 | ret = __sp804_clockevents_init(base, irq, clk1 , name); |
264 | name, clk2, 1); | 275 | if (ret) |
276 | goto err; | ||
277 | |||
278 | ret =__sp804_clocksource_and_sched_clock_init(base + TIMER_2_BASE, | ||
279 | name, clk2, 1); | ||
280 | if (ret) | ||
281 | goto err; | ||
265 | } | 282 | } |
266 | initialized = true; | 283 | initialized = true; |
267 | 284 | ||
268 | return; | 285 | return 0; |
269 | err: | 286 | err: |
270 | iounmap(base); | 287 | iounmap(base); |
288 | return ret; | ||
271 | } | 289 | } |
272 | CLOCKSOURCE_OF_DECLARE(sp804, "arm,sp804", sp804_of_init); | 290 | CLOCKSOURCE_OF_DECLARE_RET(sp804, "arm,sp804", sp804_of_init); |
273 | 291 | ||
274 | static void __init integrator_cp_of_init(struct device_node *np) | 292 | static int __init integrator_cp_of_init(struct device_node *np) |
275 | { | 293 | { |
276 | static int init_count = 0; | 294 | static int init_count = 0; |
277 | void __iomem *base; | 295 | void __iomem *base; |
278 | int irq; | 296 | int irq, ret = -EINVAL; |
279 | const char *name = of_get_property(np, "compatible", NULL); | 297 | const char *name = of_get_property(np, "compatible", NULL); |
280 | struct clk *clk; | 298 | struct clk *clk; |
281 | 299 | ||
282 | base = of_iomap(np, 0); | 300 | base = of_iomap(np, 0); |
283 | if (WARN_ON(!base)) | 301 | if (!base) { |
284 | return; | 302 | pr_err("Failed to iomap"); |
303 | return -ENXIO; | ||
304 | } | ||
305 | |||
285 | clk = of_clk_get(np, 0); | 306 | clk = of_clk_get(np, 0); |
286 | if (WARN_ON(IS_ERR(clk))) | 307 | if (IS_ERR(clk)) { |
287 | return; | 308 | pr_err("Failed to get clock"); |
309 | return PTR_ERR(clk); | ||
310 | } | ||
288 | 311 | ||
289 | /* Ensure timer is disabled */ | 312 | /* Ensure timer is disabled */ |
290 | writel(0, base + TIMER_CTRL); | 313 | writel(0, base + TIMER_CTRL); |
@@ -292,19 +315,24 @@ static void __init integrator_cp_of_init(struct device_node *np) | |||
292 | if (init_count == 2 || !of_device_is_available(np)) | 315 | if (init_count == 2 || !of_device_is_available(np)) |
293 | goto err; | 316 | goto err; |
294 | 317 | ||
295 | if (!init_count) | 318 | if (!init_count) { |
296 | __sp804_clocksource_and_sched_clock_init(base, name, clk, 0); | 319 | ret = __sp804_clocksource_and_sched_clock_init(base, name, clk, 0); |
297 | else { | 320 | if (ret) |
321 | goto err; | ||
322 | } else { | ||
298 | irq = irq_of_parse_and_map(np, 0); | 323 | irq = irq_of_parse_and_map(np, 0); |
299 | if (irq <= 0) | 324 | if (irq <= 0) |
300 | goto err; | 325 | goto err; |
301 | 326 | ||
302 | __sp804_clockevents_init(base, irq, clk, name); | 327 | ret = __sp804_clockevents_init(base, irq, clk, name); |
328 | if (ret) | ||
329 | goto err; | ||
303 | } | 330 | } |
304 | 331 | ||
305 | init_count++; | 332 | init_count++; |
306 | return; | 333 | return 0; |
307 | err: | 334 | err: |
308 | iounmap(base); | 335 | iounmap(base); |
336 | return ret; | ||
309 | } | 337 | } |
310 | CLOCKSOURCE_OF_DECLARE(intcp, "arm,integrator-cp-timer", integrator_cp_of_init); | 338 | CLOCKSOURCE_OF_DECLARE_RET(intcp, "arm,integrator-cp-timer", integrator_cp_of_init); |
diff --git a/include/clocksource/timer-sp804.h b/include/clocksource/timer-sp804.h index 1f8a1caa7cb4..7654d71243dd 100644 --- a/include/clocksource/timer-sp804.h +++ b/include/clocksource/timer-sp804.h | |||
@@ -3,10 +3,10 @@ | |||
3 | 3 | ||
4 | struct clk; | 4 | struct clk; |
5 | 5 | ||
6 | void __sp804_clocksource_and_sched_clock_init(void __iomem *, | 6 | int __sp804_clocksource_and_sched_clock_init(void __iomem *, |
7 | const char *, struct clk *, int); | 7 | const char *, struct clk *, int); |
8 | void __sp804_clockevents_init(void __iomem *, unsigned int, | 8 | int __sp804_clockevents_init(void __iomem *, unsigned int, |
9 | struct clk *, const char *); | 9 | struct clk *, const char *); |
10 | void sp804_timer_disable(void __iomem *); | 10 | void sp804_timer_disable(void __iomem *); |
11 | 11 | ||
12 | static inline void sp804_clocksource_init(void __iomem *base, const char *name) | 12 | static inline void sp804_clocksource_init(void __iomem *base, const char *name) |