summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Lezcano <daniel.lezcano@linaro.org>2016-06-06 17:27:24 -0400
committerDaniel Lezcano <daniel.lezcano@linaro.org>2016-06-28 04:19:30 -0400
commit76804d052316d3562c58934200c932243f312c07 (patch)
tree4ff74018a5aefe653bf72accfa913caf4fc1f719
parentc11cd416aea9e4f71b58def49e860ba8609a1892 (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.c59
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
39static void integrator_clocksource_init(unsigned long inrate, 39static 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
60static unsigned long timer_reload; 65static 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
141static void integrator_clockevent_init(unsigned long inrate, 146static 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
166static void __init integrator_ap_timer_init_of(struct device_node *node) 176static 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
218CLOCKSOURCE_OF_DECLARE(integrator_ap_timer, "arm,integrator-timer", 235CLOCKSOURCE_OF_DECLARE_RET(integrator_ap_timer, "arm,integrator-timer",
219 integrator_ap_timer_init_of); 236 integrator_ap_timer_init_of);