aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJon Hunter <jon-hunter@ti.com>2013-03-19 13:38:17 -0400
committerBenoit Cousson <benoit.cousson@linaro.org>2013-04-08 18:21:31 -0400
commit8fc7fcb593ac3c5730c8391c2d7db5b87e2d0bf2 (patch)
tree4863953406205f2ee04499d01b8561a72537cd6b /arch
parent385c4c7b7c2f6829048d8b041b31f9da10a8202e (diff)
ARM: OMAP: Add function to request timer by node
Add a function so that OMAP dmtimers can be requested by device-tree node. This allows for devices, such as the internal DSP, or drivers, such as PWM, to reference a specific dmtimer node via the device-tree. Given that there are several APIs available for requesting dmtimers (by ID, by capability or by node) consolidate the code for all these functions into a single helper function that can be used by these request functions. Signed-off-by: Jon Hunter <jon-hunter@ti.com> Acked-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Benoit Cousson <benoit.cousson@linaro.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/plat-omap/dmtimer.c167
-rw-r--r--arch/arm/plat-omap/include/plat/dmtimer.h1
2 files changed, 94 insertions, 74 deletions
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 725d9720dd2b..05efb370a2bd 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -52,6 +52,13 @@ static u32 omap_reserved_systimers;
52static LIST_HEAD(omap_timer_list); 52static LIST_HEAD(omap_timer_list);
53static DEFINE_SPINLOCK(dm_timer_lock); 53static DEFINE_SPINLOCK(dm_timer_lock);
54 54
55enum {
56 REQUEST_ANY = 0,
57 REQUEST_BY_ID,
58 REQUEST_BY_CAP,
59 REQUEST_BY_NODE,
60};
61
55/** 62/**
56 * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode 63 * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
57 * @timer: timer pointer over which read operation to perform 64 * @timer: timer pointer over which read operation to perform
@@ -178,29 +185,82 @@ int omap_dm_timer_reserve_systimer(int id)
178 return 0; 185 return 0;
179} 186}
180 187
181struct omap_dm_timer *omap_dm_timer_request(void) 188static struct omap_dm_timer *_omap_dm_timer_request(int req_type, void *data)
182{ 189{
183 struct omap_dm_timer *timer = NULL, *t; 190 struct omap_dm_timer *timer = NULL, *t;
191 struct device_node *np = NULL;
184 unsigned long flags; 192 unsigned long flags;
185 int ret = 0; 193 u32 cap = 0;
194 int id = 0;
195
196 switch (req_type) {
197 case REQUEST_BY_ID:
198 id = *(int *)data;
199 break;
200 case REQUEST_BY_CAP:
201 cap = *(u32 *)data;
202 break;
203 case REQUEST_BY_NODE:
204 np = (struct device_node *)data;
205 break;
206 default:
207 /* REQUEST_ANY */
208 break;
209 }
186 210
187 spin_lock_irqsave(&dm_timer_lock, flags); 211 spin_lock_irqsave(&dm_timer_lock, flags);
188 list_for_each_entry(t, &omap_timer_list, node) { 212 list_for_each_entry(t, &omap_timer_list, node) {
189 if (t->reserved) 213 if (t->reserved)
190 continue; 214 continue;
191 215
192 timer = t; 216 switch (req_type) {
193 timer->reserved = 1; 217 case REQUEST_BY_ID:
194 break; 218 if (id == t->pdev->id) {
219 timer = t;
220 timer->reserved = 1;
221 goto found;
222 }
223 break;
224 case REQUEST_BY_CAP:
225 if (cap == (t->capability & cap)) {
226 /*
227 * If timer is not NULL, we have already found
228 * one timer but it was not an exact match
229 * because it had more capabilites that what
230 * was required. Therefore, unreserve the last
231 * timer found and see if this one is a better
232 * match.
233 */
234 if (timer)
235 timer->reserved = 0;
236 timer = t;
237 timer->reserved = 1;
238
239 /* Exit loop early if we find an exact match */
240 if (t->capability == cap)
241 goto found;
242 }
243 break;
244 case REQUEST_BY_NODE:
245 if (np == t->pdev->dev.of_node) {
246 timer = t;
247 timer->reserved = 1;
248 goto found;
249 }
250 break;
251 default:
252 /* REQUEST_ANY */
253 timer = t;
254 timer->reserved = 1;
255 goto found;
256 }
195 } 257 }
258found:
196 spin_unlock_irqrestore(&dm_timer_lock, flags); 259 spin_unlock_irqrestore(&dm_timer_lock, flags);
197 260
198 if (timer) { 261 if (timer && omap_dm_timer_prepare(timer)) {
199 ret = omap_dm_timer_prepare(timer); 262 timer->reserved = 0;
200 if (ret) { 263 timer = NULL;
201 timer->reserved = 0;
202 timer = NULL;
203 }
204 } 264 }
205 265
206 if (!timer) 266 if (!timer)
@@ -208,43 +268,23 @@ struct omap_dm_timer *omap_dm_timer_request(void)
208 268
209 return timer; 269 return timer;
210} 270}
271
272struct omap_dm_timer *omap_dm_timer_request(void)
273{
274 return _omap_dm_timer_request(REQUEST_ANY, NULL);
275}
211EXPORT_SYMBOL_GPL(omap_dm_timer_request); 276EXPORT_SYMBOL_GPL(omap_dm_timer_request);
212 277
213struct omap_dm_timer *omap_dm_timer_request_specific(int id) 278struct omap_dm_timer *omap_dm_timer_request_specific(int id)
214{ 279{
215 struct omap_dm_timer *timer = NULL, *t;
216 unsigned long flags;
217 int ret = 0;
218
219 /* Requesting timer by ID is not supported when device tree is used */ 280 /* Requesting timer by ID is not supported when device tree is used */
220 if (of_have_populated_dt()) { 281 if (of_have_populated_dt()) {
221 pr_warn("%s: Please use omap_dm_timer_request_by_cap()\n", 282 pr_warn("%s: Please use omap_dm_timer_request_by_cap/node()\n",
222 __func__); 283 __func__);
223 return NULL; 284 return NULL;
224 } 285 }
225 286
226 spin_lock_irqsave(&dm_timer_lock, flags); 287 return _omap_dm_timer_request(REQUEST_BY_ID, &id);
227 list_for_each_entry(t, &omap_timer_list, node) {
228 if (t->pdev->id == id && !t->reserved) {
229 timer = t;
230 timer->reserved = 1;
231 break;
232 }
233 }
234 spin_unlock_irqrestore(&dm_timer_lock, flags);
235
236 if (timer) {
237 ret = omap_dm_timer_prepare(timer);
238 if (ret) {
239 timer->reserved = 0;
240 timer = NULL;
241 }
242 }
243
244 if (!timer)
245 pr_debug("%s: timer%d request failed!\n", __func__, id);
246
247 return timer;
248} 288}
249EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific); 289EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
250 290
@@ -259,46 +299,25 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
259 */ 299 */
260struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap) 300struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap)
261{ 301{
262 struct omap_dm_timer *timer = NULL, *t; 302 return _omap_dm_timer_request(REQUEST_BY_CAP, &cap);
263 unsigned long flags; 303}
304EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_cap);
264 305
265 if (!cap) 306/**
307 * omap_dm_timer_request_by_node - Request a timer by device-tree node
308 * @np: Pointer to device-tree timer node
309 *
310 * Request a timer based upon a device node pointer. Returns pointer to
311 * timer handle on success and a NULL pointer on failure.
312 */
313struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *np)
314{
315 if (!np)
266 return NULL; 316 return NULL;
267 317
268 spin_lock_irqsave(&dm_timer_lock, flags); 318 return _omap_dm_timer_request(REQUEST_BY_NODE, np);
269 list_for_each_entry(t, &omap_timer_list, node) {
270 if ((!t->reserved) && ((t->capability & cap) == cap)) {
271 /*
272 * If timer is not NULL, we have already found one timer
273 * but it was not an exact match because it had more
274 * capabilites that what was required. Therefore,
275 * unreserve the last timer found and see if this one
276 * is a better match.
277 */
278 if (timer)
279 timer->reserved = 0;
280
281 timer = t;
282 timer->reserved = 1;
283
284 /* Exit loop early if we find an exact match */
285 if (t->capability == cap)
286 break;
287 }
288 }
289 spin_unlock_irqrestore(&dm_timer_lock, flags);
290
291 if (timer && omap_dm_timer_prepare(timer)) {
292 timer->reserved = 0;
293 timer = NULL;
294 }
295
296 if (!timer)
297 pr_debug("%s: timer request failed!\n", __func__);
298
299 return timer;
300} 319}
301EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_cap); 320EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_node);
302 321
303int omap_dm_timer_free(struct omap_dm_timer *timer) 322int omap_dm_timer_free(struct omap_dm_timer *timer)
304{ 323{
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index a3fbc48c332e..fb92abb91628 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -128,6 +128,7 @@ int omap_dm_timer_reserve_systimer(int id);
128struct omap_dm_timer *omap_dm_timer_request(void); 128struct omap_dm_timer *omap_dm_timer_request(void);
129struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id); 129struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
130struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap); 130struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap);
131struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *np);
131int omap_dm_timer_free(struct omap_dm_timer *timer); 132int omap_dm_timer_free(struct omap_dm_timer *timer);
132void omap_dm_timer_enable(struct omap_dm_timer *timer); 133void omap_dm_timer_enable(struct omap_dm_timer *timer);
133void omap_dm_timer_disable(struct omap_dm_timer *timer); 134void omap_dm_timer_disable(struct omap_dm_timer *timer);