diff options
author | Viresh Kumar <viresh.kumar@linaro.org> | 2015-07-06 07:12:01 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2015-09-03 06:07:53 -0400 |
commit | e3280b2a54b38406563d6422685a20172382d365 (patch) | |
tree | b58d3aa7aba40f4922244a47aab6e4c51616eb34 /arch/mips/loongson64 | |
parent | d199da550da30e0946a7554f8a93ef75f66f8005 (diff) |
MIPS: loongson64/timer: Migrate to new 'set-state' interface
Migrate loongson 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.
[ralf@linux-mips.org: Folded in Viresh's followon fix.]
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Huacai Chen <chenhc@lemote.com>
Cc: Michael Opdenacker <michael.opdenacker@free-electrons.com>
Cc: Hongliang Tao <taohl@lemote.com>
Cc: Valentin Rothberg <valentinrothberg@gmail.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: linux-mips@linux-mips.org
Cc: linaro-kernel@lists.linaro.org
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Patchwork: https://patchwork.linux-mips.org/patch/10608/
Patchwork: https://patchwork.linux-mips.org/patch/10883/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/loongson64')
-rw-r--r-- | arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c | 46 | ||||
-rw-r--r-- | arch/mips/loongson64/loongson-3/hpet.c | 117 |
2 files changed, 92 insertions, 71 deletions
diff --git a/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c b/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c index 875037063a80..da77d412514c 100644 --- a/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c +++ b/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c | |||
@@ -51,40 +51,36 @@ void enable_mfgpt0_counter(void) | |||
51 | } | 51 | } |
52 | EXPORT_SYMBOL(enable_mfgpt0_counter); | 52 | EXPORT_SYMBOL(enable_mfgpt0_counter); |
53 | 53 | ||
54 | static void init_mfgpt_timer(enum clock_event_mode mode, | 54 | static int mfgpt_timer_set_periodic(struct clock_event_device *evt) |
55 | struct clock_event_device *evt) | ||
56 | { | 55 | { |
57 | raw_spin_lock(&mfgpt_lock); | 56 | raw_spin_lock(&mfgpt_lock); |
58 | 57 | ||
59 | switch (mode) { | 58 | outw(COMPARE, MFGPT0_CMP2); /* set comparator2 */ |
60 | case CLOCK_EVT_MODE_PERIODIC: | 59 | outw(0, MFGPT0_CNT); /* set counter to 0 */ |
61 | outw(COMPARE, MFGPT0_CMP2); /* set comparator2 */ | 60 | enable_mfgpt0_counter(); |
62 | outw(0, MFGPT0_CNT); /* set counter to 0 */ | 61 | |
63 | enable_mfgpt0_counter(); | ||
64 | break; | ||
65 | |||
66 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
67 | case CLOCK_EVT_MODE_UNUSED: | ||
68 | if (evt->mode == CLOCK_EVT_MODE_PERIODIC || | ||
69 | evt->mode == CLOCK_EVT_MODE_ONESHOT) | ||
70 | disable_mfgpt0_counter(); | ||
71 | break; | ||
72 | |||
73 | case CLOCK_EVT_MODE_ONESHOT: | ||
74 | /* The oneshot mode have very high deviation, Not use it! */ | ||
75 | break; | ||
76 | |||
77 | case CLOCK_EVT_MODE_RESUME: | ||
78 | /* Nothing to do here */ | ||
79 | break; | ||
80 | } | ||
81 | raw_spin_unlock(&mfgpt_lock); | 62 | raw_spin_unlock(&mfgpt_lock); |
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static int mfgpt_timer_shutdown(struct clock_event_device *evt) | ||
67 | { | ||
68 | if (clockevent_state_periodic(evt) || clockevent_state_oneshot(evt)) { | ||
69 | raw_spin_lock(&mfgpt_lock); | ||
70 | disable_mfgpt0_counter(); | ||
71 | raw_spin_unlock(&mfgpt_lock); | ||
72 | } | ||
73 | |||
74 | return 0; | ||
82 | } | 75 | } |
83 | 76 | ||
84 | static struct clock_event_device mfgpt_clockevent = { | 77 | static struct clock_event_device mfgpt_clockevent = { |
85 | .name = "mfgpt", | 78 | .name = "mfgpt", |
86 | .features = CLOCK_EVT_FEAT_PERIODIC, | 79 | .features = CLOCK_EVT_FEAT_PERIODIC, |
87 | .set_mode = init_mfgpt_timer, | 80 | |
81 | /* The oneshot mode have very high deviation, don't use it! */ | ||
82 | .set_state_shutdown = mfgpt_timer_shutdown, | ||
83 | .set_state_periodic = mfgpt_timer_set_periodic, | ||
88 | .irq = CS5536_MFGPT_INTR, | 84 | .irq = CS5536_MFGPT_INTR, |
89 | }; | 85 | }; |
90 | 86 | ||
diff --git a/arch/mips/loongson64/loongson-3/hpet.c b/arch/mips/loongson64/loongson-3/hpet.c index 5c21cd3bd339..bf9f1a77f0e5 100644 --- a/arch/mips/loongson64/loongson-3/hpet.c +++ b/arch/mips/loongson64/loongson-3/hpet.c | |||
@@ -78,55 +78,77 @@ static void hpet_enable_legacy_int(void) | |||
78 | /* Do nothing on Loongson-3 */ | 78 | /* Do nothing on Loongson-3 */ |
79 | } | 79 | } |
80 | 80 | ||
81 | static void hpet_set_mode(enum clock_event_mode mode, | 81 | static int hpet_set_state_periodic(struct clock_event_device *evt) |
82 | struct clock_event_device *evt) | ||
83 | { | 82 | { |
84 | int cfg = 0; | 83 | int cfg; |
85 | 84 | ||
86 | spin_lock(&hpet_lock); | 85 | spin_lock(&hpet_lock); |
87 | switch (mode) { | 86 | |
88 | case CLOCK_EVT_MODE_PERIODIC: | 87 | pr_info("set clock event to periodic mode!\n"); |
89 | pr_info("set clock event to periodic mode!\n"); | 88 | /* stop counter */ |
90 | /* stop counter */ | 89 | hpet_stop_counter(); |
91 | hpet_stop_counter(); | 90 | |
92 | 91 | /* enables the timer0 to generate a periodic interrupt */ | |
93 | /* enables the timer0 to generate a periodic interrupt */ | 92 | cfg = hpet_read(HPET_T0_CFG); |
94 | cfg = hpet_read(HPET_T0_CFG); | 93 | cfg &= ~HPET_TN_LEVEL; |
95 | cfg &= ~HPET_TN_LEVEL; | 94 | cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL | |
96 | cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | | 95 | HPET_TN_32BIT; |
97 | HPET_TN_SETVAL | HPET_TN_32BIT; | 96 | hpet_write(HPET_T0_CFG, cfg); |
98 | hpet_write(HPET_T0_CFG, cfg); | 97 | |
99 | 98 | /* set the comparator */ | |
100 | /* set the comparator */ | 99 | hpet_write(HPET_T0_CMP, HPET_COMPARE_VAL); |
101 | hpet_write(HPET_T0_CMP, HPET_COMPARE_VAL); | 100 | udelay(1); |
102 | udelay(1); | 101 | hpet_write(HPET_T0_CMP, HPET_COMPARE_VAL); |
103 | hpet_write(HPET_T0_CMP, HPET_COMPARE_VAL); | 102 | |
104 | 103 | /* start counter */ | |
105 | /* start counter */ | 104 | hpet_start_counter(); |
106 | hpet_start_counter(); | 105 | |
107 | break; | 106 | spin_unlock(&hpet_lock); |
108 | case CLOCK_EVT_MODE_SHUTDOWN: | 107 | return 0; |
109 | case CLOCK_EVT_MODE_UNUSED: | 108 | } |
110 | cfg = hpet_read(HPET_T0_CFG); | 109 | |
111 | cfg &= ~HPET_TN_ENABLE; | 110 | static int hpet_set_state_shutdown(struct clock_event_device *evt) |
112 | hpet_write(HPET_T0_CFG, cfg); | 111 | { |
113 | break; | 112 | int cfg; |
114 | case CLOCK_EVT_MODE_ONESHOT: | 113 | |
115 | pr_info("set clock event to one shot mode!\n"); | 114 | spin_lock(&hpet_lock); |
116 | cfg = hpet_read(HPET_T0_CFG); | 115 | |
117 | /* set timer0 type | 116 | cfg = hpet_read(HPET_T0_CFG); |
118 | * 1 : periodic interrupt | 117 | cfg &= ~HPET_TN_ENABLE; |
119 | * 0 : non-periodic(oneshot) interrupt | 118 | hpet_write(HPET_T0_CFG, cfg); |
120 | */ | 119 | |
121 | cfg &= ~HPET_TN_PERIODIC; | ||
122 | cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; | ||
123 | hpet_write(HPET_T0_CFG, cfg); | ||
124 | break; | ||
125 | case CLOCK_EVT_MODE_RESUME: | ||
126 | hpet_enable_legacy_int(); | ||
127 | break; | ||
128 | } | ||
129 | spin_unlock(&hpet_lock); | 120 | spin_unlock(&hpet_lock); |
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static int hpet_set_state_oneshot(struct clock_event_device *evt) | ||
125 | { | ||
126 | int cfg; | ||
127 | |||
128 | spin_lock(&hpet_lock); | ||
129 | |||
130 | pr_info("set clock event to one shot mode!\n"); | ||
131 | cfg = hpet_read(HPET_T0_CFG); | ||
132 | /* | ||
133 | * set timer0 type | ||
134 | * 1 : periodic interrupt | ||
135 | * 0 : non-periodic(oneshot) interrupt | ||
136 | */ | ||
137 | cfg &= ~HPET_TN_PERIODIC; | ||
138 | cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; | ||
139 | hpet_write(HPET_T0_CFG, cfg); | ||
140 | |||
141 | spin_unlock(&hpet_lock); | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static int hpet_tick_resume(struct clock_event_device *evt) | ||
146 | { | ||
147 | spin_lock(&hpet_lock); | ||
148 | hpet_enable_legacy_int(); | ||
149 | spin_unlock(&hpet_lock); | ||
150 | |||
151 | return 0; | ||
130 | } | 152 | } |
131 | 153 | ||
132 | static int hpet_next_event(unsigned long delta, | 154 | static int hpet_next_event(unsigned long delta, |
@@ -206,7 +228,10 @@ void __init setup_hpet_timer(void) | |||
206 | cd->name = "hpet"; | 228 | cd->name = "hpet"; |
207 | cd->rating = 320; | 229 | cd->rating = 320; |
208 | cd->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; | 230 | cd->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; |
209 | cd->set_mode = hpet_set_mode; | 231 | cd->set_state_shutdown = hpet_set_state_shutdown; |
232 | cd->set_state_periodic = hpet_set_state_periodic; | ||
233 | cd->set_state_oneshot = hpet_set_state_oneshot; | ||
234 | cd->tick_resume = hpet_tick_resume; | ||
210 | cd->set_next_event = hpet_next_event; | 235 | cd->set_next_event = hpet_next_event; |
211 | cd->irq = HPET_T0_IRQ; | 236 | cd->irq = HPET_T0_IRQ; |
212 | cd->cpumask = cpumask_of(cpu); | 237 | cd->cpumask = cpumask_of(cpu); |