|
@@ -35,6 +35,7 @@
|
|
|
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
*/
|
|
|
|
|
|
+#include <linux/clk.h>
|
|
|
#include <linux/module.h>
|
|
|
#include <linux/io.h>
|
|
|
#include <linux/device.h>
|
|
@@ -83,10 +84,6 @@ static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
|
|
|
|
|
|
static void omap_timer_restore_context(struct omap_dm_timer *timer)
|
|
|
{
|
|
|
- if (timer->revision == 1)
|
|
|
- __raw_writel(timer->context.tistat, timer->sys_stat);
|
|
|
-
|
|
|
- __raw_writel(timer->context.tisr, timer->irq_stat);
|
|
|
omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
|
|
|
timer->context.twer);
|
|
|
omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
|
|
@@ -121,21 +118,13 @@ static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
|
|
|
|
|
|
static void omap_dm_timer_reset(struct omap_dm_timer *timer)
|
|
|
{
|
|
|
- omap_dm_timer_enable(timer);
|
|
|
- if (timer->pdev->id != 1) {
|
|
|
- omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
|
|
|
- omap_dm_timer_wait_for_reset(timer);
|
|
|
- }
|
|
|
-
|
|
|
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
|
|
|
+ omap_dm_timer_wait_for_reset(timer);
|
|
|
__omap_dm_timer_reset(timer, 0, 0);
|
|
|
- omap_dm_timer_disable(timer);
|
|
|
- timer->posted = 1;
|
|
|
}
|
|
|
|
|
|
int omap_dm_timer_prepare(struct omap_dm_timer *timer)
|
|
|
{
|
|
|
- int ret;
|
|
|
-
|
|
|
/*
|
|
|
* FIXME: OMAP1 devices do not use the clock framework for dmtimers so
|
|
|
* do not call clk_get() for these devices.
|
|
@@ -149,13 +138,15 @@ int omap_dm_timer_prepare(struct omap_dm_timer *timer)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ omap_dm_timer_enable(timer);
|
|
|
+
|
|
|
if (timer->capability & OMAP_TIMER_NEEDS_RESET)
|
|
|
omap_dm_timer_reset(timer);
|
|
|
|
|
|
- ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
|
|
|
+ __omap_dm_timer_enable_posted(timer);
|
|
|
+ omap_dm_timer_disable(timer);
|
|
|
|
|
|
- timer->posted = 1;
|
|
|
- return ret;
|
|
|
+ return omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
|
|
|
}
|
|
|
|
|
|
static inline u32 omap_dm_timer_reserved_systimer(int id)
|
|
@@ -449,7 +440,6 @@ int omap_dm_timer_stop(struct omap_dm_timer *timer)
|
|
|
*/
|
|
|
timer->context.tclr =
|
|
|
omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
|
|
|
- timer->context.tisr = __raw_readl(timer->irq_stat);
|
|
|
omap_dm_timer_disable(timer);
|
|
|
return 0;
|
|
|
}
|
|
@@ -459,7 +449,7 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
|
|
|
{
|
|
|
int ret;
|
|
|
char *parent_name = NULL;
|
|
|
- struct clk *fclk, *parent;
|
|
|
+ struct clk *parent;
|
|
|
struct dmtimer_platform_data *pdata;
|
|
|
|
|
|
if (unlikely(!timer))
|
|
@@ -478,11 +468,8 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
|
|
|
if (pdata && pdata->set_timer_src)
|
|
|
return pdata->set_timer_src(timer->pdev, source);
|
|
|
|
|
|
- fclk = clk_get(&timer->pdev->dev, "fck");
|
|
|
- if (IS_ERR_OR_NULL(fclk)) {
|
|
|
- pr_err("%s: fck not found\n", __func__);
|
|
|
+ if (!timer->fclk)
|
|
|
return -EINVAL;
|
|
|
- }
|
|
|
|
|
|
switch (source) {
|
|
|
case OMAP_TIMER_SRC_SYS_CLK:
|
|
@@ -501,18 +488,15 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
|
|
|
parent = clk_get(&timer->pdev->dev, parent_name);
|
|
|
if (IS_ERR_OR_NULL(parent)) {
|
|
|
pr_err("%s: %s not found\n", __func__, parent_name);
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- ret = clk_set_parent(fclk, parent);
|
|
|
+ ret = clk_set_parent(timer->fclk, parent);
|
|
|
if (IS_ERR_VALUE(ret))
|
|
|
pr_err("%s: failed to set %s as parent\n", __func__,
|
|
|
parent_name);
|
|
|
|
|
|
clk_put(parent);
|
|
|
-out:
|
|
|
- clk_put(fclk);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
@@ -595,8 +579,8 @@ int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
|
|
|
l |= OMAP_TIMER_CTRL_CE;
|
|
|
else
|
|
|
l &= ~OMAP_TIMER_CTRL_CE;
|
|
|
- omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
|
|
|
omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
|
|
|
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
|
|
|
|
|
|
/* Save the context */
|
|
|
timer->context.tclr = l;
|
|
@@ -672,6 +656,37 @@ int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
|
|
|
|
|
|
+/**
|
|
|
+ * omap_dm_timer_set_int_disable - disable timer interrupts
|
|
|
+ * @timer: pointer to timer handle
|
|
|
+ * @mask: bit mask of interrupts to be disabled
|
|
|
+ *
|
|
|
+ * Disables the specified timer interrupts for a timer.
|
|
|
+ */
|
|
|
+int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask)
|
|
|
+{
|
|
|
+ u32 l = mask;
|
|
|
+
|
|
|
+ if (unlikely(!timer))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ omap_dm_timer_enable(timer);
|
|
|
+
|
|
|
+ if (timer->revision == 1)
|
|
|
+ l = __raw_readl(timer->irq_ena) & ~mask;
|
|
|
+
|
|
|
+ __raw_writel(l, timer->irq_dis);
|
|
|
+ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask;
|
|
|
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, l);
|
|
|
+
|
|
|
+ /* Save the context */
|
|
|
+ timer->context.tier &= ~mask;
|
|
|
+ timer->context.twer &= ~mask;
|
|
|
+ omap_dm_timer_disable(timer);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_disable);
|
|
|
+
|
|
|
unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
|
|
|
{
|
|
|
unsigned int l;
|
|
@@ -693,8 +708,7 @@ int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
|
|
|
return -EINVAL;
|
|
|
|
|
|
__omap_dm_timer_write_status(timer, value);
|
|
|
- /* Save the context */
|
|
|
- timer->context.tisr = value;
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
|
|
@@ -797,6 +811,7 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
|
|
|
timer->capability |= OMAP_TIMER_SECURE;
|
|
|
} else {
|
|
|
timer->id = pdev->id;
|
|
|
+ timer->errata = pdata->timer_errata;
|
|
|
timer->capability = pdata->timer_capability;
|
|
|
timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
|
|
|
timer->get_context_loss_count = pdata->get_context_loss_count;
|