| 1 | |
| 2 | * Copyright (C) 2013-2014 Altera Corporation
|
| 3 | * Copyright (C) 2010 Tobias Klauser <[email protected]>
|
| 4 | * Copyright (C) 2004 Microtronix Datacom Ltd.
|
| 5 | *
|
| 6 | * This file is subject to the terms and conditions of the GNU General Public
|
| 7 | * License. See the file "COPYING" in the main directory of this archive
|
| 8 | * for more details.
|
| 9 |
|
| 10 |
|
| 11 | #include <linux/export.h>
|
| 12 | #include <linux/interrupt.h>
|
| 13 | #include <linux/clockchips.h>
|
| 14 | #include <linux/clocksource.h>
|
| 15 | #include <linux/delay.h>
|
| 16 | #include <linux/of.h>
|
| 17 | #include <linux/of_address.h>
|
| 18 | #include <linux/of_irq.h>
|
| 19 | #include <linux/io.h>
|
| 20 | #include <linux/slab.h>
|
| 21 |
|
| 22 | #define ALTR_TIMER_COMPATIBLE "altr,timer-1.0"
|
| 23 |
|
| 24 | #define ALTERA_TIMER_STATUS_REG 0
|
| 25 | #define ALTERA_TIMER_CONTROL_REG 4
|
| 26 | #define ALTERA_TIMER_PERIODL_REG 8
|
| 27 | #define ALTERA_TIMER_PERIODH_REG 12
|
| 28 | #define ALTERA_TIMER_SNAPL_REG 16
|
| 29 | #define ALTERA_TIMER_SNAPH_REG 20
|
| 30 |
|
| 31 | #define ALTERA_TIMER_CONTROL_ITO_MSK (0x1)
|
| 32 | #define ALTERA_TIMER_CONTROL_CONT_MSK (0x2)
|
| 33 | #define ALTERA_TIMER_CONTROL_START_MSK (0x4)
|
| 34 | #define ALTERA_TIMER_CONTROL_STOP_MSK (0x8)
|
| 35 |
|
| 36 | struct nios2_timer {
|
| 37 | void __iomem *base;
|
| 38 | unsigned long freq;
|
| 39 | };
|
| 40 |
|
| 41 | struct nios2_clockevent_dev {
|
| 42 | struct nios2_timer timer;
|
| 43 | struct clock_event_device ced;
|
| 44 | };
|
| 45 |
|
| 46 | struct nios2_clocksource {
|
| 47 | struct nios2_timer timer;
|
| 48 | struct clocksource cs;
|
| 49 | };
|
| 50 |
|
| 51 | static inline struct nios2_clockevent_dev *
|
| 52 | to_nios2_clkevent(struct clock_event_device *evt)
|
| 53 | {
|
| 54 | return container_of(evt, struct nios2_clockevent_dev, ced);
|
| 55 | }
|
| 56 |
|
| 57 | static inline struct nios2_clocksource *
|
| 58 | to_nios2_clksource(struct clocksource *cs)
|
| 59 | {
|
| 60 | return container_of(cs, struct nios2_clocksource, cs);
|
| 61 | }
|
| 62 |
|
| 63 | static u16 timer_readw(struct nios2_timer *timer, u32 offs)
|
| 64 | {
|
| 65 | return readw(timer->base + offs);
|
| 66 | }
|
| 67 |
|
| 68 | static void timer_writew(struct nios2_timer *timer, u16 val, u32 offs)
|
| 69 | {
|
| 70 | writew(val, timer->base + offs);
|
| 71 | }
|
| 72 |
|
| 73 | static inline unsigned long read_timersnapshot(struct nios2_timer *timer)
|
| 74 | {
|
| 75 | unsigned long count;
|
| 76 |
|
| 77 | timer_writew(timer, 0, ALTERA_TIMER_SNAPL_REG);
|
| 78 | count = timer_readw(timer, ALTERA_TIMER_SNAPH_REG) << 16 |
|
| 79 | timer_readw(timer, ALTERA_TIMER_SNAPL_REG);
|
| 80 |
|
| 81 | return count;
|
| 82 | }
|
| 83 |
|
| 84 | static u64 nios2_timer_read(struct clocksource *cs)
|
| 85 | {
|
| 86 | struct nios2_clocksource *nios2_cs = to_nios2_clksource(cs);
|
| 87 | unsigned long flags;
|
| 88 | u32 count;
|
| 89 |
|
| 90 | local_irq_save(flags);
|
| 91 | count = read_timersnapshot(&nios2_cs->timer);
|
| 92 | local_irq_restore(flags);
|
| 93 |
|
| 94 |
|
| 95 | return ~count;
|
| 96 | }
|
| 97 |
|
| 98 | static struct nios2_clocksource nios2_cs = {
|
| 99 | .cs = {
|
| 100 | .name = "nios2-clksrc",
|
| 101 | .rating = 250,
|
| 102 | .read = nios2_timer_read,
|
| 103 | .mask = CLOCKSOURCE_MASK(32),
|
| 104 | .flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
| 105 | },
|
| 106 | };
|
| 107 |
|
| 108 | cycles_t get_cycles(void)
|
| 109 | {
|
| 110 |
|
| 111 | if (nios2_cs.timer.base)
|
| 112 | return nios2_timer_read(&nios2_cs.cs);
|
| 113 | return 0;
|
| 114 | }
|
| 115 | EXPORT_SYMBOL(get_cycles);
|
| 116 |
|
| 117 | static void nios2_timer_start(struct nios2_timer *timer)
|
| 118 | {
|
| 119 | u16 ctrl;
|
| 120 |
|
| 121 | ctrl = timer_readw(timer, ALTERA_TIMER_CONTROL_REG);
|
| 122 | ctrl |= ALTERA_TIMER_CONTROL_START_MSK;
|
| 123 | timer_writew(timer, ctrl, ALTERA_TIMER_CONTROL_REG);
|
| 124 | }
|
| 125 |
|
| 126 | static void nios2_timer_stop(struct nios2_timer *timer)
|
| 127 | {
|
| 128 | u16 ctrl;
|
| 129 |
|
| 130 | ctrl = timer_readw(timer, ALTERA_TIMER_CONTROL_REG);
|
| 131 | ctrl |= ALTERA_TIMER_CONTROL_STOP_MSK;
|
| 132 | timer_writew(timer, ctrl, ALTERA_TIMER_CONTROL_REG);
|
| 133 | }
|
| 134 |
|
| 135 | static void nios2_timer_config(struct nios2_timer *timer, unsigned long period,
|
| 136 | bool periodic)
|
| 137 | {
|
| 138 | u16 ctrl;
|
| 139 |
|
| 140 | |
| 141 | * stored in the period register.
|
| 142 | period--;
|
| 143 |
|
| 144 | ctrl = timer_readw(timer, ALTERA_TIMER_CONTROL_REG);
|
| 145 |
|
| 146 | timer_writew(timer, ctrl | ALTERA_TIMER_CONTROL_STOP_MSK,
|
| 147 | ALTERA_TIMER_CONTROL_REG);
|
| 148 |
|
| 149 |
|
| 150 | timer_writew(timer, period, ALTERA_TIMER_PERIODL_REG);
|
| 151 | timer_writew(timer, period >> 16, ALTERA_TIMER_PERIODH_REG);
|
| 152 |
|
| 153 | ctrl |= ALTERA_TIMER_CONTROL_START_MSK | ALTERA_TIMER_CONTROL_ITO_MSK;
|
| 154 | if (periodic)
|
| 155 | ctrl |= ALTERA_TIMER_CONTROL_CONT_MSK;
|
| 156 | else
|
| 157 | ctrl &= ~ALTERA_TIMER_CONTROL_CONT_MSK;
|
| 158 | timer_writew(timer, ctrl, ALTERA_TIMER_CONTROL_REG);
|
| 159 | }
|
| 160 |
|
| 161 | static int nios2_timer_set_next_event(unsigned long delta,
|
| 162 | struct clock_event_device *evt)
|
| 163 | {
|
| 164 | struct nios2_clockevent_dev *nios2_ced = to_nios2_clkevent(evt);
|
| 165 |
|
| 166 | nios2_timer_config(&nios2_ced->timer, delta, false);
|
| 167 |
|
| 168 | return 0;
|
| 169 | }
|
| 170 |
|
| 171 | static int nios2_timer_shutdown(struct clock_event_device *evt)
|
| 172 | {
|
| 173 | struct nios2_clockevent_dev *nios2_ced = to_nios2_clkevent(evt);
|
| 174 | struct nios2_timer *timer = &nios2_ced->timer;
|
| 175 |
|
| 176 | nios2_timer_stop(timer);
|
| 177 | return 0;
|
| 178 | }
|
| 179 |
|
| 180 | static int nios2_timer_set_periodic(struct clock_event_device *evt)
|
| 181 | {
|
| 182 | unsigned long period;
|
| 183 | struct nios2_clockevent_dev *nios2_ced = to_nios2_clkevent(evt);
|
| 184 | struct nios2_timer *timer = &nios2_ced->timer;
|
| 185 |
|
| 186 | period = DIV_ROUND_UP(timer->freq, HZ);
|
| 187 | nios2_timer_config(timer, period, true);
|
| 188 | return 0;
|
| 189 | }
|
| 190 |
|
| 191 | static int nios2_timer_resume(struct clock_event_device *evt)
|
| 192 | {
|
| 193 | struct nios2_clockevent_dev *nios2_ced = to_nios2_clkevent(evt);
|
| 194 | struct nios2_timer *timer = &nios2_ced->timer;
|
| 195 |
|
| 196 | nios2_timer_start(timer);
|
| 197 | return 0;
|
| 198 | }
|
| 199 |
|
| 200 | irqreturn_t timer_interrupt(int irq, void *dev_id)
|
| 201 | {
|
| 202 | struct clock_event_device *evt = (struct clock_event_device *) dev_id;
|
| 203 | struct nios2_clockevent_dev *nios2_ced = to_nios2_clkevent(evt);
|
| 204 |
|
| 205 |
|
| 206 | timer_writew(&nios2_ced->timer, 0, ALTERA_TIMER_STATUS_REG);
|
| 207 | evt->event_handler(evt);
|
| 208 |
|
| 209 | return IRQ_HANDLED;
|
| 210 | }
|
| 211 |
|
| 212 | static int __init nios2_timer_get_base_and_freq(struct device_node *np,
|
| 213 | void __iomem **base, u32 *freq)
|
| 214 | {
|
| 215 | *base = of_iomap(np, 0);
|
| 216 | if (!*base) {
|
| 217 | pr_crit("Unable to map reg for %pOFn\n", np);
|
| 218 | return -ENXIO;
|
| 219 | }
|
| 220 |
|
| 221 | if (of_property_read_u32(np, "clock-frequency", freq)) {
|
| 222 | pr_crit("Unable to get %pOFn clock frequency\n", np);
|
| 223 | return -EINVAL;
|
| 224 | }
|
| 225 |
|
| 226 | return 0;
|
| 227 | }
|
| 228 |
|
| 229 | static struct nios2_clockevent_dev nios2_ce = {
|
| 230 | .ced = {
|
| 231 | .name = "nios2-clkevent",
|
| 232 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
| 233 | .rating = 250,
|
| 234 | .shift = 32,
|
| 235 | .set_next_event = nios2_timer_set_next_event,
|
| 236 | .set_state_shutdown = nios2_timer_shutdown,
|
| 237 | .set_state_periodic = nios2_timer_set_periodic,
|
| 238 | .set_state_oneshot = nios2_timer_shutdown,
|
| 239 | .tick_resume = nios2_timer_resume,
|
| 240 | },
|
| 241 | };
|
| 242 |
|
| 243 | static __init int nios2_clockevent_init(struct device_node *timer)
|
| 244 | {
|
| 245 | void __iomem *iobase;
|
| 246 | u32 freq;
|
| 247 | int irq, ret;
|
| 248 |
|
| 249 | ret = nios2_timer_get_base_and_freq(timer, &iobase, &freq);
|
| 250 | if (ret)
|
| 251 | return ret;
|
| 252 |
|
| 253 | irq = irq_of_parse_and_map(timer, 0);
|
| 254 | if (!irq) {
|
| 255 | pr_crit("Unable to parse timer irq\n");
|
| 256 | return -EINVAL;
|
| 257 | }
|
| 258 |
|
| 259 | nios2_ce.timer.base = iobase;
|
| 260 | nios2_ce.timer.freq = freq;
|
| 261 |
|
| 262 | nios2_ce.ced.cpumask = cpumask_of(0);
|
| 263 | nios2_ce.ced.irq = irq;
|
| 264 |
|
| 265 | nios2_timer_stop(&nios2_ce.timer);
|
| 266 |
|
| 267 | timer_writew(&nios2_ce.timer, 0, ALTERA_TIMER_STATUS_REG);
|
| 268 |
|
| 269 | ret = request_irq(irq, timer_interrupt, IRQF_TIMER, timer->name,
|
| 270 | &nios2_ce.ced);
|
| 271 | if (ret) {
|
| 272 | pr_crit("Unable to setup timer irq\n");
|
| 273 | return ret;
|
| 274 | }
|
| 275 |
|
| 276 | clockevents_config_and_register(&nios2_ce.ced, freq, 1, ULONG_MAX);
|
| 277 |
|
| 278 | return 0;
|
| 279 | }
|
| 280 |
|
| 281 | static __init int nios2_clocksource_init(struct device_node *timer)
|
| 282 | {
|
| 283 | unsigned int ctrl;
|
| 284 | void __iomem *iobase;
|
| 285 | u32 freq;
|
| 286 | int ret;
|
| 287 |
|
| 288 | ret = nios2_timer_get_base_and_freq(timer, &iobase, &freq);
|
| 289 | if (ret)
|
| 290 | return ret;
|
| 291 |
|
| 292 | nios2_cs.timer.base = iobase;
|
| 293 | nios2_cs.timer.freq = freq;
|
| 294 |
|
| 295 | ret = clocksource_register_hz(&nios2_cs.cs, freq);
|
| 296 | if (ret)
|
| 297 | return ret;
|
| 298 |
|
| 299 | timer_writew(&nios2_cs.timer, USHRT_MAX, ALTERA_TIMER_PERIODL_REG);
|
| 300 | timer_writew(&nios2_cs.timer, USHRT_MAX, ALTERA_TIMER_PERIODH_REG);
|
| 301 |
|
| 302 |
|
| 303 | ctrl = ALTERA_TIMER_CONTROL_CONT_MSK | ALTERA_TIMER_CONTROL_START_MSK;
|
| 304 | timer_writew(&nios2_cs.timer, ctrl, ALTERA_TIMER_CONTROL_REG);
|
| 305 |
|
| 306 |
|
| 307 | lpj_fine = freq / HZ;
|
| 308 |
|
| 309 | return 0;
|
| 310 | }
|
| 311 |
|
| 312 | |
| 313 | * The first timer instance will use as a clockevent. If there are two or
|
| 314 | * more instances, the second one gets used as clocksource and all
|
| 315 | * others are unused.
|
| 316 |
|
| 317 | static int __init nios2_time_init(struct device_node *timer)
|
| 318 | {
|
| 319 | static int num_called;
|
| 320 | int ret;
|
| 321 |
|
| 322 | switch (num_called) {
|
| 323 | case 0:
|
| 324 | ret = nios2_clockevent_init(timer);
|
| 325 | break;
|
| 326 | case 1:
|
| 327 | ret = nios2_clocksource_init(timer);
|
| 328 | break;
|
| 329 | default:
|
| 330 | ret = 0;
|
| 331 | break;
|
| 332 | }
|
| 333 |
|
| 334 | num_called++;
|
| 335 |
|
| 336 | return ret;
|
| 337 | }
|
| 338 |
|
| 339 | void read_persistent_clock64(struct timespec64 *ts)
|
| 340 | {
|
| 341 | ts->tv_sec = mktime64(2007, 1, 1, 0, 0, 0);
|
| 342 | ts->tv_nsec = 0;
|
| 343 | }
|
| 344 |
|
| 345 | void __init time_init(void)
|
| 346 | {
|
| 347 | struct device_node *np;
|
| 348 | int count = 0;
|
| 349 |
|
| 350 | for_each_compatible_node(np, NULL, ALTR_TIMER_COMPATIBLE)
|
| 351 | count++;
|
| 352 |
|
| 353 | if (count < 2)
|
| 354 | panic("%d timer is found, it needs 2 timers in system\n", count);
|
| 355 |
|
| 356 | timer_probe();
|
| 357 | }
|
| 358 |
|
| 359 | TIMER_OF_DECLARE(nios2_timer, ALTR_TIMER_COMPATIBLE, nios2_time_init);
|