aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-07 14:06:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-07 14:06:17 -0400
commit38f56f33ca381751f9b8910f67e7a805ec0b68cb (patch)
tree202f2ce60f3f43a948607ec76c8cc48c1cf73a4b /arch/arm/plat-omap
parentfcba914542082b272f31c8e4c40000b88ed3208d (diff)
parent4183bef2e093a2f0aab45f2d5fed82b0e02aeacf (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.c241
-rw-r--r--arch/arm/plat-omap/include/plat/dmtimer.h1
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;
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
@@ -177,29 +184,82 @@ int omap_dm_timer_reserve_systimer(int id)
177 return 0; 184 return 0;
178} 185}
179 186
180struct omap_dm_timer *omap_dm_timer_request(void) 187static 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 }
257found:
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
271struct omap_dm_timer *omap_dm_timer_request(void)
272{
273 return _omap_dm_timer_request(REQUEST_ANY, NULL);
274}
210EXPORT_SYMBOL_GPL(omap_dm_timer_request); 275EXPORT_SYMBOL_GPL(omap_dm_timer_request);
211 276
212struct omap_dm_timer *omap_dm_timer_request_specific(int id) 277struct 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}
248EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific); 288EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
249 289
@@ -258,46 +298,25 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
258 */ 298 */
259struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap) 299struct 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}
303EXPORT_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 */
312struct 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}
300EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_cap); 319EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_node);
301 320
302int omap_dm_timer_free(struct omap_dm_timer *timer) 321int omap_dm_timer_free(struct omap_dm_timer *timer)
303{ 322{
@@ -314,7 +333,21 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_free);
314 333
315void omap_dm_timer_enable(struct omap_dm_timer *timer) 334void 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}
319EXPORT_SYMBOL_GPL(omap_dm_timer_enable); 352EXPORT_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}
770EXPORT_SYMBOL_GPL(omap_dm_timers_active); 783EXPORT_SYMBOL_GPL(omap_dm_timers_active);
771 784
785static 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
905static const struct dmtimer_platform_data omap3plus_pdata = {
906 .timer_errata = OMAP_TIMER_ERRATA_I103_I767,
907};
908
884static const struct of_device_id omap_timer_match[] = { 909static 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};
888MODULE_DEVICE_TABLE(of, omap_timer_match); 935MODULE_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);
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);