diff options
author | Daniel Lezcano <daniel.lezcano@linaro.org> | 2016-06-06 17:27:24 -0400 |
---|---|---|
committer | Daniel Lezcano <daniel.lezcano@linaro.org> | 2016-06-28 04:19:30 -0400 |
commit | 76804d052316d3562c58934200c932243f312c07 (patch) | |
tree | 4ff74018a5aefe653bf72accfa913caf4fc1f719 | |
parent | c11cd416aea9e4f71b58def49e860ba8609a1892 (diff) |
clocksource/drivers/integrator-ap: 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-integrator-ap.c | 59 |
1 files changed, 38 insertions, 21 deletions
diff --git a/drivers/clocksource/timer-integrator-ap.c b/drivers/clocksource/timer-integrator-ap.c index 3f59ac2180dc..675faceab5d6 100644 --- a/drivers/clocksource/timer-integrator-ap.c +++ b/drivers/clocksource/timer-integrator-ap.c | |||
@@ -36,11 +36,12 @@ static u64 notrace integrator_read_sched_clock(void) | |||
36 | return -readl(sched_clk_base + TIMER_VALUE); | 36 | return -readl(sched_clk_base + TIMER_VALUE); |
37 | } | 37 | } |
38 | 38 | ||
39 | static void integrator_clocksource_init(unsigned long inrate, | 39 | static int integrator_clocksource_init(unsigned long inrate, |
40 | void __iomem *base) | 40 | void __iomem *base) |
41 | { | 41 | { |
42 | u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC; | 42 | u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC; |
43 | unsigned long rate = inrate; | 43 | unsigned long rate = inrate; |
44 | int ret; | ||
44 | 45 | ||
45 | if (rate >= 1500000) { | 46 | if (rate >= 1500000) { |
46 | rate /= 16; | 47 | rate /= 16; |
@@ -50,11 +51,15 @@ static void integrator_clocksource_init(unsigned long inrate, | |||
50 | writel(0xffff, base + TIMER_LOAD); | 51 | writel(0xffff, base + TIMER_LOAD); |
51 | writel(ctrl, base + TIMER_CTRL); | 52 | writel(ctrl, base + TIMER_CTRL); |
52 | 53 | ||
53 | clocksource_mmio_init(base + TIMER_VALUE, "timer2", | 54 | ret = clocksource_mmio_init(base + TIMER_VALUE, "timer2", |
54 | rate, 200, 16, clocksource_mmio_readl_down); | 55 | rate, 200, 16, clocksource_mmio_readl_down); |
56 | if (ret) | ||
57 | return ret; | ||
55 | 58 | ||
56 | sched_clk_base = base; | 59 | sched_clk_base = base; |
57 | sched_clock_register(integrator_read_sched_clock, 16, rate); | 60 | sched_clock_register(integrator_read_sched_clock, 16, rate); |
61 | |||
62 | return 0; | ||
58 | } | 63 | } |
59 | 64 | ||
60 | static unsigned long timer_reload; | 65 | static unsigned long timer_reload; |
@@ -138,11 +143,12 @@ static struct irqaction integrator_timer_irq = { | |||
138 | .dev_id = &integrator_clockevent, | 143 | .dev_id = &integrator_clockevent, |
139 | }; | 144 | }; |
140 | 145 | ||
141 | static void integrator_clockevent_init(unsigned long inrate, | 146 | static int integrator_clockevent_init(unsigned long inrate, |
142 | void __iomem *base, int irq) | 147 | void __iomem *base, int irq) |
143 | { | 148 | { |
144 | unsigned long rate = inrate; | 149 | unsigned long rate = inrate; |
145 | unsigned int ctrl = 0; | 150 | unsigned int ctrl = 0; |
151 | int ret; | ||
146 | 152 | ||
147 | clkevt_base = base; | 153 | clkevt_base = base; |
148 | /* Calculate and program a divisor */ | 154 | /* Calculate and program a divisor */ |
@@ -156,14 +162,18 @@ static void integrator_clockevent_init(unsigned long inrate, | |||
156 | timer_reload = rate / HZ; | 162 | timer_reload = rate / HZ; |
157 | writel(ctrl, clkevt_base + TIMER_CTRL); | 163 | writel(ctrl, clkevt_base + TIMER_CTRL); |
158 | 164 | ||
159 | setup_irq(irq, &integrator_timer_irq); | 165 | ret = setup_irq(irq, &integrator_timer_irq); |
166 | if (ret) | ||
167 | return ret; | ||
168 | |||
160 | clockevents_config_and_register(&integrator_clockevent, | 169 | clockevents_config_and_register(&integrator_clockevent, |
161 | rate, | 170 | rate, |
162 | 1, | 171 | 1, |
163 | 0xffffU); | 172 | 0xffffU); |
173 | return 0; | ||
164 | } | 174 | } |
165 | 175 | ||
166 | static void __init integrator_ap_timer_init_of(struct device_node *node) | 176 | static int __init integrator_ap_timer_init_of(struct device_node *node) |
167 | { | 177 | { |
168 | const char *path; | 178 | const char *path; |
169 | void __iomem *base; | 179 | void __iomem *base; |
@@ -176,12 +186,12 @@ static void __init integrator_ap_timer_init_of(struct device_node *node) | |||
176 | 186 | ||
177 | base = of_io_request_and_map(node, 0, "integrator-timer"); | 187 | base = of_io_request_and_map(node, 0, "integrator-timer"); |
178 | if (IS_ERR(base)) | 188 | if (IS_ERR(base)) |
179 | return; | 189 | return PTR_ERR(base); |
180 | 190 | ||
181 | clk = of_clk_get(node, 0); | 191 | clk = of_clk_get(node, 0); |
182 | if (IS_ERR(clk)) { | 192 | if (IS_ERR(clk)) { |
183 | pr_err("No clock for %s\n", node->name); | 193 | pr_err("No clock for %s\n", node->name); |
184 | return; | 194 | return PTR_ERR(clk); |
185 | } | 195 | } |
186 | clk_prepare_enable(clk); | 196 | clk_prepare_enable(clk); |
187 | rate = clk_get_rate(clk); | 197 | rate = clk_get_rate(clk); |
@@ -189,31 +199,38 @@ static void __init integrator_ap_timer_init_of(struct device_node *node) | |||
189 | 199 | ||
190 | err = of_property_read_string(of_aliases, | 200 | err = of_property_read_string(of_aliases, |
191 | "arm,timer-primary", &path); | 201 | "arm,timer-primary", &path); |
192 | if (WARN_ON(err)) | 202 | if (err) { |
193 | return; | 203 | pr_warn("Failed to read property"); |
204 | return err; | ||
205 | } | ||
206 | |||
194 | pri_node = of_find_node_by_path(path); | 207 | pri_node = of_find_node_by_path(path); |
208 | |||
195 | err = of_property_read_string(of_aliases, | 209 | err = of_property_read_string(of_aliases, |
196 | "arm,timer-secondary", &path); | 210 | "arm,timer-secondary", &path); |
197 | if (WARN_ON(err)) | 211 | if (err) { |
198 | return; | 212 | pr_warn("Failed to read property"); |
213 | return err; | ||
214 | } | ||
215 | |||
216 | |||
199 | sec_node = of_find_node_by_path(path); | 217 | sec_node = of_find_node_by_path(path); |
200 | 218 | ||
201 | if (node == pri_node) { | 219 | if (node == pri_node) |
202 | /* The primary timer lacks IRQ, use as clocksource */ | 220 | /* The primary timer lacks IRQ, use as clocksource */ |
203 | integrator_clocksource_init(rate, base); | 221 | return integrator_clocksource_init(rate, base); |
204 | return; | ||
205 | } | ||
206 | 222 | ||
207 | if (node == sec_node) { | 223 | if (node == sec_node) { |
208 | /* The secondary timer will drive the clock event */ | 224 | /* The secondary timer will drive the clock event */ |
209 | irq = irq_of_parse_and_map(node, 0); | 225 | irq = irq_of_parse_and_map(node, 0); |
210 | integrator_clockevent_init(rate, base, irq); | 226 | return integrator_clockevent_init(rate, base, irq); |
211 | return; | ||
212 | } | 227 | } |
213 | 228 | ||
214 | pr_info("Timer @%p unused\n", base); | 229 | pr_info("Timer @%p unused\n", base); |
215 | clk_disable_unprepare(clk); | 230 | clk_disable_unprepare(clk); |
231 | |||
232 | return 0; | ||
216 | } | 233 | } |
217 | 234 | ||
218 | CLOCKSOURCE_OF_DECLARE(integrator_ap_timer, "arm,integrator-timer", | 235 | CLOCKSOURCE_OF_DECLARE_RET(integrator_ap_timer, "arm,integrator-timer", |
219 | integrator_ap_timer_init_of); | 236 | integrator_ap_timer_init_of); |