diff options
author | Joel Stanley <joel@jms.id.au> | 2016-07-21 09:43:52 -0400 |
---|---|---|
committer | Daniel Lezcano <daniel.lezcano@linaro.org> | 2016-09-09 08:15:36 -0400 |
commit | 82fdd070873f7ac9b3e37b3d4523b4ae27d02e50 (patch) | |
tree | e6504c03f247e742a460b511b712e0246190c650 | |
parent | 70164742783c371516199271d923731afc40e25e (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.c | 147 |
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 | ||
58 | static void __iomem *base; | 59 | struct moxart_timer { |
59 | static 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 | |||
68 | static inline struct moxart_timer *to_moxart(struct clock_event_device *evt) | ||
69 | { | ||
70 | return container_of(evt, struct moxart_timer, clkevt); | ||
71 | } | ||
60 | 72 | ||
61 | static inline void moxart_disable(struct clock_event_device *evt) | 73 | static 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 | ||
66 | static inline void moxart_enable(struct clock_event_device *evt) | 80 | static 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 | ||
71 | static int moxart_shutdown(struct clock_event_device *evt) | 87 | static int moxart_shutdown(struct clock_event_device *evt) |
@@ -77,13 +93,17 @@ static int moxart_shutdown(struct clock_event_device *evt) | |||
77 | static int moxart_set_oneshot(struct clock_event_device *evt) | 93 | static 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 | ||
84 | static int moxart_set_periodic(struct clock_event_device *evt) | 100 | static 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) | |||
91 | static int moxart_clkevt_next_event(unsigned long cycles, | 111 | static 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 | ||
106 | static 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 | |||
118 | static irqreturn_t moxart_timer_interrupt(int irq, void *dev_id) | 127 | static 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 | ||
125 | static 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 | |||
132 | static int __init moxart_timer_init(struct device_node *node) | 134 | static 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 | } |