@@ -1765,11 +1765,7 @@ static struct omap_clk omap2420_clks[] = {
CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_242X),
/* general l4 interface ck, multi-parent functional clk */
CLK(NULL, "gpt1_ick", &gpt1_ick, CK_242X),
- /*
- * gpt1 will be modified in subsequent patch when dmtimers
- * will be fully converted to platform device
- */
- CLK(NULL, "gpt1_fck", &gpt1_fck, CK_242X),
+ CLK("dmtimer.0", "fck", &gpt1_fck, CK_242X),
CLK(NULL, "gpt2_ick", &gpt2_ick, CK_242X),
CLK("dmtimer.1", "fck", &gpt2_fck, CK_242X),
CLK(NULL, "gpt3_ick", &gpt3_ick, CK_242X),
@@ -1851,11 +1851,7 @@ static struct omap_clk omap2430_clks[] = {
CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_243X),
/* general l4 interface ck, multi-parent functional clk */
CLK(NULL, "gpt1_ick", &gpt1_ick, CK_243X),
- /*
- * gpt1 will be modified in subsequent patch when dmtimers
- * will be fully converted to platform device
- */
- CLK(NULL, "gpt1_fck", &gpt1_fck, CK_243X),
+ CLK("dmtimer.0", "fck", &gpt1_fck, CK_243X),
CLK(NULL, "gpt2_ick", &gpt2_ick, CK_243X),
CLK("dmtimer.1", "fck", &gpt2_fck, CK_243X),
CLK(NULL, "gpt3_ick", &gpt3_ick, CK_243X),
@@ -3334,11 +3334,7 @@ static struct omap_clk omap3xxx_clks[] = {
CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2 | CK_AM35XX),
CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2 | CK_AM35XX),
CLK(NULL, "usim_fck", &usim_fck, CK_3430ES2),
- /*
- * gpt1 will be changed in subsequent patch when dmtimer
- * is fully converted to platform device.
- */
- CLK(NULL, "gpt1_fck", &gpt1_fck, CK_3XXX),
+ CLK("dmtimer.0", "fck", &gpt1_fck, CK_3XXX),
CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_3XXX),
CLK(NULL, "gpio1_dbck", &gpio1_dbck, CK_3XXX),
CLK("omap_wdt", "fck", &wdt2_fck, CK_3XXX),
@@ -2574,11 +2574,7 @@ static struct omap_clk omap44xx_clks[] = {
CLK(NULL, "smartreflex_core_fck", &smartreflex_core_fck, CK_443X),
CLK(NULL, "smartreflex_iva_fck", &smartreflex_iva_fck, CK_443X),
CLK(NULL, "smartreflex_mpu_fck", &smartreflex_mpu_fck, CK_443X),
- /*
- * gpt1 will be changed in subsequent patch when dmtimer
- * will be fully converted to platform device.
- */
- CLK(NULL, "gpt1_fck", &timer1_fck, CK_443X),
+ CLK("dmtimer.0", "fck", &timer1_fck, CK_443X),
CLK("dmtimer.9", "fck", &timer10_fck, CK_443X),
CLK("dmtimer.10", "fck", &timer11_fck, CK_443X),
CLK("dmtimer.1", "fck", &timer2_fck, CK_443X),
@@ -45,6 +45,7 @@
#include "clockdomains.h"
#include <plat/omap_hwmod.h>
+#include "dmtimer.h"
/*
* The machine specific code may provide the extra mapping besides the
@@ -350,4 +351,5 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
_omap2_init_reprogram_sdrc();
}
gpmc_init();
+ omap2_dm_timer_early_init();
}
@@ -231,7 +231,6 @@ static void __init omap2_gp_timer_init(void)
twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256);
BUG_ON(!twd_base);
#endif
- omap_dm_timer_init();
omap2_gp_clockevent_init();
omap2_gp_clocksource_init();
@@ -48,6 +48,7 @@
#include <linux/pm_runtime.h>
#include <plat/dmtimer.h>
#include <mach/irqs.h>
+#include <linux/err.h>
/* register offsets */
#define _OMAP_TIMER_ID_OFFSET 0x00
@@ -84,67 +85,6 @@
#define _OMAP_TIMER_TICK_INT_MASK_SET_OFFSET 0x54 /* TOCR, 34xx only */
#define _OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET 0x58 /* TOWR, 34xx only */
-
-#define OMAP_TIMER_ID_REG (_OMAP_TIMER_ID_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_OCP_CFG_REG (_OMAP_TIMER_OCP_CFG_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_SYS_STAT_REG (_OMAP_TIMER_SYS_STAT_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_STAT_REG (_OMAP_TIMER_STAT_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_INT_EN_REG (_OMAP_TIMER_INT_EN_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_WAKEUP_EN_REG (_OMAP_TIMER_WAKEUP_EN_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_CTRL_REG (_OMAP_TIMER_CTRL_OFFSET \
- | (WP_TCLR << WPSHIFT))
-
-#define OMAP_TIMER_COUNTER_REG (_OMAP_TIMER_COUNTER_OFFSET \
- | (WP_TCRR << WPSHIFT))
-
-#define OMAP_TIMER_LOAD_REG (_OMAP_TIMER_LOAD_OFFSET \
- | (WP_TLDR << WPSHIFT))
-
-#define OMAP_TIMER_TRIGGER_REG (_OMAP_TIMER_TRIGGER_OFFSET \
- | (WP_TTGR << WPSHIFT))
-
-#define OMAP_TIMER_WRITE_PEND_REG (_OMAP_TIMER_WRITE_PEND_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_MATCH_REG (_OMAP_TIMER_MATCH_OFFSET \
- | (WP_TMAR << WPSHIFT))
-
-#define OMAP_TIMER_CAPTURE_REG (_OMAP_TIMER_CAPTURE_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_IF_CTRL_REG (_OMAP_TIMER_IF_CTRL_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_CAPTURE2_REG (_OMAP_TIMER_CAPTURE2_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_TICK_POS_REG (_OMAP_TIMER_TICK_POS_OFFSET \
- | (WP_TPIR << WPSHIFT))
-
-#define OMAP_TIMER_TICK_NEG_REG (_OMAP_TIMER_TICK_NEG_OFFSET \
- | (WP_TNIR << WPSHIFT))
-
-#define OMAP_TIMER_TICK_COUNT_REG (_OMAP_TIMER_TICK_COUNT_OFFSET \
- | (WP_TCVR << WPSHIFT))
-
-#define OMAP_TIMER_TICK_INT_MASK_SET_REG \
- (_OMAP_TIMER_TICK_INT_MASK_SET_OFFSET | (WP_TOCR << WPSHIFT))
-
-#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG \
- (_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
-
struct omap_dm_timer {
int id;
unsigned long fclk_rate;
@@ -265,34 +205,48 @@ static struct clk **dm_source_clocks;
static LIST_HEAD(omap_timer_list);
static DEFINE_SPINLOCK(dm_timer_lock);
-/*
- * Reads timer registers in posted and non-posted mode. The posted mode bit
- * is encoded in reg. Note that in posted mode write pending bit must be
- * checked. Otherwise a read of a non completed write will produce an error.
+/**
+ * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
+ * @timer: timer pointer over which read operation to perform
+ * @reg: lowest byte holds the register offset
+ *
+ * The posted mode bit is encoded in reg. Note that in posted mode write
+ * pending bit must be checked. Otherwise a read of a non completed write
+ * will produce an error.
*/
-static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
+static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u8 reg)
{
+ struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+
if (timer->posted)
- while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
- & (reg >> WPSHIFT))
+ while (readl(timer->io_base +
+ ((pdata->reg_map[OMAP_TIMER_WRITE_PEND_REG]) & 0xff))
+ & (pdata->reg_map[reg] >> WPSHIFT))
cpu_relax();
- return readl(timer->io_base + (reg & 0xff));
+ return readl(timer->io_base + (pdata->reg_map[reg] & 0xff));
}
-/*
- * Writes timer registers in posted and non-posted mode. The posted mode bit
- * is encoded in reg. Note that in posted mode the write pending bit must be
- * checked. Otherwise a write on a register which has a pending write will be
- * lost.
+/**
+ * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
+ * @timer: timer pointer over which write operation is to perform
+ * @reg: lowest byte holds the register offset
+ * @value: data to write into the register
+ *
+ * The posted mode bit is encoded in reg. Note that in posted mode the write
+ * pending bit must be checked. Otherwise a write on a register which has a
+ * pending write will be lost.
*/
-static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
+static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u8 reg,
u32 value)
{
+ struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+
if (timer->posted)
- while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
- & (reg >> WPSHIFT))
+ while (readl(timer->io_base +
+ ((pdata->reg_map[OMAP_TIMER_WRITE_PEND_REG]) & 0xff))
+ & (pdata->reg_map[reg] >> WPSHIFT))
cpu_relax();
- writel(value, timer->io_base + (reg & 0xff));
+ writel(value, timer->io_base + (pdata->reg_map[reg] & 0xff));
}
static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
@@ -397,15 +351,18 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_free);
void omap_dm_timer_enable(struct omap_dm_timer *timer)
{
+ struct clk *timer_clk;
+
if (timer->enabled)
return;
-#ifdef CONFIG_ARCH_OMAP2PLUS
- if (cpu_class_is_omap2()) {
- clk_enable(timer->fclk);
- clk_enable(timer->iclk);
- }
-#endif
+ timer_clk = clk_get(&timer->pdev->dev, "fck");
+ if (IS_ERR(timer_clk)) {
+ dev_err(&timer->pdev->dev,
+ "ERROR: no clk pointer to enable\n");
+ return;
+ } else
+ clk_enable(timer_clk);
timer->enabled = 1;
}
@@ -413,15 +370,18 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
void omap_dm_timer_disable(struct omap_dm_timer *timer)
{
+ struct clk *timer_clk;
+
if (!timer->enabled)
return;
-#ifdef CONFIG_ARCH_OMAP2PLUS
- if (cpu_class_is_omap2()) {
- clk_disable(timer->iclk);
- clk_disable(timer->fclk);
- }
-#endif
+ timer_clk = clk_get(&timer->pdev->dev, "fck");
+ if (IS_ERR(timer_clk)) {
+ dev_err(&timer->pdev->dev,
+ "ERROR: no clk pointer to disable\n");
+ return;
+ } else
+ clk_disable(timer_clk);
timer->enabled = 0;
}
@@ -473,7 +433,12 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
{
- return timer->fclk;
+ struct clk *timer_clk = clk_get(&timer->pdev->dev, "fck");
+
+ if (IS_ERR(timer_clk))
+ return ERR_PTR((int)timer_clk);
+ else
+ return timer_clk;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
@@ -520,7 +485,7 @@ void omap_dm_timer_stop(struct omap_dm_timer *timer)
* Wait for functional clock period x 3.5 to make sure that
* timer is stopped
*/
- udelay(3500000 / clk_get_rate(timer->fclk) + 1);
+ udelay(3500000 / timer->fclk_rate + 1);
#endif
}
/* Ack possibly pending interrupt */
@@ -529,27 +494,41 @@ void omap_dm_timer_stop(struct omap_dm_timer *timer)
}
EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
-
-
-
-
int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
{
- int ret = -EINVAL;
+ int ret = 0;
+ struct clk *timer_clk = NULL;
+ struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
- if (source < 0 || source >= 3)
+ if (source < 0 || source >= NR_CLK_SOURCES)
return -EINVAL;
-#ifdef CONFIG_ARCH_OMAP1
- if (pdata->set_timer_src)
- ret = pdata->set_timer_src(timer->pdev, source);
-#else
- clk_disable(timer->fclk);
- ret = clk_set_parent(timer->fclk, dm_source_clocks[source]);
- clk_enable(timer->fclk);
-#endif
+ timer_clk = clk_get(&timer->pdev->dev, "fck");
+ if (IS_ERR(timer_clk)) {
+ dev_err(&timer->pdev->dev,
+ "ERROR: no clk pointer to disable\n");
+ return -EINVAL;
+ } else
+ clk_disable(timer_clk); /* enabled in hwmod */
/*
+ * change the timer clock source and
+ * store the fclk_rate of the new clock source.
+ */
+ ret = pdata->set_timer_src(timer->pdev, source);
+ if (!ret)
+ timer->fclk_rate = clk_get_rate(omap_dm_timer_get_fclk(timer));
+
+ /* enable timer clock again after timer clock source change */
+ if (unlikely(pdata->is_early_init))
+ clk_enable(timer_clk);
+ else {
+ if (pm_runtime_get_sync(&timer->pdev->dev))
+ dev_warn(&timer->pdev->dev,
+ "%s: pm_runtime_get_sync FAILED\n",
+ __func__);
+ }
+ /*
* When the functional clock disappears, too quick writes seem
* to cause an abort. XXX Is this still necessary?
*/
@@ -935,6 +914,7 @@ static void __exit omap_dmtimer_driver_exit(void)
platform_driver_unregister(&omap_dmtimer_driver);
}
+early_platform_init("earlytimer", &omap_dmtimer_driver);
module_init(omap_dmtimer_driver_init);
module_exit(omap_dmtimer_driver_exit);