aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Stanley <joel@jms.id.au>2016-07-21 09:43:52 -0400
committerDaniel Lezcano <daniel.lezcano@linaro.org>2016-09-09 08:15:36 -0400
commit82fdd070873f7ac9b3e37b3d4523b4ae27d02e50 (patch)
treee6504c03f247e742a460b511b712e0246190c650
parent70164742783c371516199271d923731afc40e25e (diff)
clocksource/drivers/moxart: Use struct to hold state
Add a struct moxart_timer to hold the driver state, including the irqaction and struct clock_event_device. Most importantly this holds values for enabling and disabling the timer, so future support can be added for devices that use different bits for enable/disable. In preparation for future hardware support we add a MOXART prefix to the existing values. Signed-off-by: Joel Stanley <joel@jms.id.au> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
-rw-r--r--drivers/clocksource/moxart_timer.c147
1 files changed, 86 insertions, 61 deletions
diff --git a/drivers/clocksource/moxart_timer.c b/drivers/clocksource/moxart_timer.c
index a3aaa5658a49..cb0b34786a8e 100644
--- a/drivers/clocksource/moxart_timer.c
+++ b/drivers/clocksource/moxart_timer.c
@@ -21,6 +21,7 @@
21#include <linux/io.h> 21#include <linux/io.h>
22#include <linux/clocksource.h> 22#include <linux/clocksource.h>
23#include <linux/bitops.h> 23#include <linux/bitops.h>
24#include <linux/slab.h>
24 25
25#define TIMER1_BASE 0x00 26#define TIMER1_BASE 0x00
26#define TIMER2_BASE 0x10 27#define TIMER2_BASE 0x10
@@ -36,36 +37,51 @@
36#define TIMER_INTR_MASK 0x38 37#define TIMER_INTR_MASK 0x38
37 38
38/* 39/*
39 * TIMER_CR flags: 40 * Moxart TIMER_CR flags:
40 * 41 *
41 * TIMEREG_CR_*_CLOCK 0: PCLK, 1: EXT1CLK 42 * MOXART_CR_*_CLOCK 0: PCLK, 1: EXT1CLK
42 * TIMEREG_CR_*_INT overflow interrupt enable bit 43 * MOXART_CR_*_INT overflow interrupt enable bit
43 */ 44 */
44#define TIMEREG_CR_1_ENABLE BIT(0) 45#define MOXART_CR_1_ENABLE BIT(0)
45#define TIMEREG_CR_1_CLOCK BIT(1) 46#define MOXART_CR_1_CLOCK BIT(1)
46#define TIMEREG_CR_1_INT BIT(2) 47#define MOXART_CR_1_INT BIT(2)
47#define TIMEREG_CR_2_ENABLE BIT(3) 48#define MOXART_CR_2_ENABLE BIT(3)
48#define TIMEREG_CR_2_CLOCK BIT(4) 49#define MOXART_CR_2_CLOCK BIT(4)
49#define TIMEREG_CR_2_INT BIT(5) 50#define MOXART_CR_2_INT BIT(5)
50#define TIMEREG_CR_3_ENABLE BIT(6) 51#define MOXART_CR_3_ENABLE BIT(6)
51#define TIMEREG_CR_3_CLOCK BIT(7) 52#define MOXART_CR_3_CLOCK BIT(7)
52#define TIMEREG_CR_3_INT BIT(8) 53#define MOXART_CR_3_INT BIT(8)
53#define TIMEREG_CR_COUNT_UP BIT(9) 54#define MOXART_CR_COUNT_UP BIT(9)
54 55
55#define TIMER1_ENABLE (TIMEREG_CR_2_ENABLE | TIMEREG_CR_1_ENABLE) 56#define MOXART_TIMER1_ENABLE (MOXART_CR_2_ENABLE | MOXART_CR_1_ENABLE)
56#define TIMER1_DISABLE (TIMEREG_CR_2_ENABLE) 57#define MOXART_TIMER1_DISABLE (MOXART_CR_2_ENABLE)
57 58
58static void __iomem *base; 59struct moxart_timer {
59static unsigned int clock_count_per_tick; 60 void __iomem *base;
61 unsigned int t1_disable_val;
62 unsigned int t1_enable_val;
63 unsigned int count_per_tick;
64 struct clock_event_device clkevt;
65 struct irqaction act;
66};
67
68static inline struct moxart_timer *to_moxart(struct clock_event_device *evt)
69{
70 return container_of(evt, struct moxart_timer, clkevt);
71}
60 72
61static inline void moxart_disable(struct clock_event_device *evt) 73static inline void moxart_disable(struct clock_event_device *evt)
62{ 74{
63 writel(TIMER1_DISABLE, base + TIMER_CR); 75 struct moxart_timer *timer = to_moxart(evt);
76
77 writel(timer->t1_disable_val, timer->base + TIMER_CR);
64} 78}
65 79
66static inline void moxart_enable(struct clock_event_device *evt) 80static inline void moxart_enable(struct clock_event_device *evt)
67{ 81{
68 writel(TIMER1_ENABLE, base + TIMER_CR); 82 struct moxart_timer *timer = to_moxart(evt);
83
84 writel(timer->t1_enable_val, timer->base + TIMER_CR);
69} 85}
70 86
71static int moxart_shutdown(struct clock_event_device *evt) 87static int moxart_shutdown(struct clock_event_device *evt)
@@ -77,13 +93,17 @@ static int moxart_shutdown(struct clock_event_device *evt)
77static int moxart_set_oneshot(struct clock_event_device *evt) 93static int moxart_set_oneshot(struct clock_event_device *evt)
78{ 94{
79 moxart_disable(evt); 95 moxart_disable(evt);
80 writel(~0, base + TIMER1_BASE + REG_LOAD); 96 writel(~0, to_moxart(evt)->base + TIMER1_BASE + REG_LOAD);
81 return 0; 97 return 0;
82} 98}
83 99
84static int moxart_set_periodic(struct clock_event_device *evt) 100static int moxart_set_periodic(struct clock_event_device *evt)
85{ 101{
86 writel(clock_count_per_tick, base + TIMER1_BASE + REG_LOAD); 102 struct moxart_timer *timer = to_moxart(evt);
103
104 moxart_disable(evt);
105 writel(timer->count_per_tick, timer->base + TIMER1_BASE + REG_LOAD);
106 writel(0, timer->base + TIMER1_BASE + REG_MATCH1);
87 moxart_enable(evt); 107 moxart_enable(evt);
88 return 0; 108 return 0;
89} 109}
@@ -91,30 +111,19 @@ static int moxart_set_periodic(struct clock_event_device *evt)
91static int moxart_clkevt_next_event(unsigned long cycles, 111static int moxart_clkevt_next_event(unsigned long cycles,
92 struct clock_event_device *evt) 112 struct clock_event_device *evt)
93{ 113{
114 struct moxart_timer *timer = to_moxart(evt);
94 u32 u; 115 u32 u;
95 116
96 moxart_disable(evt); 117 moxart_disable(evt);
97 118
98 u = readl(base + TIMER1_BASE + REG_COUNT) - cycles; 119 u = readl(timer->base + TIMER1_BASE + REG_COUNT) - cycles;
99 writel(u, base + TIMER1_BASE + REG_MATCH1); 120 writel(u, timer->base + TIMER1_BASE + REG_MATCH1);
100 121
101 moxart_enable(evt); 122 moxart_enable(evt);
102 123
103 return 0; 124 return 0;
104} 125}
105 126
106static struct clock_event_device moxart_clockevent = {
107 .name = "moxart_timer",
108 .rating = 200,
109 .features = CLOCK_EVT_FEAT_PERIODIC |
110 CLOCK_EVT_FEAT_ONESHOT,
111 .set_state_shutdown = moxart_shutdown,
112 .set_state_periodic = moxart_set_periodic,
113 .set_state_oneshot = moxart_set_oneshot,
114 .tick_resume = moxart_set_oneshot,
115 .set_next_event = moxart_clkevt_next_event,
116};
117
118static irqreturn_t moxart_timer_interrupt(int irq, void *dev_id) 127static irqreturn_t moxart_timer_interrupt(int irq, void *dev_id)
119{ 128{
120 struct clock_event_device *evt = dev_id; 129 struct clock_event_device *evt = dev_id;
@@ -122,21 +131,19 @@ static irqreturn_t moxart_timer_interrupt(int irq, void *dev_id)
122 return IRQ_HANDLED; 131 return IRQ_HANDLED;
123} 132}
124 133
125static struct irqaction moxart_timer_irq = {
126 .name = "moxart-timer",
127 .flags = IRQF_TIMER,
128 .handler = moxart_timer_interrupt,
129 .dev_id = &moxart_clockevent,
130};
131
132static int __init moxart_timer_init(struct device_node *node) 134static int __init moxart_timer_init(struct device_node *node)
133{ 135{
134 int ret, irq; 136 int ret, irq;
135 unsigned long pclk; 137 unsigned long pclk;
136 struct clk *clk; 138 struct clk *clk;
139 struct moxart_timer *timer;
137 140
138 base = of_iomap(node, 0); 141 timer = kzalloc(sizeof(*timer), GFP_KERNEL);
139 if (!base) { 142 if (!timer)
143 return -ENOMEM;
144
145 timer->base = of_iomap(node, 0);
146 if (!timer->base) {
140 pr_err("%s: of_iomap failed\n", node->full_name); 147 pr_err("%s: of_iomap failed\n", node->full_name);
141 return -ENXIO; 148 return -ENXIO;
142 } 149 }
@@ -147,12 +154,6 @@ static int __init moxart_timer_init(struct device_node *node)
147 return -EINVAL; 154 return -EINVAL;
148 } 155 }
149 156
150 ret = setup_irq(irq, &moxart_timer_irq);
151 if (ret) {
152 pr_err("%s: setup_irq failed\n", node->full_name);
153 return ret;
154 }
155
156 clk = of_clk_get(node, 0); 157 clk = of_clk_get(node, 0);
157 if (IS_ERR(clk)) { 158 if (IS_ERR(clk)) {
158 pr_err("%s: of_clk_get failed\n", node->full_name); 159 pr_err("%s: of_clk_get failed\n", node->full_name);
@@ -161,7 +162,31 @@ static int __init moxart_timer_init(struct device_node *node)
161 162
162 pclk = clk_get_rate(clk); 163 pclk = clk_get_rate(clk);
163 164
164 ret = clocksource_mmio_init(base + TIMER2_BASE + REG_COUNT, 165 if (of_device_is_compatible(node, "moxa,moxart-timer")) {
166 timer->t1_enable_val = MOXART_TIMER1_ENABLE;
167 timer->t1_disable_val = MOXART_TIMER1_DISABLE;
168 } else
169 panic("%s: unknown platform\n", node->full_name);
170
171 timer->count_per_tick = DIV_ROUND_CLOSEST(pclk, HZ);
172
173 timer->clkevt.name = node->name;
174 timer->clkevt.rating = 200;
175 timer->clkevt.features = CLOCK_EVT_FEAT_PERIODIC |
176 CLOCK_EVT_FEAT_ONESHOT;
177 timer->clkevt.set_state_shutdown = moxart_shutdown;
178 timer->clkevt.set_state_periodic = moxart_set_periodic;
179 timer->clkevt.set_state_oneshot = moxart_set_oneshot;
180 timer->clkevt.tick_resume = moxart_set_oneshot;
181 timer->clkevt.set_next_event = moxart_clkevt_next_event;
182 timer->clkevt.cpumask = cpumask_of(0);
183 timer->clkevt.irq = irq;
184 timer->act.name = node->name;
185 timer->act.flags = IRQF_TIMER;
186 timer->act.handler = moxart_timer_interrupt;
187 timer->act.dev_id = &timer->clkevt;
188
189 ret = clocksource_mmio_init(timer->base + TIMER2_BASE + REG_COUNT,
165 "moxart_timer", pclk, 200, 32, 190 "moxart_timer", pclk, 200, 32,
166 clocksource_mmio_readl_down); 191 clocksource_mmio_readl_down);
167 if (ret) { 192 if (ret) {
@@ -169,13 +194,14 @@ static int __init moxart_timer_init(struct device_node *node)
169 return ret; 194 return ret;
170 } 195 }
171 196
172 clock_count_per_tick = DIV_ROUND_CLOSEST(pclk, HZ); 197 ret = setup_irq(irq, &timer->act);
173 198 if (ret) {
174 writel(~0, base + TIMER2_BASE + REG_LOAD); 199 pr_err("%s: setup_irq failed\n", node->full_name);
175 writel(TIMEREG_CR_2_ENABLE, base + TIMER_CR); 200 return ret;
201 }
176 202
177 moxart_clockevent.cpumask = cpumask_of(0); 203 writel(~0, timer->base + TIMER2_BASE + REG_LOAD);
178 moxart_clockevent.irq = irq; 204 writel(timer->t1_disable_val, timer->base + TIMER_CR);
179 205
180 /* 206 /*
181 * documentation is not publicly available: 207 * documentation is not publicly available:
@@ -183,8 +209,7 @@ static int __init moxart_timer_init(struct device_node *node)
183 * max_delta 0xfffffffe should be ok because count 209 * max_delta 0xfffffffe should be ok because count
184 * register size is u32 210 * register size is u32
185 */ 211 */
186 clockevents_config_and_register(&moxart_clockevent, pclk, 212 clockevents_config_and_register(&timer->clkevt, pclk, 0x4, 0xfffffffe);
187 0x4, 0xfffffffe);
188 213
189 return 0; 214 return 0;
190} 215}