diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-07 14:06:17 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-07 14:06:17 -0400 |
commit | 38f56f33ca381751f9b8910f67e7a805ec0b68cb (patch) | |
tree | 202f2ce60f3f43a948607ec76c8cc48c1cf73a4b /arch/arm/plat-omap | |
parent | fcba914542082b272f31c8e4c40000b88ed3208d (diff) | |
parent | 4183bef2e093a2f0aab45f2d5fed82b0e02aeacf (diff) |
Merge tag 'dt-for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC device tree updates (part 2) from Arnd Bergmann:
"These are mostly new device tree bindings for existing drivers, as
well as changes to the device tree source files to add support for
those devices, and a couple of new boards, most notably Samsung's
Exynos5 based Chromebook.
The changes depend on earlier platform specific updates and touch the
usual platforms: omap, exynos, tegra, mxs, mvebu and davinci."
* tag 'dt-for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (169 commits)
ARM: exynos: dts: cros5250: add EC device
ARM: dts: Add sbs-battery for exynos5250-snow
ARM: dts: Add i2c-arbitrator bus for exynos5250-snow
ARM: dts: add mshc controller node for Exynos4x12 SoCs
ARM: dts: Add chip-id controller node on Exynos4/5 SoC
ARM: EXYNOS: Create virtual I/O mapping for Chip-ID controller using device tree
ARM: davinci: da850-evm: add SPI flash support
ARM: davinci: da850: override SPI DT node device name
ARM: davinci: da850: add SPI1 DT node
spi/davinci: add DT binding documentation
spi/davinci: no wildcards in DT compatible property
ARM: dts: mvebu: Convert mvebu device tree files to 64 bits
ARM: dts: mvebu: introduce internal-regs node
ARM: dts: mvebu: Convert all the mvebu files to use the range property
ARM: dts: mvebu: move all peripherals inside soc
ARM: dts: mvebu: fix cpus section indentation
ARM: davinci: da850: add EHRPWM & ECAP DT node
ARM/dts: OMAP3: fix pinctrl-single configuration
ARM: dts: Add OMAP3430 SDP NOR flash memory binding
ARM: dts: Add NOR flash bindings for OMAP2420 H4
...
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r-- | arch/arm/plat-omap/dmtimer.c | 241 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/dmtimer.h | 1 |
2 files changed, 145 insertions, 97 deletions
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index e6dbc8dbe6a6..869254cebf84 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c | |||
@@ -52,6 +52,13 @@ static u32 omap_reserved_systimers; | |||
52 | static LIST_HEAD(omap_timer_list); | 52 | static LIST_HEAD(omap_timer_list); |
53 | static DEFINE_SPINLOCK(dm_timer_lock); | 53 | static DEFINE_SPINLOCK(dm_timer_lock); |
54 | 54 | ||
55 | enum { | ||
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 |
@@ -177,29 +184,82 @@ int omap_dm_timer_reserve_systimer(int id) | |||
177 | return 0; | 184 | return 0; |
178 | } | 185 | } |
179 | 186 | ||
180 | struct omap_dm_timer *omap_dm_timer_request(void) | 187 | static struct omap_dm_timer *_omap_dm_timer_request(int req_type, void *data) |
181 | { | 188 | { |
182 | struct omap_dm_timer *timer = NULL, *t; | 189 | struct omap_dm_timer *timer = NULL, *t; |
190 | struct device_node *np = NULL; | ||
183 | unsigned long flags; | 191 | unsigned long flags; |
184 | int ret = 0; | 192 | u32 cap = 0; |
193 | int id = 0; | ||
194 | |||
195 | switch (req_type) { | ||
196 | case REQUEST_BY_ID: | ||
197 | id = *(int *)data; | ||
198 | break; | ||
199 | case REQUEST_BY_CAP: | ||
200 | cap = *(u32 *)data; | ||
201 | break; | ||
202 | case REQUEST_BY_NODE: | ||
203 | np = (struct device_node *)data; | ||
204 | break; | ||
205 | default: | ||
206 | /* REQUEST_ANY */ | ||
207 | break; | ||
208 | } | ||
185 | 209 | ||
186 | spin_lock_irqsave(&dm_timer_lock, flags); | 210 | spin_lock_irqsave(&dm_timer_lock, flags); |
187 | list_for_each_entry(t, &omap_timer_list, node) { | 211 | list_for_each_entry(t, &omap_timer_list, node) { |
188 | if (t->reserved) | 212 | if (t->reserved) |
189 | continue; | 213 | continue; |
190 | 214 | ||
191 | timer = t; | 215 | switch (req_type) { |
192 | timer->reserved = 1; | 216 | case REQUEST_BY_ID: |
193 | break; | 217 | if (id == t->pdev->id) { |
218 | timer = t; | ||
219 | timer->reserved = 1; | ||
220 | goto found; | ||
221 | } | ||
222 | break; | ||
223 | case REQUEST_BY_CAP: | ||
224 | if (cap == (t->capability & cap)) { | ||
225 | /* | ||
226 | * If timer is not NULL, we have already found | ||
227 | * one timer but it was not an exact match | ||
228 | * because it had more capabilites that what | ||
229 | * was required. Therefore, unreserve the last | ||
230 | * timer found and see if this one is a better | ||
231 | * match. | ||
232 | */ | ||
233 | if (timer) | ||
234 | timer->reserved = 0; | ||
235 | timer = t; | ||
236 | timer->reserved = 1; | ||
237 | |||
238 | /* Exit loop early if we find an exact match */ | ||
239 | if (t->capability == cap) | ||
240 | goto found; | ||
241 | } | ||
242 | break; | ||
243 | case REQUEST_BY_NODE: | ||
244 | if (np == t->pdev->dev.of_node) { | ||
245 | timer = t; | ||
246 | timer->reserved = 1; | ||
247 | goto found; | ||
248 | } | ||
249 | break; | ||
250 | default: | ||
251 | /* REQUEST_ANY */ | ||
252 | timer = t; | ||
253 | timer->reserved = 1; | ||
254 | goto found; | ||
255 | } | ||
194 | } | 256 | } |
257 | found: | ||
195 | spin_unlock_irqrestore(&dm_timer_lock, flags); | 258 | spin_unlock_irqrestore(&dm_timer_lock, flags); |
196 | 259 | ||
197 | if (timer) { | 260 | if (timer && omap_dm_timer_prepare(timer)) { |
198 | ret = omap_dm_timer_prepare(timer); | 261 | timer->reserved = 0; |
199 | if (ret) { | 262 | timer = NULL; |
200 | timer->reserved = 0; | ||
201 | timer = NULL; | ||
202 | } | ||
203 | } | 263 | } |
204 | 264 | ||
205 | if (!timer) | 265 | if (!timer) |
@@ -207,43 +267,23 @@ struct omap_dm_timer *omap_dm_timer_request(void) | |||
207 | 267 | ||
208 | return timer; | 268 | return timer; |
209 | } | 269 | } |
270 | |||
271 | struct omap_dm_timer *omap_dm_timer_request(void) | ||
272 | { | ||
273 | return _omap_dm_timer_request(REQUEST_ANY, NULL); | ||
274 | } | ||
210 | EXPORT_SYMBOL_GPL(omap_dm_timer_request); | 275 | EXPORT_SYMBOL_GPL(omap_dm_timer_request); |
211 | 276 | ||
212 | struct omap_dm_timer *omap_dm_timer_request_specific(int id) | 277 | struct omap_dm_timer *omap_dm_timer_request_specific(int id) |
213 | { | 278 | { |
214 | struct omap_dm_timer *timer = NULL, *t; | ||
215 | unsigned long flags; | ||
216 | int ret = 0; | ||
217 | |||
218 | /* Requesting timer by ID is not supported when device tree is used */ | 279 | /* Requesting timer by ID is not supported when device tree is used */ |
219 | if (of_have_populated_dt()) { | 280 | if (of_have_populated_dt()) { |
220 | pr_warn("%s: Please use omap_dm_timer_request_by_cap()\n", | 281 | pr_warn("%s: Please use omap_dm_timer_request_by_cap/node()\n", |
221 | __func__); | 282 | __func__); |
222 | return NULL; | 283 | return NULL; |
223 | } | 284 | } |
224 | 285 | ||
225 | spin_lock_irqsave(&dm_timer_lock, flags); | 286 | return _omap_dm_timer_request(REQUEST_BY_ID, &id); |
226 | list_for_each_entry(t, &omap_timer_list, node) { | ||
227 | if (t->pdev->id == id && !t->reserved) { | ||
228 | timer = t; | ||
229 | timer->reserved = 1; | ||
230 | break; | ||
231 | } | ||
232 | } | ||
233 | spin_unlock_irqrestore(&dm_timer_lock, flags); | ||
234 | |||
235 | if (timer) { | ||
236 | ret = omap_dm_timer_prepare(timer); | ||
237 | if (ret) { | ||
238 | timer->reserved = 0; | ||
239 | timer = NULL; | ||
240 | } | ||
241 | } | ||
242 | |||
243 | if (!timer) | ||
244 | pr_debug("%s: timer%d request failed!\n", __func__, id); | ||
245 | |||
246 | return timer; | ||
247 | } | 287 | } |
248 | EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific); | 288 | EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific); |
249 | 289 | ||
@@ -258,46 +298,25 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific); | |||
258 | */ | 298 | */ |
259 | struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap) | 299 | struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap) |
260 | { | 300 | { |
261 | struct omap_dm_timer *timer = NULL, *t; | 301 | return _omap_dm_timer_request(REQUEST_BY_CAP, &cap); |
262 | unsigned long flags; | 302 | } |
303 | EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_cap); | ||
263 | 304 | ||
264 | if (!cap) | 305 | /** |
306 | * omap_dm_timer_request_by_node - Request a timer by device-tree node | ||
307 | * @np: Pointer to device-tree timer node | ||
308 | * | ||
309 | * Request a timer based upon a device node pointer. Returns pointer to | ||
310 | * timer handle on success and a NULL pointer on failure. | ||
311 | */ | ||
312 | struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *np) | ||
313 | { | ||
314 | if (!np) | ||
265 | return NULL; | 315 | return NULL; |
266 | 316 | ||
267 | spin_lock_irqsave(&dm_timer_lock, flags); | 317 | return _omap_dm_timer_request(REQUEST_BY_NODE, np); |
268 | list_for_each_entry(t, &omap_timer_list, node) { | ||
269 | if ((!t->reserved) && ((t->capability & cap) == cap)) { | ||
270 | /* | ||
271 | * If timer is not NULL, we have already found one timer | ||
272 | * but it was not an exact match because it had more | ||
273 | * capabilites that what was required. Therefore, | ||
274 | * unreserve the last timer found and see if this one | ||
275 | * is a better match. | ||
276 | */ | ||
277 | if (timer) | ||
278 | timer->reserved = 0; | ||
279 | |||
280 | timer = t; | ||
281 | timer->reserved = 1; | ||
282 | |||
283 | /* Exit loop early if we find an exact match */ | ||
284 | if (t->capability == cap) | ||
285 | break; | ||
286 | } | ||
287 | } | ||
288 | spin_unlock_irqrestore(&dm_timer_lock, flags); | ||
289 | |||
290 | if (timer && omap_dm_timer_prepare(timer)) { | ||
291 | timer->reserved = 0; | ||
292 | timer = NULL; | ||
293 | } | ||
294 | |||
295 | if (!timer) | ||
296 | pr_debug("%s: timer request failed!\n", __func__); | ||
297 | |||
298 | return timer; | ||
299 | } | 318 | } |
300 | EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_cap); | 319 | EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_node); |
301 | 320 | ||
302 | int omap_dm_timer_free(struct omap_dm_timer *timer) | 321 | int omap_dm_timer_free(struct omap_dm_timer *timer) |
303 | { | 322 | { |
@@ -314,7 +333,21 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_free); | |||
314 | 333 | ||
315 | void omap_dm_timer_enable(struct omap_dm_timer *timer) | 334 | void omap_dm_timer_enable(struct omap_dm_timer *timer) |
316 | { | 335 | { |
336 | int c; | ||
337 | |||
317 | pm_runtime_get_sync(&timer->pdev->dev); | 338 | pm_runtime_get_sync(&timer->pdev->dev); |
339 | |||
340 | if (!(timer->capability & OMAP_TIMER_ALWON)) { | ||
341 | if (timer->get_context_loss_count) { | ||
342 | c = timer->get_context_loss_count(&timer->pdev->dev); | ||
343 | if (c != timer->ctx_loss_count) { | ||
344 | omap_timer_restore_context(timer); | ||
345 | timer->ctx_loss_count = c; | ||
346 | } | ||
347 | } else { | ||
348 | omap_timer_restore_context(timer); | ||
349 | } | ||
350 | } | ||
318 | } | 351 | } |
319 | EXPORT_SYMBOL_GPL(omap_dm_timer_enable); | 352 | EXPORT_SYMBOL_GPL(omap_dm_timer_enable); |
320 | 353 | ||
@@ -409,13 +442,6 @@ int omap_dm_timer_start(struct omap_dm_timer *timer) | |||
409 | 442 | ||
410 | omap_dm_timer_enable(timer); | 443 | omap_dm_timer_enable(timer); |
411 | 444 | ||
412 | if (!(timer->capability & OMAP_TIMER_ALWON)) { | ||
413 | if (timer->get_context_loss_count && | ||
414 | timer->get_context_loss_count(&timer->pdev->dev) != | ||
415 | timer->ctx_loss_count) | ||
416 | omap_timer_restore_context(timer); | ||
417 | } | ||
418 | |||
419 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); | 445 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); |
420 | if (!(l & OMAP_TIMER_CTRL_ST)) { | 446 | if (!(l & OMAP_TIMER_CTRL_ST)) { |
421 | l |= OMAP_TIMER_CTRL_ST; | 447 | l |= OMAP_TIMER_CTRL_ST; |
@@ -440,12 +466,6 @@ int omap_dm_timer_stop(struct omap_dm_timer *timer) | |||
440 | 466 | ||
441 | __omap_dm_timer_stop(timer, timer->posted, rate); | 467 | __omap_dm_timer_stop(timer, timer->posted, rate); |
442 | 468 | ||
443 | if (!(timer->capability & OMAP_TIMER_ALWON)) { | ||
444 | if (timer->get_context_loss_count) | ||
445 | timer->ctx_loss_count = | ||
446 | timer->get_context_loss_count(&timer->pdev->dev); | ||
447 | } | ||
448 | |||
449 | /* | 469 | /* |
450 | * Since the register values are computed and written within | 470 | * Since the register values are computed and written within |
451 | * __omap_dm_timer_stop, we need to use read to retrieve the | 471 | * __omap_dm_timer_stop, we need to use read to retrieve the |
@@ -552,13 +572,6 @@ int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, | |||
552 | 572 | ||
553 | omap_dm_timer_enable(timer); | 573 | omap_dm_timer_enable(timer); |
554 | 574 | ||
555 | if (!(timer->capability & OMAP_TIMER_ALWON)) { | ||
556 | if (timer->get_context_loss_count && | ||
557 | timer->get_context_loss_count(&timer->pdev->dev) != | ||
558 | timer->ctx_loss_count) | ||
559 | omap_timer_restore_context(timer); | ||
560 | } | ||
561 | |||
562 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); | 575 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); |
563 | if (autoreload) { | 576 | if (autoreload) { |
564 | l |= OMAP_TIMER_CTRL_AR; | 577 | l |= OMAP_TIMER_CTRL_AR; |
@@ -769,6 +782,8 @@ int omap_dm_timers_active(void) | |||
769 | } | 782 | } |
770 | EXPORT_SYMBOL_GPL(omap_dm_timers_active); | 783 | EXPORT_SYMBOL_GPL(omap_dm_timers_active); |
771 | 784 | ||
785 | static const struct of_device_id omap_timer_match[]; | ||
786 | |||
772 | /** | 787 | /** |
773 | * omap_dm_timer_probe - probe function called for every registered device | 788 | * omap_dm_timer_probe - probe function called for every registered device |
774 | * @pdev: pointer to current timer platform device | 789 | * @pdev: pointer to current timer platform device |
@@ -782,7 +797,11 @@ static int omap_dm_timer_probe(struct platform_device *pdev) | |||
782 | struct omap_dm_timer *timer; | 797 | struct omap_dm_timer *timer; |
783 | struct resource *mem, *irq; | 798 | struct resource *mem, *irq; |
784 | struct device *dev = &pdev->dev; | 799 | struct device *dev = &pdev->dev; |
785 | struct dmtimer_platform_data *pdata = pdev->dev.platform_data; | 800 | const struct of_device_id *match; |
801 | const struct dmtimer_platform_data *pdata; | ||
802 | |||
803 | match = of_match_device(of_match_ptr(omap_timer_match), dev); | ||
804 | pdata = match ? match->data : dev->platform_data; | ||
786 | 805 | ||
787 | if (!pdata && !dev->of_node) { | 806 | if (!pdata && !dev->of_node) { |
788 | dev_err(dev, "%s: no platform data.\n", __func__); | 807 | dev_err(dev, "%s: no platform data.\n", __func__); |
@@ -823,12 +842,14 @@ static int omap_dm_timer_probe(struct platform_device *pdev) | |||
823 | timer->capability |= OMAP_TIMER_SECURE; | 842 | timer->capability |= OMAP_TIMER_SECURE; |
824 | } else { | 843 | } else { |
825 | timer->id = pdev->id; | 844 | timer->id = pdev->id; |
826 | timer->errata = pdata->timer_errata; | ||
827 | timer->capability = pdata->timer_capability; | 845 | timer->capability = pdata->timer_capability; |
828 | timer->reserved = omap_dm_timer_reserved_systimer(timer->id); | 846 | timer->reserved = omap_dm_timer_reserved_systimer(timer->id); |
829 | timer->get_context_loss_count = pdata->get_context_loss_count; | 847 | timer->get_context_loss_count = pdata->get_context_loss_count; |
830 | } | 848 | } |
831 | 849 | ||
850 | if (pdata) | ||
851 | timer->errata = pdata->timer_errata; | ||
852 | |||
832 | timer->irq = irq->start; | 853 | timer->irq = irq->start; |
833 | timer->pdev = pdev; | 854 | timer->pdev = pdev; |
834 | 855 | ||
@@ -881,8 +902,34 @@ static int omap_dm_timer_remove(struct platform_device *pdev) | |||
881 | return ret; | 902 | return ret; |
882 | } | 903 | } |
883 | 904 | ||
905 | static const struct dmtimer_platform_data omap3plus_pdata = { | ||
906 | .timer_errata = OMAP_TIMER_ERRATA_I103_I767, | ||
907 | }; | ||
908 | |||
884 | static const struct of_device_id omap_timer_match[] = { | 909 | static const struct of_device_id omap_timer_match[] = { |
885 | { .compatible = "ti,omap2-timer", }, | 910 | { |
911 | .compatible = "ti,omap2420-timer", | ||
912 | }, | ||
913 | { | ||
914 | .compatible = "ti,omap3430-timer", | ||
915 | .data = &omap3plus_pdata, | ||
916 | }, | ||
917 | { | ||
918 | .compatible = "ti,omap4430-timer", | ||
919 | .data = &omap3plus_pdata, | ||
920 | }, | ||
921 | { | ||
922 | .compatible = "ti,omap5430-timer", | ||
923 | .data = &omap3plus_pdata, | ||
924 | }, | ||
925 | { | ||
926 | .compatible = "ti,am335x-timer", | ||
927 | .data = &omap3plus_pdata, | ||
928 | }, | ||
929 | { | ||
930 | .compatible = "ti,am335x-timer-1ms", | ||
931 | .data = &omap3plus_pdata, | ||
932 | }, | ||
886 | {}, | 933 | {}, |
887 | }; | 934 | }; |
888 | MODULE_DEVICE_TABLE(of, omap_timer_match); | 935 | MODULE_DEVICE_TABLE(of, omap_timer_match); |
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); | |||
128 | struct omap_dm_timer *omap_dm_timer_request(void); | 128 | struct omap_dm_timer *omap_dm_timer_request(void); |
129 | struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id); | 129 | struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id); |
130 | struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap); | 130 | struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap); |
131 | struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *np); | ||
131 | int omap_dm_timer_free(struct omap_dm_timer *timer); | 132 | int omap_dm_timer_free(struct omap_dm_timer *timer); |
132 | void omap_dm_timer_enable(struct omap_dm_timer *timer); | 133 | void omap_dm_timer_enable(struct omap_dm_timer *timer); |
133 | void omap_dm_timer_disable(struct omap_dm_timer *timer); | 134 | void omap_dm_timer_disable(struct omap_dm_timer *timer); |