summaryrefslogtreecommitdiffstats
path: root/arch/mips/loongson64
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2015-07-06 07:12:01 -0400
committerRalf Baechle <ralf@linux-mips.org>2015-09-03 06:07:53 -0400
commite3280b2a54b38406563d6422685a20172382d365 (patch)
treeb58d3aa7aba40f4922244a47aab6e4c51616eb34 /arch/mips/loongson64
parentd199da550da30e0946a7554f8a93ef75f66f8005 (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.c46
-rw-r--r--arch/mips/loongson64/loongson-3/hpet.c117
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}
52EXPORT_SYMBOL(enable_mfgpt0_counter); 52EXPORT_SYMBOL(enable_mfgpt0_counter);
53 53
54static void init_mfgpt_timer(enum clock_event_mode mode, 54static 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
66static 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
84static struct clock_event_device mfgpt_clockevent = { 77static 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
81static void hpet_set_mode(enum clock_event_mode mode, 81static 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; 110static 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
124static 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
145static 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
132static int hpet_next_event(unsigned long delta, 154static 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);