Merge master.kernel.org:/pub/scm/linux/kernel/git/herbert/crypto-2.6
[linux-drm-fsl-dcu.git] / arch / arm / plat-omap / dmtimer.c
index 804a53534370389a321077af34b3cb6ed625e949..659619f235ca325234c1bdea44cd3c05926fc17a 100644 (file)
@@ -75,10 +75,14 @@ struct omap_dm_timer {
 #endif
        void __iomem *io_base;
        unsigned reserved:1;
+       unsigned enabled:1;
 };
 
 #ifdef CONFIG_ARCH_OMAP1
 
+#define omap_dm_clk_enable(x)
+#define omap_dm_clk_disable(x)
+
 static struct omap_dm_timer dm_timers[] = {
        { .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 },
        { .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 },
@@ -86,12 +90,15 @@ static struct omap_dm_timer dm_timers[] = {
        { .phys_base = 0xfffb2c00, .irq = INT_1610_GPTIMER4 },
        { .phys_base = 0xfffb3400, .irq = INT_1610_GPTIMER5 },
        { .phys_base = 0xfffb3c00, .irq = INT_1610_GPTIMER6 },
-       { .phys_base = 0xfffb4400, .irq = INT_1610_GPTIMER7 },
-       { .phys_base = 0xfffb4c00, .irq = INT_1610_GPTIMER8 },
+       { .phys_base = 0xfffb7400, .irq = INT_1610_GPTIMER7 },
+       { .phys_base = 0xfffbd400, .irq = INT_1610_GPTIMER8 },
 };
 
 #elif defined(CONFIG_ARCH_OMAP2)
 
+#define omap_dm_clk_enable(x) clk_enable(x)
+#define omap_dm_clk_disable(x) clk_disable(x)
+
 static struct omap_dm_timer dm_timers[] = {
        { .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
        { .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 },
@@ -154,24 +161,28 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer)
 {
        u32 l;
 
-       if (timer != &dm_timers[0]) {
+       if (!cpu_class_is_omap2() || timer != &dm_timers[0]) {
                omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
                omap_dm_timer_wait_for_reset(timer);
        }
-       omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_SYS_CLK);
+       omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
 
        /* Set to smart-idle mode */
        l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG);
        l |= 0x02 << 3;
+
+       if (cpu_class_is_omap2() && timer == &dm_timers[0]) {
+               /* Enable wake-up only for GPT1 on OMAP2 CPUs*/
+               l |= 1 << 2;
+               /* Non-posted mode */
+               omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0);
+       }
        omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
 }
 
 static void omap_dm_timer_prepare(struct omap_dm_timer *timer)
 {
-#ifdef CONFIG_ARCH_OMAP2
-       clk_enable(timer->iclk);
-       clk_enable(timer->fclk);
-#endif
+       omap_dm_timer_enable(timer);
        omap_dm_timer_reset(timer);
 }
 
@@ -223,15 +234,36 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id)
 
 void omap_dm_timer_free(struct omap_dm_timer *timer)
 {
+       omap_dm_timer_enable(timer);
        omap_dm_timer_reset(timer);
-#ifdef CONFIG_ARCH_OMAP2
-       clk_disable(timer->iclk);
-       clk_disable(timer->fclk);
-#endif
+       omap_dm_timer_disable(timer);
+
        WARN_ON(!timer->reserved);
        timer->reserved = 0;
 }
 
+void omap_dm_timer_enable(struct omap_dm_timer *timer)
+{
+       if (timer->enabled)
+               return;
+
+       omap_dm_clk_enable(timer->fclk);
+       omap_dm_clk_enable(timer->iclk);
+
+       timer->enabled = 1;
+}
+
+void omap_dm_timer_disable(struct omap_dm_timer *timer)
+{
+       if (!timer->enabled)
+               return;
+
+       omap_dm_clk_disable(timer->iclk);
+       omap_dm_clk_disable(timer->fclk);
+
+       timer->enabled = 0;
+}
+
 int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
 {
        return timer->irq;
@@ -260,7 +292,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
        for (i = 0; i < dm_timer_count; i++) {
                u32 l;
 
-               l = omap_dm_timer_read_reg(&dm_timers[n], OMAP_TIMER_CTRL_REG);
+               l = omap_dm_timer_read_reg(&dm_timers[i], OMAP_TIMER_CTRL_REG);
                if (l & OMAP_TIMER_CTRL_ST) {
                        if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
                                inputmask &= ~(1 << 1);
@@ -276,12 +308,14 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
 
 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
 {
-        return timer->fclk;
+       return timer->fclk;
 }
 
 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
 {
        BUG();
+
+       return 0;
 }
 
 #endif
@@ -406,11 +440,16 @@ void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
                                  unsigned int value)
 {
        omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
+       omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, value);
 }
 
 unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
 {
-       return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
+       unsigned int l;
+
+       l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
+
+       return l;
 }
 
 void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
@@ -420,12 +459,16 @@ void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
 
 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
 {
-       return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
+       unsigned int l;
+
+       l = omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
+
+       return l;
 }
 
 void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
 {
-       return omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
+       omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
 }
 
 int omap_dm_timers_active(void)
@@ -436,9 +479,14 @@ int omap_dm_timers_active(void)
                struct omap_dm_timer *timer;
 
                timer = &dm_timers[i];
+
+               if (!timer->enabled)
+                       continue;
+
                if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
-                   OMAP_TIMER_CTRL_ST)
+                   OMAP_TIMER_CTRL_ST) {
                        return 1;
+               }
        }
        return 0;
 }
@@ -458,6 +506,8 @@ int omap_dm_timer_init(void)
                BUG_ON(dm_source_clocks[i] == NULL);
        }
 #endif
+       if (cpu_is_omap243x())
+               dm_timers[0].phys_base = 0x49018000;
 
        for (i = 0; i < dm_timer_count; i++) {
 #ifdef CONFIG_ARCH_OMAP2