summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: ad2d6e0)
raw | patch | inline | side by side (parent: ad2d6e0)
author | Venkateswara Rao Mandela <venkat.mandela@ti.com> | |
Thu, 12 Sep 2019 17:45:12 +0000 (17:45 +0000) | ||
committer | Suman Anna <s-anna@ti.com> | |
Mon, 23 Sep 2019 01:46:55 +0000 (20:46 -0500) |
During late attach, the dmtimers used by remote processors would already
have been configured and running. To prevent the kernel from resetting or
reconfiguring the timers,
- Set the late attach parameter if the timer is already running.
- If late attach flag is set, increment the dmtimer's usage counter
immediately on probe and maintain this state until remoteproc starts
the timer. This prevents kernel power management functionality from
idling and disabling the dmtimers.
- If late attach flag is set, also prevent the dmtimer configuration
code from modifying the dmtimer registers.
The late attach flag in the omap_dm_timer structure is cleared on timer
start to allow normal operation to resume.
Signed-off-by: Venkateswara Rao Mandela <venkat.mandela@ti.com>
Signed-off-by: Angela Stegmaier <angelabaker@ti.com>
Signed-off-by: Suman Anna <s-anna@ti.com>
Signed-off-by: Shravan Karthik <shravan.karthik@ti.com>
Signed-off-by: Keerthy <j-keerthy@ti.com>
have been configured and running. To prevent the kernel from resetting or
reconfiguring the timers,
- Set the late attach parameter if the timer is already running.
- If late attach flag is set, increment the dmtimer's usage counter
immediately on probe and maintain this state until remoteproc starts
the timer. This prevents kernel power management functionality from
idling and disabling the dmtimers.
- If late attach flag is set, also prevent the dmtimer configuration
code from modifying the dmtimer registers.
The late attach flag in the omap_dm_timer structure is cleared on timer
start to allow normal operation to resume.
Signed-off-by: Venkateswara Rao Mandela <venkat.mandela@ti.com>
Signed-off-by: Angela Stegmaier <angelabaker@ti.com>
Signed-off-by: Suman Anna <s-anna@ti.com>
Signed-off-by: Shravan Karthik <shravan.karthik@ti.com>
Signed-off-by: Keerthy <j-keerthy@ti.com>
drivers/clocksource/timer-ti-dm.c | patch | blob | history | |
include/clocksource/timer-ti-dm.h | patch | blob | history | |
include/linux/platform_data/dmtimer-omap.h | patch | blob | history |
index d7adbc102649619bef817a522e35934d2612a111..b2b7613f7602aa3bc91a36c132c8cc17bdb07e0a 100644 (file)
static void omap_timer_restore_context(struct omap_dm_timer *timer)
{
+ /*
+ * Do not restore the context during late attach. Kernel data
+ * structure is not in sync with the register settings of the timer.
+ */
+ if (timer->late_attach)
+ return;
+
omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
timer->context.twer);
omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
return ret;
}
+static int omap_dm_timer_is_enabled(struct omap_dm_timer *timer)
+{
+ u32 val;
+
+ val = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+
+ /* Check if timer ST bit is set or the Counter register is loaded */
+ if (val & OMAP_TIMER_CTRL_ST ||
+ omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG))
+ return 1;
+ else
+ return 0;
+}
+
static void omap_dm_timer_enable(struct omap_dm_timer *timer)
{
int c;
__omap_dm_timer_enable_posted(timer);
omap_dm_timer_disable(timer);
+ /*
+ * During late attach, do not set the timer source during prepare
+ * as the timer might be clocked from a different source. It will
+ * be set properly from remoteproc.
+ */
+ if (timer->late_attach)
+ return 0;
+
rc = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
return rc;
/* Save the context */
timer->context.tclr = l;
+
+ /*
+ * Now that timer has been started, call pm_runtime_put_noidle to
+ * balance the pm_runtime device usage count to the proper value as
+ * the regular case, and reset the late_attach flag.
+ */
+ if (timer->late_attach)
+ pm_runtime_put_noidle(&timer->pdev->dev);
+ timer->late_attach = 0;
+
return 0;
}
@@ -543,10 +582,18 @@ static int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
l |= OMAP_TIMER_CTRL_AR;
else
l &= ~OMAP_TIMER_CTRL_AR;
- omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
- omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
- omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
+ /*
+ * If late attach is enabled, do not modify the dmtimer registers.
+ * The registers would have been configured already.
+ */
+ if (!timer->late_attach) {
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
+
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
+ }
+
/* Save the context */
timer->context.tclr = l;
timer->context.tldr = load;
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
if (autoreload) {
l |= OMAP_TIMER_CTRL_AR;
- omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
+ /*
+ * If late attach is enabled, do not modify the dmtimer
+ * registers. The registers would have been configured
+ * already.
+ */
+ if (!timer->late_attach)
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG,
+ load);
} else {
l &= ~OMAP_TIMER_CTRL_AR;
}
l |= OMAP_TIMER_CTRL_ST;
- __omap_dm_timer_load_start(timer, l, load, timer->posted);
+ if (!timer->late_attach)
+ __omap_dm_timer_load_start(timer, l, load, timer->posted);
/* Save the context */
timer->context.tclr = l;
goto err_get_sync;
}
__omap_dm_timer_init_regs(timer);
+
+ if (omap_dm_timer_is_enabled(timer))
+ timer->late_attach = 1;
+ /*
+ * Increase the pm_runtime usage count and prevent kernel power
+ * management from idling or disabling the timer.
+ */
+ if (timer->late_attach)
+ pm_runtime_get_noresume(dev);
+
pm_runtime_put(dev);
}
if (!strcmp(dev_name(&timer->pdev->dev),
dev_name(&pdev->dev))) {
list_del(&timer->node);
+ /*
+ * Reset device usage counter if late_attach is still
+ * set
+ */
+ if (timer->late_attach)
+ pm_runtime_put_noidle(&timer->pdev->dev);
ret = 0;
break;
}
.free = omap_dm_timer_free,
.enable = omap_dm_timer_enable,
.disable = omap_dm_timer_disable,
+ .is_enabled = omap_dm_timer_is_enabled,
.get_fclk = omap_dm_timer_get_fclk,
.start = omap_dm_timer_start,
.stop = omap_dm_timer_stop,
index 7d9598dc578d3d039a5fc2bd821024e425f71ed6..a2654f4f3cbcc2201ed56d20771286f532890d0f 100644 (file)
u32 errata;
struct platform_device *pdev;
struct list_head node;
+ u32 late_attach;
};
int omap_dm_timer_reserve_systimer(int id);
diff --git a/include/linux/platform_data/dmtimer-omap.h b/include/linux/platform_data/dmtimer-omap.h
index 757a0f9e26f9a7b6c4b1da910fac2efcee9c658a..1f6d3b038ae0e07a4319f310338d934c7a657965 100644 (file)
int (*free)(struct omap_dm_timer *timer);
void (*enable)(struct omap_dm_timer *timer);
+ int (*is_enabled)(struct omap_dm_timer *timer);
void (*disable)(struct omap_dm_timer *timer);
int (*get_irq)(struct omap_dm_timer *timer);