1*1f2acc5aSJohn Crispin /* 2*1f2acc5aSJohn Crispin * This file is subject to the terms and conditions of the GNU General Public 3*1f2acc5aSJohn Crispin * License. See the file "COPYING" in the main directory of this archive 4*1f2acc5aSJohn Crispin * for more details. 5*1f2acc5aSJohn Crispin * 6*1f2acc5aSJohn Crispin * Copyright (C) 2013 by John Crispin <blogic@openwrt.org> 7*1f2acc5aSJohn Crispin */ 8*1f2acc5aSJohn Crispin 9*1f2acc5aSJohn Crispin #include <linux/clockchips.h> 10*1f2acc5aSJohn Crispin #include <linux/clocksource.h> 11*1f2acc5aSJohn Crispin #include <linux/interrupt.h> 12*1f2acc5aSJohn Crispin #include <linux/reset.h> 13*1f2acc5aSJohn Crispin #include <linux/init.h> 14*1f2acc5aSJohn Crispin #include <linux/time.h> 15*1f2acc5aSJohn Crispin #include <linux/of.h> 16*1f2acc5aSJohn Crispin #include <linux/of_irq.h> 17*1f2acc5aSJohn Crispin #include <linux/of_address.h> 18*1f2acc5aSJohn Crispin 19*1f2acc5aSJohn Crispin #include <asm/mach-ralink/ralink_regs.h> 20*1f2acc5aSJohn Crispin 21*1f2acc5aSJohn Crispin #define SYSTICK_FREQ (50 * 1000) 22*1f2acc5aSJohn Crispin 23*1f2acc5aSJohn Crispin #define SYSTICK_CONFIG 0x00 24*1f2acc5aSJohn Crispin #define SYSTICK_COMPARE 0x04 25*1f2acc5aSJohn Crispin #define SYSTICK_COUNT 0x08 26*1f2acc5aSJohn Crispin 27*1f2acc5aSJohn Crispin /* route systick irq to mips irq 7 instead of the r4k-timer */ 28*1f2acc5aSJohn Crispin #define CFG_EXT_STK_EN 0x2 29*1f2acc5aSJohn Crispin /* enable the counter */ 30*1f2acc5aSJohn Crispin #define CFG_CNT_EN 0x1 31*1f2acc5aSJohn Crispin 32*1f2acc5aSJohn Crispin struct systick_device { 33*1f2acc5aSJohn Crispin void __iomem *membase; 34*1f2acc5aSJohn Crispin struct clock_event_device dev; 35*1f2acc5aSJohn Crispin int irq_requested; 36*1f2acc5aSJohn Crispin int freq_scale; 37*1f2acc5aSJohn Crispin }; 38*1f2acc5aSJohn Crispin 39*1f2acc5aSJohn Crispin static void systick_set_clock_mode(enum clock_event_mode mode, 40*1f2acc5aSJohn Crispin struct clock_event_device *evt); 41*1f2acc5aSJohn Crispin 42*1f2acc5aSJohn Crispin static int systick_next_event(unsigned long delta, 43*1f2acc5aSJohn Crispin struct clock_event_device *evt) 44*1f2acc5aSJohn Crispin { 45*1f2acc5aSJohn Crispin struct systick_device *sdev; 46*1f2acc5aSJohn Crispin u32 count; 47*1f2acc5aSJohn Crispin 48*1f2acc5aSJohn Crispin sdev = container_of(evt, struct systick_device, dev); 49*1f2acc5aSJohn Crispin count = ioread32(sdev->membase + SYSTICK_COUNT); 50*1f2acc5aSJohn Crispin count = (count + delta) % SYSTICK_FREQ; 51*1f2acc5aSJohn Crispin iowrite32(count + delta, sdev->membase + SYSTICK_COMPARE); 52*1f2acc5aSJohn Crispin 53*1f2acc5aSJohn Crispin return 0; 54*1f2acc5aSJohn Crispin } 55*1f2acc5aSJohn Crispin 56*1f2acc5aSJohn Crispin static void systick_event_handler(struct clock_event_device *dev) 57*1f2acc5aSJohn Crispin { 58*1f2acc5aSJohn Crispin /* noting to do here */ 59*1f2acc5aSJohn Crispin } 60*1f2acc5aSJohn Crispin 61*1f2acc5aSJohn Crispin static irqreturn_t systick_interrupt(int irq, void *dev_id) 62*1f2acc5aSJohn Crispin { 63*1f2acc5aSJohn Crispin struct clock_event_device *dev = (struct clock_event_device *) dev_id; 64*1f2acc5aSJohn Crispin 65*1f2acc5aSJohn Crispin dev->event_handler(dev); 66*1f2acc5aSJohn Crispin 67*1f2acc5aSJohn Crispin return IRQ_HANDLED; 68*1f2acc5aSJohn Crispin } 69*1f2acc5aSJohn Crispin 70*1f2acc5aSJohn Crispin static struct systick_device systick = { 71*1f2acc5aSJohn Crispin .dev = { 72*1f2acc5aSJohn Crispin /* 73*1f2acc5aSJohn Crispin * cevt-r4k uses 300, make sure systick 74*1f2acc5aSJohn Crispin * gets used if available 75*1f2acc5aSJohn Crispin */ 76*1f2acc5aSJohn Crispin .rating = 310, 77*1f2acc5aSJohn Crispin .features = CLOCK_EVT_FEAT_ONESHOT, 78*1f2acc5aSJohn Crispin .set_next_event = systick_next_event, 79*1f2acc5aSJohn Crispin .set_mode = systick_set_clock_mode, 80*1f2acc5aSJohn Crispin .event_handler = systick_event_handler, 81*1f2acc5aSJohn Crispin }, 82*1f2acc5aSJohn Crispin }; 83*1f2acc5aSJohn Crispin 84*1f2acc5aSJohn Crispin static struct irqaction systick_irqaction = { 85*1f2acc5aSJohn Crispin .handler = systick_interrupt, 86*1f2acc5aSJohn Crispin .flags = IRQF_PERCPU | IRQF_TIMER, 87*1f2acc5aSJohn Crispin .dev_id = &systick.dev, 88*1f2acc5aSJohn Crispin }; 89*1f2acc5aSJohn Crispin 90*1f2acc5aSJohn Crispin static void systick_set_clock_mode(enum clock_event_mode mode, 91*1f2acc5aSJohn Crispin struct clock_event_device *evt) 92*1f2acc5aSJohn Crispin { 93*1f2acc5aSJohn Crispin struct systick_device *sdev; 94*1f2acc5aSJohn Crispin 95*1f2acc5aSJohn Crispin sdev = container_of(evt, struct systick_device, dev); 96*1f2acc5aSJohn Crispin 97*1f2acc5aSJohn Crispin switch (mode) { 98*1f2acc5aSJohn Crispin case CLOCK_EVT_MODE_ONESHOT: 99*1f2acc5aSJohn Crispin if (!sdev->irq_requested) 100*1f2acc5aSJohn Crispin setup_irq(systick.dev.irq, &systick_irqaction); 101*1f2acc5aSJohn Crispin sdev->irq_requested = 1; 102*1f2acc5aSJohn Crispin iowrite32(CFG_EXT_STK_EN | CFG_CNT_EN, 103*1f2acc5aSJohn Crispin systick.membase + SYSTICK_CONFIG); 104*1f2acc5aSJohn Crispin break; 105*1f2acc5aSJohn Crispin 106*1f2acc5aSJohn Crispin case CLOCK_EVT_MODE_SHUTDOWN: 107*1f2acc5aSJohn Crispin if (sdev->irq_requested) 108*1f2acc5aSJohn Crispin free_irq(systick.dev.irq, &systick_irqaction); 109*1f2acc5aSJohn Crispin sdev->irq_requested = 0; 110*1f2acc5aSJohn Crispin iowrite32(0, systick.membase + SYSTICK_CONFIG); 111*1f2acc5aSJohn Crispin break; 112*1f2acc5aSJohn Crispin 113*1f2acc5aSJohn Crispin default: 114*1f2acc5aSJohn Crispin pr_err("%s: Unhandeled mips clock_mode\n", systick.dev.name); 115*1f2acc5aSJohn Crispin break; 116*1f2acc5aSJohn Crispin } 117*1f2acc5aSJohn Crispin } 118*1f2acc5aSJohn Crispin 119*1f2acc5aSJohn Crispin static void __init ralink_systick_init(struct device_node *np) 120*1f2acc5aSJohn Crispin { 121*1f2acc5aSJohn Crispin systick.membase = of_iomap(np, 0); 122*1f2acc5aSJohn Crispin if (!systick.membase) 123*1f2acc5aSJohn Crispin return; 124*1f2acc5aSJohn Crispin 125*1f2acc5aSJohn Crispin systick_irqaction.name = np->name; 126*1f2acc5aSJohn Crispin systick.dev.name = np->name; 127*1f2acc5aSJohn Crispin clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60); 128*1f2acc5aSJohn Crispin systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev); 129*1f2acc5aSJohn Crispin systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev); 130*1f2acc5aSJohn Crispin systick.dev.irq = irq_of_parse_and_map(np, 0); 131*1f2acc5aSJohn Crispin if (!systick.dev.irq) { 132*1f2acc5aSJohn Crispin pr_err("%s: request_irq failed", np->name); 133*1f2acc5aSJohn Crispin return; 134*1f2acc5aSJohn Crispin } 135*1f2acc5aSJohn Crispin 136*1f2acc5aSJohn Crispin clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name, 137*1f2acc5aSJohn Crispin SYSTICK_FREQ, 301, 16, clocksource_mmio_readl_up); 138*1f2acc5aSJohn Crispin 139*1f2acc5aSJohn Crispin clockevents_register_device(&systick.dev); 140*1f2acc5aSJohn Crispin 141*1f2acc5aSJohn Crispin pr_info("%s: runing - mult: %d, shift: %d\n", 142*1f2acc5aSJohn Crispin np->name, systick.dev.mult, systick.dev.shift); 143*1f2acc5aSJohn Crispin } 144*1f2acc5aSJohn Crispin 145*1f2acc5aSJohn Crispin CLOCKSOURCE_OF_DECLARE(systick, "ralink,cevt-systick", ralink_systick_init); 146