[COMMON] clocksource: exynos_mct: change H/W control sequence
authorHosung Kim <hosung0.kim@samsung.com>
Sun, 9 Apr 2017 11:06:05 +0000 (20:06 +0900)
committerJaehyoung Choi <jkkkkk.choi@samsung.com>
Wed, 2 May 2018 02:15:47 +0000 (11:15 +0900)
This commit changes H/W control sequence of a majority in
exynos_mct codes. Because changed codes are mass-produced already
but mainline code is not so.

Change-Id: I168e289b06eddf4a53df66c8c11a4df52d11fd4d
Signed-off-by: Hosung Kim <hosung0.kim@samsung.com>
drivers/clocksource/exynos_mct.c

index d828795a612cdede5bbbe2b0002a48c8f1c63b8b..fcb850715c5d9732a074ad9482ac57ea7e3c66ef 100644 (file)
@@ -357,26 +357,25 @@ static int exynos4_clockevent_init(void)
 static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick);
 
 /* Clock event handling */
-static void exynos4_mct_tick_stop(struct mct_clock_event_device *mevt)
+static void exynos4_mct_tick_stop(struct mct_clock_event_device *mevt, int force)
 {
        unsigned long tmp;
-       unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START;
-       unsigned long offset = mevt->base + MCT_L_TCON_OFFSET;
 
-       tmp = readl_relaxed(reg_base + offset);
-       if (tmp & mask) {
-               tmp &= ~mask;
-               exynos4_mct_write(tmp, offset);
+       /* clear MCT local interrupt */
+       exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
+
+       if (force || !clockevent_state_periodic(&mevt->evt)) {
+               tmp = readl_relaxed(reg_base + mevt->base + MCT_L_TCON_OFFSET);
+               tmp &= ~(MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START | MCT_L_TCON_INTERVAL_MODE);
+               exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET);
        }
 }
 
-static void exynos4_mct_tick_start(unsigned long cycles,
+static void exynos4_mct_tick_start(unsigned long cycles, int periodic,
                                   struct mct_clock_event_device *mevt)
 {
        unsigned long tmp;
 
-       exynos4_mct_tick_stop(mevt);
-
        tmp = (1 << 31) | cycles;       /* MCT_L_UPDATE_ICNTB */
 
        /* update interrupt count buffer */
@@ -385,9 +384,11 @@ static void exynos4_mct_tick_start(unsigned long cycles,
        /* enable MCT tick interrupt */
        exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET);
 
-       tmp = readl_relaxed(reg_base + mevt->base + MCT_L_TCON_OFFSET);
-       tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START |
-              MCT_L_TCON_INTERVAL_MODE;
+       tmp = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START;
+
+       if (periodic || clockevent_state_periodic(&mevt->evt))
+               tmp |= MCT_L_TCON_INTERVAL_MODE;
+
        exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET);
 }
 
@@ -397,7 +398,7 @@ static int exynos4_tick_set_next_event(unsigned long cycles,
        struct mct_clock_event_device *mevt;
 
        mevt = container_of(evt, struct mct_clock_event_device, evt);
-       exynos4_mct_tick_start(cycles, mevt);
+       exynos4_mct_tick_start(cycles, 0, mevt);
        return 0;
 }
 
@@ -406,7 +407,7 @@ static int set_state_shutdown(struct clock_event_device *evt)
        struct mct_clock_event_device *mevt;
 
        mevt = container_of(evt, struct mct_clock_event_device, evt);
-       exynos4_mct_tick_stop(mevt);
+       exynos4_mct_tick_stop(mevt, 1);
        return 0;
 }
 
@@ -418,32 +419,17 @@ static int set_state_periodic(struct clock_event_device *evt)
        mevt = container_of(evt, struct mct_clock_event_device, evt);
        cycles_per_jiffy = (((unsigned long long)NSEC_PER_SEC / HZ * evt->mult)
                            >> evt->shift);
-       exynos4_mct_tick_stop(mevt);
-       exynos4_mct_tick_start(cycles_per_jiffy, mevt);
+       exynos4_mct_tick_stop(mevt, 1);
+       exynos4_mct_tick_start(cycles_per_jiffy, 1, mevt);
        return 0;
 }
 
-static void exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
-{
-       /*
-        * This is for supporting oneshot mode.
-        * Mct would generate interrupt periodically
-        * without explicit stopping.
-        */
-       if (!clockevent_state_periodic(&mevt->evt))
-               exynos4_mct_tick_stop(mevt);
-
-       /* Clear the MCT tick interrupt */
-       if (readl_relaxed(reg_base + mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1)
-               exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
-}
-
 static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
 {
        struct mct_clock_event_device *mevt = dev_id;
        struct clock_event_device *evt = &mevt->evt;
 
-       exynos4_mct_tick_clear(mevt);
+       exynos4_mct_tick_stop(mevt, 0);
 
        evt->event_handler(evt);