Hi Viresh,
(adding samsung list and Krzysztof to c/c)
Please don't forget to send patches to platform list and platform maintainers.
On Thu, Jun 18, 2015 at 1:54 PM, Viresh Kumar viresh.kumar@linaro.org wrote:
Migrate exynos_mct driver to the new 'set-state' interface provided by clockevents core, the earlier 'set-mode' interface is marked obsolete now.
This also enables us to implement callbacks for new states of clockevent devices, for example: ONESHOT_STOPPED.
Cc: Kukjin Kim kgene.kim@samsung.com Signed-off-by: Viresh Kumar viresh.kumar@linaro.org
drivers/clocksource/exynos_mct.c | 85 +++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 45 deletions(-)
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index 935b05936dbd..82e060cb7b95 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c @@ -257,15 +257,14 @@ static void exynos4_mct_comp0_stop(void) exynos4_mct_write(0, EXYNOS4_MCT_G_INT_ENB); }
-static void exynos4_mct_comp0_start(enum clock_event_mode mode,
unsigned long cycles)
+static void exynos4_mct_comp0_start(bool periodic, unsigned long cycles) { unsigned int tcon; cycle_t comp_cycle;
tcon = readl_relaxed(reg_base + EXYNOS4_MCT_G_TCON);
if (mode == CLOCK_EVT_MODE_PERIODIC) {
if (periodic) { tcon |= MCT_G_TCON_COMP0_AUTO_INC; exynos4_mct_write(cycles, EXYNOS4_MCT_G_COMP0_ADD_INCR); }
@@ -283,38 +282,38 @@ static void exynos4_mct_comp0_start(enum clock_event_mode mode, static int exynos4_comp_set_next_event(unsigned long cycles, struct clock_event_device *evt) {
exynos4_mct_comp0_start(evt->mode, cycles);
exynos4_mct_comp0_start(false, cycles); return 0;
}
-static void exynos4_comp_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
+static int mct_set_state_shutdown(struct clock_event_device *evt) {
unsigned long cycles_per_jiffy; exynos4_mct_comp0_stop();
return 0;
+}
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
cycles_per_jiffy =
(((unsigned long long) NSEC_PER_SEC / HZ * evt->mult) >> evt->shift);
exynos4_mct_comp0_start(mode, cycles_per_jiffy);
break;
+static int mct_set_state_periodic(struct clock_event_device *evt) +{
unsigned long cycles_per_jiffy;
case CLOCK_EVT_MODE_ONESHOT:
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_RESUME:
break;
}
cycles_per_jiffy = (((unsigned long long)NSEC_PER_SEC / HZ * evt->mult)
>> evt->shift);
exynos4_mct_comp0_stop();
exynos4_mct_comp0_start(true, cycles_per_jiffy);
return 0;
}
static struct clock_event_device mct_comp_device = {
.name = "mct-comp",
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
.rating = 250,
.set_next_event = exynos4_comp_set_next_event,
.set_mode = exynos4_comp_set_mode,
.name = "mct-comp",
.features = CLOCK_EVT_FEAT_PERIODIC |
CLOCK_EVT_FEAT_ONESHOT,
.rating = 250,
.set_next_event = exynos4_comp_set_next_event,
.set_state_periodic = mct_set_state_periodic,
.set_state_shutdown = mct_set_state_shutdown,
.set_state_oneshot = mct_set_state_shutdown,
.tick_resume = mct_set_state_shutdown,
};
static irqreturn_t exynos4_mct_comp_isr(int irq, void *dev_id) @@ -390,39 +389,32 @@ static int exynos4_tick_set_next_event(unsigned long cycles, return 0; }
-static inline void exynos4_tick_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
+static int set_state_shutdown(struct clock_event_device *evt) +{
exynos4_mct_tick_stop(this_cpu_ptr(&percpu_mct_tick));
Passed evt pointer isn't used and instead you're going to locate percpu_mct_tick struct knowing current cpu number offset. What do you think, since evt is embedded into percpu_mct_tick structure then maybe it will be cheaper to calculate percpu_mct_tick using container_of()?
struct mct_clock_event_device *mevt; mevt = container_of(evt, struct mct_clock_event_device, evt);
return 0;
+}
+static int set_state_periodic(struct clock_event_device *evt) { struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick); unsigned long cycles_per_jiffy;
cycles_per_jiffy = (((unsigned long long)NSEC_PER_SEC / HZ * evt->mult)
>> evt->shift); exynos4_mct_tick_stop(mevt);
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
cycles_per_jiffy =
(((unsigned long long) NSEC_PER_SEC / HZ * evt->mult) >> evt->shift);
exynos4_mct_tick_start(cycles_per_jiffy, mevt);
break;
case CLOCK_EVT_MODE_ONESHOT:
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_RESUME:
break;
}
exynos4_mct_tick_start(cycles_per_jiffy, mevt);
return 0;
}
static void exynos4_mct_tick_clear(struct mct_clock_event_device *mevt) {
struct clock_event_device *evt = &mevt->evt;
/* * This is for supporting oneshot mode. * Mct would generate interrupt periodically * without explicit stopping. */
if (evt->mode != CLOCK_EVT_MODE_PERIODIC)
if (!clockevent_state_periodic(&mevt->evt)) exynos4_mct_tick_stop(mevt); /* Clear the MCT tick interrupt */
@@ -455,7 +447,10 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt) evt->name = mevt->name; evt->cpumask = cpumask_of(cpu); evt->set_next_event = exynos4_tick_set_next_event;
evt->set_mode = exynos4_tick_set_mode;
evt->set_state_periodic = set_state_periodic;
evt->set_state_shutdown = set_state_shutdown;
evt->set_state_oneshot = set_state_shutdown;
evt->tick_resume = set_state_shutdown;
Do i correctly understand that during massive hot-plug cpu events (i guess that will lead to CPU_STARING notification) on power management this *_timer_setup() function will be called? And here code performs setting of rather constant values and copying. You're going to increase number of such strange assignments.
Well, just lazy-thinking. Can we do something like this:
for_each_possible_cpu(cpu) { exynos4_local_timer_setup_prepare(&per_cpu(percpu_mct_tick, cpu).evt, cpu); }
somewhere in exynos_mct init functions and assign most of these values for each evt structure? And make *_timer_setup() function lighter moving some code to prepare/init functions. If it makes any sense i can take a look and try to prepare patch.
evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; evt->rating = 450;
@@ -482,7 +477,7 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt)
static void exynos4_local_timer_stop(struct clock_event_device *evt) {
evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
evt->set_state_shutdown(evt); if (mct_int_type == MCT_INT_SPI) free_irq(evt->irq, this_cpu_ptr(&percpu_mct_tick)); else
--
Do you need testers? I can test it on odroid-xu3.
Can't find in emails similar patch for ARM arch timer. Any plans about it? Or if it's already converted to 'set-state' then could you please share a link?
Thanks and best regards, Alexey Klimov