aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r--arch/arm/plat-omap/Kconfig6
-rw-r--r--arch/arm/plat-omap/debug-leds.c2
-rw-r--r--arch/arm/plat-omap/dmtimer.c218
-rw-r--r--arch/arm/plat-omap/include/plat/dmtimer.h143
-rw-r--r--arch/arm/plat-omap/include/plat/prcm.h37
5 files changed, 241 insertions, 165 deletions
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 82fcb206b5b2..665870dce3c8 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -154,6 +154,12 @@ config OMAP_32K_TIMER
154 intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is 154 intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is
155 currently only available for OMAP16XX, 24XX, 34XX and OMAP4/5. 155 currently only available for OMAP16XX, 24XX, 34XX and OMAP4/5.
156 156
157 On OMAP2PLUS this value is only used for CONFIG_HZ and
158 CLOCK_TICK_RATE compile time calculation.
159 The actual timer selection is done in the board file
160 through the (DT_)MACHINE_START structure.
161
162
157config OMAP3_L2_AUX_SECURE_SAVE_RESTORE 163config OMAP3_L2_AUX_SECURE_SAVE_RESTORE
158 bool "OMAP3 HS/EMU save and restore for L2 AUX control register" 164 bool "OMAP3 HS/EMU save and restore for L2 AUX control register"
159 depends on ARCH_OMAP3 && PM 165 depends on ARCH_OMAP3 && PM
diff --git a/arch/arm/plat-omap/debug-leds.c b/arch/arm/plat-omap/debug-leds.c
index c43ea21f33b4..aa7ebc6bcd65 100644
--- a/arch/arm/plat-omap/debug-leds.c
+++ b/arch/arm/plat-omap/debug-leds.c
@@ -111,7 +111,7 @@ static int fpga_probe(struct platform_device *pdev)
111 if (!iomem) 111 if (!iomem)
112 return -ENODEV; 112 return -ENODEV;
113 113
114 fpga = ioremap(iomem->start, H2P2_DBG_FPGA_SIZE); 114 fpga = ioremap(iomem->start, resource_size(iomem));
115 __raw_writew(0xff, &fpga->leds); 115 __raw_writew(0xff, &fpga->leds);
116 116
117 for (i = 0; i < ARRAY_SIZE(dbg_leds); i++) { 117 for (i = 0; i < ARRAY_SIZE(dbg_leds); i++) {
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 82231a75abd6..89585c293554 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -35,11 +35,16 @@
35 * 675 Mass Ave, Cambridge, MA 02139, USA. 35 * 675 Mass Ave, Cambridge, MA 02139, USA.
36 */ 36 */
37 37
38#include <linux/clk.h>
38#include <linux/module.h> 39#include <linux/module.h>
39#include <linux/io.h> 40#include <linux/io.h>
40#include <linux/device.h> 41#include <linux/device.h>
41#include <linux/err.h> 42#include <linux/err.h>
42#include <linux/pm_runtime.h> 43#include <linux/pm_runtime.h>
44#include <linux/of.h>
45#include <linux/of_device.h>
46#include <linux/platform_device.h>
47#include <linux/platform_data/dmtimer-omap.h>
43 48
44#include <plat/dmtimer.h> 49#include <plat/dmtimer.h>
45 50
@@ -81,10 +86,6 @@ static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
81 86
82static void omap_timer_restore_context(struct omap_dm_timer *timer) 87static void omap_timer_restore_context(struct omap_dm_timer *timer)
83{ 88{
84 if (timer->revision == 1)
85 __raw_writel(timer->context.tistat, timer->sys_stat);
86
87 __raw_writel(timer->context.tisr, timer->irq_stat);
88 omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, 89 omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
89 timer->context.twer); 90 timer->context.twer);
90 omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, 91 omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
@@ -100,39 +101,38 @@ static void omap_timer_restore_context(struct omap_dm_timer *timer)
100 timer->context.tclr); 101 timer->context.tclr);
101} 102}
102 103
103static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer) 104static int omap_dm_timer_reset(struct omap_dm_timer *timer)
104{ 105{
105 int c; 106 u32 l, timeout = 100000;
106 107
107 if (!timer->sys_stat) 108 if (timer->revision != 1)
108 return; 109 return -EINVAL;
109 110
110 c = 0; 111 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
111 while (!(__raw_readl(timer->sys_stat) & 1)) {
112 c++;
113 if (c > 100000) {
114 printk(KERN_ERR "Timer failed to reset\n");
115 return;
116 }
117 }
118}
119 112
120static void omap_dm_timer_reset(struct omap_dm_timer *timer) 113 do {
121{ 114 l = __omap_dm_timer_read(timer,
122 omap_dm_timer_enable(timer); 115 OMAP_TIMER_V1_SYS_STAT_OFFSET, 0);
123 if (timer->pdev->id != 1) { 116 } while (!l && timeout--);
124 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06); 117
125 omap_dm_timer_wait_for_reset(timer); 118 if (!timeout) {
119 dev_err(&timer->pdev->dev, "Timer failed to reset\n");
120 return -ETIMEDOUT;
126 } 121 }
127 122
128 __omap_dm_timer_reset(timer, 0, 0); 123 /* Configure timer for smart-idle mode */
129 omap_dm_timer_disable(timer); 124 l = __omap_dm_timer_read(timer, OMAP_TIMER_OCP_CFG_OFFSET, 0);
130 timer->posted = 1; 125 l |= 0x2 << 0x3;
126 __omap_dm_timer_write(timer, OMAP_TIMER_OCP_CFG_OFFSET, l, 0);
127
128 timer->posted = 0;
129
130 return 0;
131} 131}
132 132
133int omap_dm_timer_prepare(struct omap_dm_timer *timer) 133static int omap_dm_timer_prepare(struct omap_dm_timer *timer)
134{ 134{
135 int ret; 135 int rc;
136 136
137 /* 137 /*
138 * FIXME: OMAP1 devices do not use the clock framework for dmtimers so 138 * FIXME: OMAP1 devices do not use the clock framework for dmtimers so
@@ -147,13 +147,20 @@ int omap_dm_timer_prepare(struct omap_dm_timer *timer)
147 } 147 }
148 } 148 }
149 149
150 if (timer->capability & OMAP_TIMER_NEEDS_RESET) 150 omap_dm_timer_enable(timer);
151 omap_dm_timer_reset(timer); 151
152 if (timer->capability & OMAP_TIMER_NEEDS_RESET) {
153 rc = omap_dm_timer_reset(timer);
154 if (rc) {
155 omap_dm_timer_disable(timer);
156 return rc;
157 }
158 }
152 159
153 ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ); 160 __omap_dm_timer_enable_posted(timer);
161 omap_dm_timer_disable(timer);
154 162
155 timer->posted = 1; 163 return omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
156 return ret;
157} 164}
158 165
159static inline u32 omap_dm_timer_reserved_systimer(int id) 166static inline u32 omap_dm_timer_reserved_systimer(int id)
@@ -209,6 +216,13 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id)
209 unsigned long flags; 216 unsigned long flags;
210 int ret = 0; 217 int ret = 0;
211 218
219 /* Requesting timer by ID is not supported when device tree is used */
220 if (of_have_populated_dt()) {
221 pr_warn("%s: Please use omap_dm_timer_request_by_cap()\n",
222 __func__);
223 return NULL;
224 }
225
212 spin_lock_irqsave(&dm_timer_lock, flags); 226 spin_lock_irqsave(&dm_timer_lock, flags);
213 list_for_each_entry(t, &omap_timer_list, node) { 227 list_for_each_entry(t, &omap_timer_list, node) {
214 if (t->pdev->id == id && !t->reserved) { 228 if (t->pdev->id == id && !t->reserved) {
@@ -234,6 +248,58 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id)
234} 248}
235EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific); 249EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
236 250
251/**
252 * omap_dm_timer_request_by_cap - Request a timer by capability
253 * @cap: Bit mask of capabilities to match
254 *
255 * Find a timer based upon capabilities bit mask. Callers of this function
256 * should use the definitions found in the plat/dmtimer.h file under the
257 * comment "timer capabilities used in hwmod database". Returns pointer to
258 * timer handle on success and a NULL pointer on failure.
259 */
260struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap)
261{
262 struct omap_dm_timer *timer = NULL, *t;
263 unsigned long flags;
264
265 if (!cap)
266 return NULL;
267
268 spin_lock_irqsave(&dm_timer_lock, flags);
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}
301EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_cap);
302
237int omap_dm_timer_free(struct omap_dm_timer *timer) 303int omap_dm_timer_free(struct omap_dm_timer *timer)
238{ 304{
239 if (unlikely(!timer)) 305 if (unlikely(!timer))
@@ -388,7 +454,6 @@ int omap_dm_timer_stop(struct omap_dm_timer *timer)
388 */ 454 */
389 timer->context.tclr = 455 timer->context.tclr =
390 omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 456 omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
391 timer->context.tisr = __raw_readl(timer->irq_stat);
392 omap_dm_timer_disable(timer); 457 omap_dm_timer_disable(timer);
393 return 0; 458 return 0;
394} 459}
@@ -398,7 +463,7 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
398{ 463{
399 int ret; 464 int ret;
400 char *parent_name = NULL; 465 char *parent_name = NULL;
401 struct clk *fclk, *parent; 466 struct clk *parent;
402 struct dmtimer_platform_data *pdata; 467 struct dmtimer_platform_data *pdata;
403 468
404 if (unlikely(!timer)) 469 if (unlikely(!timer))
@@ -414,14 +479,11 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
414 * use the clock framework to set the parent clock. To be removed 479 * use the clock framework to set the parent clock. To be removed
415 * once OMAP1 migrated to using clock framework for dmtimers 480 * once OMAP1 migrated to using clock framework for dmtimers
416 */ 481 */
417 if (pdata->set_timer_src) 482 if (pdata && pdata->set_timer_src)
418 return pdata->set_timer_src(timer->pdev, source); 483 return pdata->set_timer_src(timer->pdev, source);
419 484
420 fclk = clk_get(&timer->pdev->dev, "fck"); 485 if (!timer->fclk)
421 if (IS_ERR_OR_NULL(fclk)) {
422 pr_err("%s: fck not found\n", __func__);
423 return -EINVAL; 486 return -EINVAL;
424 }
425 487
426 switch (source) { 488 switch (source) {
427 case OMAP_TIMER_SRC_SYS_CLK: 489 case OMAP_TIMER_SRC_SYS_CLK:
@@ -440,18 +502,15 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
440 parent = clk_get(&timer->pdev->dev, parent_name); 502 parent = clk_get(&timer->pdev->dev, parent_name);
441 if (IS_ERR_OR_NULL(parent)) { 503 if (IS_ERR_OR_NULL(parent)) {
442 pr_err("%s: %s not found\n", __func__, parent_name); 504 pr_err("%s: %s not found\n", __func__, parent_name);
443 ret = -EINVAL; 505 return -EINVAL;
444 goto out;
445 } 506 }
446 507
447 ret = clk_set_parent(fclk, parent); 508 ret = clk_set_parent(timer->fclk, parent);
448 if (IS_ERR_VALUE(ret)) 509 if (IS_ERR_VALUE(ret))
449 pr_err("%s: failed to set %s as parent\n", __func__, 510 pr_err("%s: failed to set %s as parent\n", __func__,
450 parent_name); 511 parent_name);
451 512
452 clk_put(parent); 513 clk_put(parent);
453out:
454 clk_put(fclk);
455 514
456 return ret; 515 return ret;
457} 516}
@@ -534,8 +593,8 @@ int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
534 l |= OMAP_TIMER_CTRL_CE; 593 l |= OMAP_TIMER_CTRL_CE;
535 else 594 else
536 l &= ~OMAP_TIMER_CTRL_CE; 595 l &= ~OMAP_TIMER_CTRL_CE;
537 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
538 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match); 596 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
597 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
539 598
540 /* Save the context */ 599 /* Save the context */
541 timer->context.tclr = l; 600 timer->context.tclr = l;
@@ -611,6 +670,37 @@ int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
611} 670}
612EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable); 671EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
613 672
673/**
674 * omap_dm_timer_set_int_disable - disable timer interrupts
675 * @timer: pointer to timer handle
676 * @mask: bit mask of interrupts to be disabled
677 *
678 * Disables the specified timer interrupts for a timer.
679 */
680int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask)
681{
682 u32 l = mask;
683
684 if (unlikely(!timer))
685 return -EINVAL;
686
687 omap_dm_timer_enable(timer);
688
689 if (timer->revision == 1)
690 l = __raw_readl(timer->irq_ena) & ~mask;
691
692 __raw_writel(l, timer->irq_dis);
693 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask;
694 omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, l);
695
696 /* Save the context */
697 timer->context.tier &= ~mask;
698 timer->context.twer &= ~mask;
699 omap_dm_timer_disable(timer);
700 return 0;
701}
702EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_disable);
703
614unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) 704unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
615{ 705{
616 unsigned int l; 706 unsigned int l;
@@ -632,8 +722,7 @@ int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
632 return -EINVAL; 722 return -EINVAL;
633 723
634 __omap_dm_timer_write_status(timer, value); 724 __omap_dm_timer_write_status(timer, value);
635 /* Save the context */ 725
636 timer->context.tisr = value;
637 return 0; 726 return 0;
638} 727}
639EXPORT_SYMBOL_GPL(omap_dm_timer_write_status); 728EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
@@ -696,7 +785,7 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
696 struct device *dev = &pdev->dev; 785 struct device *dev = &pdev->dev;
697 struct dmtimer_platform_data *pdata = pdev->dev.platform_data; 786 struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
698 787
699 if (!pdata) { 788 if (!pdata && !dev->of_node) {
700 dev_err(dev, "%s: no platform data.\n", __func__); 789 dev_err(dev, "%s: no platform data.\n", __func__);
701 return -ENODEV; 790 return -ENODEV;
702 } 791 }
@@ -725,12 +814,25 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
725 return -ENOMEM; 814 return -ENOMEM;
726 } 815 }
727 816
728 timer->id = pdev->id; 817 if (dev->of_node) {
818 if (of_find_property(dev->of_node, "ti,timer-alwon", NULL))
819 timer->capability |= OMAP_TIMER_ALWON;
820 if (of_find_property(dev->of_node, "ti,timer-dsp", NULL))
821 timer->capability |= OMAP_TIMER_HAS_DSP_IRQ;
822 if (of_find_property(dev->of_node, "ti,timer-pwm", NULL))
823 timer->capability |= OMAP_TIMER_HAS_PWM;
824 if (of_find_property(dev->of_node, "ti,timer-secure", NULL))
825 timer->capability |= OMAP_TIMER_SECURE;
826 } else {
827 timer->id = pdev->id;
828 timer->errata = pdata->timer_errata;
829 timer->capability = pdata->timer_capability;
830 timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
831 timer->get_context_loss_count = pdata->get_context_loss_count;
832 }
833
729 timer->irq = irq->start; 834 timer->irq = irq->start;
730 timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
731 timer->pdev = pdev; 835 timer->pdev = pdev;
732 timer->capability = pdata->timer_capability;
733 timer->get_context_loss_count = pdata->get_context_loss_count;
734 836
735 /* Skip pm_runtime_enable for OMAP1 */ 837 /* Skip pm_runtime_enable for OMAP1 */
736 if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) { 838 if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
@@ -770,7 +872,8 @@ static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
770 872
771 spin_lock_irqsave(&dm_timer_lock, flags); 873 spin_lock_irqsave(&dm_timer_lock, flags);
772 list_for_each_entry(timer, &omap_timer_list, node) 874 list_for_each_entry(timer, &omap_timer_list, node)
773 if (timer->pdev->id == pdev->id) { 875 if (!strcmp(dev_name(&timer->pdev->dev),
876 dev_name(&pdev->dev))) {
774 list_del(&timer->node); 877 list_del(&timer->node);
775 ret = 0; 878 ret = 0;
776 break; 879 break;
@@ -780,11 +883,18 @@ static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
780 return ret; 883 return ret;
781} 884}
782 885
886static const struct of_device_id omap_timer_match[] = {
887 { .compatible = "ti,omap2-timer", },
888 {},
889};
890MODULE_DEVICE_TABLE(of, omap_timer_match);
891
783static struct platform_driver omap_dm_timer_driver = { 892static struct platform_driver omap_dm_timer_driver = {
784 .probe = omap_dm_timer_probe, 893 .probe = omap_dm_timer_probe,
785 .remove = __devexit_p(omap_dm_timer_remove), 894 .remove = __devexit_p(omap_dm_timer_remove),
786 .driver = { 895 .driver = {
787 .name = "omap_timer", 896 .name = "omap_timer",
897 .of_match_table = of_match_ptr(omap_timer_match),
788 }, 898 },
789}; 899};
790 900
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index 3f5b9cfd9c0b..a3fbc48c332e 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -32,7 +32,6 @@
32 * 675 Mass Ave, Cambridge, MA 02139, USA. 32 * 675 Mass Ave, Cambridge, MA 02139, USA.
33 */ 33 */
34 34
35#include <linux/clk.h>
36#include <linux/delay.h> 35#include <linux/delay.h>
37#include <linux/io.h> 36#include <linux/io.h>
38#include <linux/platform_device.h> 37#include <linux/platform_device.h>
@@ -55,6 +54,10 @@
55#define OMAP_TIMER_TRIGGER_OVERFLOW 0x01 54#define OMAP_TIMER_TRIGGER_OVERFLOW 0x01
56#define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE 0x02 55#define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE 0x02
57 56
57/* posted mode types */
58#define OMAP_TIMER_NONPOSTED 0x00
59#define OMAP_TIMER_POSTED 0x01
60
58/* timer capabilities used in hwmod database */ 61/* timer capabilities used in hwmod database */
59#define OMAP_TIMER_SECURE 0x80000000 62#define OMAP_TIMER_SECURE 0x80000000
60#define OMAP_TIMER_ALWON 0x40000000 63#define OMAP_TIMER_ALWON 0x40000000
@@ -62,16 +65,22 @@
62#define OMAP_TIMER_NEEDS_RESET 0x10000000 65#define OMAP_TIMER_NEEDS_RESET 0x10000000
63#define OMAP_TIMER_HAS_DSP_IRQ 0x08000000 66#define OMAP_TIMER_HAS_DSP_IRQ 0x08000000
64 67
68/*
69 * timer errata flags
70 *
71 * Errata i103/i767 impacts all OMAP3/4/5 devices including AM33xx. This
72 * errata prevents us from using posted mode on these devices, unless the
73 * timer counter register is never read. For more details please refer to
74 * the OMAP3/4/5 errata documents.
75 */
76#define OMAP_TIMER_ERRATA_I103_I767 0x80000000
77
65struct omap_timer_capability_dev_attr { 78struct omap_timer_capability_dev_attr {
66 u32 timer_capability; 79 u32 timer_capability;
67}; 80};
68 81
69struct omap_dm_timer;
70
71struct timer_regs { 82struct timer_regs {
72 u32 tidr; 83 u32 tidr;
73 u32 tistat;
74 u32 tisr;
75 u32 tier; 84 u32 tier;
76 u32 twer; 85 u32 twer;
77 u32 tclr; 86 u32 tclr;
@@ -90,16 +99,35 @@ struct timer_regs {
90 u32 towr; 99 u32 towr;
91}; 100};
92 101
93struct dmtimer_platform_data { 102struct omap_dm_timer {
94 /* set_timer_src - Only used for OMAP1 devices */ 103 int id;
95 int (*set_timer_src)(struct platform_device *pdev, int source); 104 int irq;
96 u32 timer_capability; 105 struct clk *fclk;
106
107 void __iomem *io_base;
108 void __iomem *irq_stat; /* TISR/IRQSTATUS interrupt status */
109 void __iomem *irq_ena; /* irq enable */
110 void __iomem *irq_dis; /* irq disable, only on v2 ip */
111 void __iomem *pend; /* write pending */
112 void __iomem *func_base; /* function register base */
113
114 unsigned long rate;
115 unsigned reserved:1;
116 unsigned posted:1;
117 struct timer_regs context;
97 int (*get_context_loss_count)(struct device *); 118 int (*get_context_loss_count)(struct device *);
119 int ctx_loss_count;
120 int revision;
121 u32 capability;
122 u32 errata;
123 struct platform_device *pdev;
124 struct list_head node;
98}; 125};
99 126
100int omap_dm_timer_reserve_systimer(int id); 127int omap_dm_timer_reserve_systimer(int id);
101struct omap_dm_timer *omap_dm_timer_request(void); 128struct omap_dm_timer *omap_dm_timer_request(void);
102struct 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);
103int omap_dm_timer_free(struct omap_dm_timer *timer); 131int omap_dm_timer_free(struct omap_dm_timer *timer);
104void omap_dm_timer_enable(struct omap_dm_timer *timer); 132void omap_dm_timer_enable(struct omap_dm_timer *timer);
105void omap_dm_timer_disable(struct omap_dm_timer *timer); 133void omap_dm_timer_disable(struct omap_dm_timer *timer);
@@ -121,6 +149,7 @@ int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, i
121int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler); 149int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler);
122 150
123int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value); 151int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value);
152int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask);
124 153
125unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer); 154unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer);
126int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value); 155int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
@@ -246,34 +275,6 @@ int omap_dm_timers_active(void);
246#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG \ 275#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG \
247 (_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT)) 276 (_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
248 277
249struct omap_dm_timer {
250 unsigned long phys_base;
251 int id;
252 int irq;
253 struct clk *fclk;
254
255 void __iomem *io_base;
256 void __iomem *sys_stat; /* TISTAT timer status */
257 void __iomem *irq_stat; /* TISR/IRQSTATUS interrupt status */
258 void __iomem *irq_ena; /* irq enable */
259 void __iomem *irq_dis; /* irq disable, only on v2 ip */
260 void __iomem *pend; /* write pending */
261 void __iomem *func_base; /* function register base */
262
263 unsigned long rate;
264 unsigned reserved:1;
265 unsigned posted:1;
266 struct timer_regs context;
267 int (*get_context_loss_count)(struct device *);
268 int ctx_loss_count;
269 int revision;
270 u32 capability;
271 struct platform_device *pdev;
272 struct list_head node;
273};
274
275int omap_dm_timer_prepare(struct omap_dm_timer *timer);
276
277static inline u32 __omap_dm_timer_read(struct omap_dm_timer *timer, u32 reg, 278static inline u32 __omap_dm_timer_read(struct omap_dm_timer *timer, u32 reg,
278 int posted) 279 int posted)
279{ 280{
@@ -302,16 +303,13 @@ static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
302 tidr = __raw_readl(timer->io_base); 303 tidr = __raw_readl(timer->io_base);
303 if (!(tidr >> 16)) { 304 if (!(tidr >> 16)) {
304 timer->revision = 1; 305 timer->revision = 1;
305 timer->sys_stat = timer->io_base +
306 OMAP_TIMER_V1_SYS_STAT_OFFSET;
307 timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET; 306 timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET;
308 timer->irq_ena = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET; 307 timer->irq_ena = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET;
309 timer->irq_dis = NULL; 308 timer->irq_dis = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET;
310 timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET; 309 timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET;
311 timer->func_base = timer->io_base; 310 timer->func_base = timer->io_base;
312 } else { 311 } else {
313 timer->revision = 2; 312 timer->revision = 2;
314 timer->sys_stat = NULL;
315 timer->irq_stat = timer->io_base + OMAP_TIMER_V2_IRQSTATUS; 313 timer->irq_stat = timer->io_base + OMAP_TIMER_V2_IRQSTATUS;
316 timer->irq_ena = timer->io_base + OMAP_TIMER_V2_IRQENABLE_SET; 314 timer->irq_ena = timer->io_base + OMAP_TIMER_V2_IRQENABLE_SET;
317 timer->irq_dis = timer->io_base + OMAP_TIMER_V2_IRQENABLE_CLR; 315 timer->irq_dis = timer->io_base + OMAP_TIMER_V2_IRQENABLE_CLR;
@@ -322,45 +320,44 @@ static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
322 } 320 }
323} 321}
324 322
325/* Assumes the source clock has been set by caller */ 323/*
326static inline void __omap_dm_timer_reset(struct omap_dm_timer *timer, 324 * __omap_dm_timer_enable_posted - enables write posted mode
327 int autoidle, int wakeup) 325 * @timer: pointer to timer instance handle
326 *
327 * Enables the write posted mode for the timer. When posted mode is enabled
328 * writes to certain timer registers are immediately acknowledged by the
329 * internal bus and hence prevents stalling the CPU waiting for the write to
330 * complete. Enabling this feature can improve performance for writing to the
331 * timer registers.
332 */
333static inline void __omap_dm_timer_enable_posted(struct omap_dm_timer *timer)
328{ 334{
329 u32 l; 335 if (timer->posted)
336 return;
330 337
331 l = __raw_readl(timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET); 338 if (timer->errata & OMAP_TIMER_ERRATA_I103_I767)
332 l |= 0x02 << 3; /* Set to smart-idle mode */ 339 return;
333 l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */
334 340
335 if (autoidle)
336 l |= 0x1 << 0;
337
338 if (wakeup)
339 l |= 1 << 2;
340
341 __raw_writel(l, timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
342
343 /* Match hardware reset default of posted mode */
344 __omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG, 341 __omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG,
345 OMAP_TIMER_CTRL_POSTED, 0); 342 OMAP_TIMER_CTRL_POSTED, 0);
343 timer->context.tsicr = OMAP_TIMER_CTRL_POSTED;
344 timer->posted = OMAP_TIMER_POSTED;
346} 345}
347 346
348static inline int __omap_dm_timer_set_source(struct clk *timer_fck, 347/**
349 struct clk *parent) 348 * __omap_dm_timer_override_errata - override errata flags for a timer
349 * @timer: pointer to timer handle
350 * @errata: errata flags to be ignored
351 *
352 * For a given timer, override a timer errata by clearing the flags
353 * specified by the errata argument. A specific erratum should only be
354 * overridden for a timer if the timer is used in such a way the erratum
355 * has no impact.
356 */
357static inline void __omap_dm_timer_override_errata(struct omap_dm_timer *timer,
358 u32 errata)
350{ 359{
351 int ret; 360 timer->errata &= ~errata;
352
353 clk_disable(timer_fck);
354 ret = clk_set_parent(timer_fck, parent);
355 clk_enable(timer_fck);
356
357 /*
358 * When the functional clock disappears, too quick writes seem
359 * to cause an abort. XXX Is this still necessary?
360 */
361 __delay(300000);
362
363 return ret;
364} 361}
365 362
366static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer, 363static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer,
diff --git a/arch/arm/plat-omap/include/plat/prcm.h b/arch/arm/plat-omap/include/plat/prcm.h
deleted file mode 100644
index 267f43bb2a4e..000000000000
--- a/arch/arm/plat-omap/include/plat/prcm.h
+++ /dev/null
@@ -1,37 +0,0 @@
1/*
2 * arch/arm/plat-omap/include/mach/prcm.h
3 *
4 * Access definations for use in OMAP24XX clock and power management
5 *
6 * Copyright (C) 2005 Texas Instruments, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 * XXX This file is deprecated. The PRCM is an OMAP2+-only subsystem,
23 * so this file doesn't belong in plat-omap/include/plat. Please
24 * do not add anything new to this file.
25 */
26
27#ifndef __ASM_ARM_ARCH_OMAP_PRCM_H
28#define __ASM_ARM_ARCH_OMAP_PRCM_H
29
30u32 omap_prcm_get_reset_sources(void);
31int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest,
32 const char *name);
33
34#endif
35
36
37