1*f5bf0ee4SLinus Walleij /* 2*f5bf0ee4SLinus Walleij * Faraday Technology FTTMR010 timer driver 3*f5bf0ee4SLinus Walleij * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org> 4*f5bf0ee4SLinus Walleij * 5*f5bf0ee4SLinus Walleij * Based on a rewrite of arch/arm/mach-gemini/timer.c: 6*f5bf0ee4SLinus Walleij * Copyright (C) 2001-2006 Storlink, Corp. 7*f5bf0ee4SLinus Walleij * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> 8*f5bf0ee4SLinus Walleij */ 9*f5bf0ee4SLinus Walleij #include <linux/interrupt.h> 10*f5bf0ee4SLinus Walleij #include <linux/io.h> 11*f5bf0ee4SLinus Walleij #include <linux/of.h> 12*f5bf0ee4SLinus Walleij #include <linux/of_address.h> 13*f5bf0ee4SLinus Walleij #include <linux/of_irq.h> 14*f5bf0ee4SLinus Walleij #include <linux/mfd/syscon.h> 15*f5bf0ee4SLinus Walleij #include <linux/regmap.h> 16*f5bf0ee4SLinus Walleij #include <linux/clockchips.h> 17*f5bf0ee4SLinus Walleij #include <linux/clocksource.h> 18*f5bf0ee4SLinus Walleij #include <linux/sched_clock.h> 19*f5bf0ee4SLinus Walleij 20*f5bf0ee4SLinus Walleij /* 21*f5bf0ee4SLinus Walleij * Relevant registers in the global syscon 22*f5bf0ee4SLinus Walleij */ 23*f5bf0ee4SLinus Walleij #define GLOBAL_STATUS 0x04 24*f5bf0ee4SLinus Walleij #define CPU_AHB_RATIO_MASK (0x3 << 18) 25*f5bf0ee4SLinus Walleij #define CPU_AHB_1_1 (0x0 << 18) 26*f5bf0ee4SLinus Walleij #define CPU_AHB_3_2 (0x1 << 18) 27*f5bf0ee4SLinus Walleij #define CPU_AHB_24_13 (0x2 << 18) 28*f5bf0ee4SLinus Walleij #define CPU_AHB_2_1 (0x3 << 18) 29*f5bf0ee4SLinus Walleij #define REG_TO_AHB_SPEED(reg) ((((reg) >> 15) & 0x7) * 10 + 130) 30*f5bf0ee4SLinus Walleij 31*f5bf0ee4SLinus Walleij /* 32*f5bf0ee4SLinus Walleij * Register definitions for the timers 33*f5bf0ee4SLinus Walleij */ 34*f5bf0ee4SLinus Walleij #define TIMER1_COUNT (0x00) 35*f5bf0ee4SLinus Walleij #define TIMER1_LOAD (0x04) 36*f5bf0ee4SLinus Walleij #define TIMER1_MATCH1 (0x08) 37*f5bf0ee4SLinus Walleij #define TIMER1_MATCH2 (0x0c) 38*f5bf0ee4SLinus Walleij #define TIMER2_COUNT (0x10) 39*f5bf0ee4SLinus Walleij #define TIMER2_LOAD (0x14) 40*f5bf0ee4SLinus Walleij #define TIMER2_MATCH1 (0x18) 41*f5bf0ee4SLinus Walleij #define TIMER2_MATCH2 (0x1c) 42*f5bf0ee4SLinus Walleij #define TIMER3_COUNT (0x20) 43*f5bf0ee4SLinus Walleij #define TIMER3_LOAD (0x24) 44*f5bf0ee4SLinus Walleij #define TIMER3_MATCH1 (0x28) 45*f5bf0ee4SLinus Walleij #define TIMER3_MATCH2 (0x2c) 46*f5bf0ee4SLinus Walleij #define TIMER_CR (0x30) 47*f5bf0ee4SLinus Walleij #define TIMER_INTR_STATE (0x34) 48*f5bf0ee4SLinus Walleij #define TIMER_INTR_MASK (0x38) 49*f5bf0ee4SLinus Walleij 50*f5bf0ee4SLinus Walleij #define TIMER_1_CR_ENABLE (1 << 0) 51*f5bf0ee4SLinus Walleij #define TIMER_1_CR_CLOCK (1 << 1) 52*f5bf0ee4SLinus Walleij #define TIMER_1_CR_INT (1 << 2) 53*f5bf0ee4SLinus Walleij #define TIMER_2_CR_ENABLE (1 << 3) 54*f5bf0ee4SLinus Walleij #define TIMER_2_CR_CLOCK (1 << 4) 55*f5bf0ee4SLinus Walleij #define TIMER_2_CR_INT (1 << 5) 56*f5bf0ee4SLinus Walleij #define TIMER_3_CR_ENABLE (1 << 6) 57*f5bf0ee4SLinus Walleij #define TIMER_3_CR_CLOCK (1 << 7) 58*f5bf0ee4SLinus Walleij #define TIMER_3_CR_INT (1 << 8) 59*f5bf0ee4SLinus Walleij #define TIMER_1_CR_UPDOWN (1 << 9) 60*f5bf0ee4SLinus Walleij #define TIMER_2_CR_UPDOWN (1 << 10) 61*f5bf0ee4SLinus Walleij #define TIMER_3_CR_UPDOWN (1 << 11) 62*f5bf0ee4SLinus Walleij #define TIMER_DEFAULT_FLAGS (TIMER_1_CR_UPDOWN | \ 63*f5bf0ee4SLinus Walleij TIMER_3_CR_ENABLE | \ 64*f5bf0ee4SLinus Walleij TIMER_3_CR_UPDOWN) 65*f5bf0ee4SLinus Walleij 66*f5bf0ee4SLinus Walleij #define TIMER_1_INT_MATCH1 (1 << 0) 67*f5bf0ee4SLinus Walleij #define TIMER_1_INT_MATCH2 (1 << 1) 68*f5bf0ee4SLinus Walleij #define TIMER_1_INT_OVERFLOW (1 << 2) 69*f5bf0ee4SLinus Walleij #define TIMER_2_INT_MATCH1 (1 << 3) 70*f5bf0ee4SLinus Walleij #define TIMER_2_INT_MATCH2 (1 << 4) 71*f5bf0ee4SLinus Walleij #define TIMER_2_INT_OVERFLOW (1 << 5) 72*f5bf0ee4SLinus Walleij #define TIMER_3_INT_MATCH1 (1 << 6) 73*f5bf0ee4SLinus Walleij #define TIMER_3_INT_MATCH2 (1 << 7) 74*f5bf0ee4SLinus Walleij #define TIMER_3_INT_OVERFLOW (1 << 8) 75*f5bf0ee4SLinus Walleij #define TIMER_INT_ALL_MASK 0x1ff 76*f5bf0ee4SLinus Walleij 77*f5bf0ee4SLinus Walleij static unsigned int tick_rate; 78*f5bf0ee4SLinus Walleij static void __iomem *base; 79*f5bf0ee4SLinus Walleij 80*f5bf0ee4SLinus Walleij static u64 notrace fttmr010_read_sched_clock(void) 81*f5bf0ee4SLinus Walleij { 82*f5bf0ee4SLinus Walleij return readl(base + TIMER3_COUNT); 83*f5bf0ee4SLinus Walleij } 84*f5bf0ee4SLinus Walleij 85*f5bf0ee4SLinus Walleij static int fttmr010_timer_set_next_event(unsigned long cycles, 86*f5bf0ee4SLinus Walleij struct clock_event_device *evt) 87*f5bf0ee4SLinus Walleij { 88*f5bf0ee4SLinus Walleij u32 cr; 89*f5bf0ee4SLinus Walleij 90*f5bf0ee4SLinus Walleij /* Setup the match register */ 91*f5bf0ee4SLinus Walleij cr = readl(base + TIMER1_COUNT); 92*f5bf0ee4SLinus Walleij writel(cr + cycles, base + TIMER1_MATCH1); 93*f5bf0ee4SLinus Walleij if (readl(base + TIMER1_COUNT) - cr > cycles) 94*f5bf0ee4SLinus Walleij return -ETIME; 95*f5bf0ee4SLinus Walleij 96*f5bf0ee4SLinus Walleij return 0; 97*f5bf0ee4SLinus Walleij } 98*f5bf0ee4SLinus Walleij 99*f5bf0ee4SLinus Walleij static int fttmr010_timer_shutdown(struct clock_event_device *evt) 100*f5bf0ee4SLinus Walleij { 101*f5bf0ee4SLinus Walleij u32 cr; 102*f5bf0ee4SLinus Walleij 103*f5bf0ee4SLinus Walleij /* 104*f5bf0ee4SLinus Walleij * Disable also for oneshot: the set_next() call will arm the timer 105*f5bf0ee4SLinus Walleij * instead. 106*f5bf0ee4SLinus Walleij */ 107*f5bf0ee4SLinus Walleij /* Stop timer and interrupt. */ 108*f5bf0ee4SLinus Walleij cr = readl(base + TIMER_CR); 109*f5bf0ee4SLinus Walleij cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT); 110*f5bf0ee4SLinus Walleij writel(cr, base + TIMER_CR); 111*f5bf0ee4SLinus Walleij 112*f5bf0ee4SLinus Walleij /* Setup counter start from 0 */ 113*f5bf0ee4SLinus Walleij writel(0, base + TIMER1_COUNT); 114*f5bf0ee4SLinus Walleij writel(0, base + TIMER1_LOAD); 115*f5bf0ee4SLinus Walleij 116*f5bf0ee4SLinus Walleij /* enable interrupt */ 117*f5bf0ee4SLinus Walleij cr = readl(base + TIMER_INTR_MASK); 118*f5bf0ee4SLinus Walleij cr &= ~(TIMER_1_INT_OVERFLOW | TIMER_1_INT_MATCH2); 119*f5bf0ee4SLinus Walleij cr |= TIMER_1_INT_MATCH1; 120*f5bf0ee4SLinus Walleij writel(cr, base + TIMER_INTR_MASK); 121*f5bf0ee4SLinus Walleij 122*f5bf0ee4SLinus Walleij /* start the timer */ 123*f5bf0ee4SLinus Walleij cr = readl(base + TIMER_CR); 124*f5bf0ee4SLinus Walleij cr |= TIMER_1_CR_ENABLE; 125*f5bf0ee4SLinus Walleij writel(cr, base + TIMER_CR); 126*f5bf0ee4SLinus Walleij 127*f5bf0ee4SLinus Walleij return 0; 128*f5bf0ee4SLinus Walleij } 129*f5bf0ee4SLinus Walleij 130*f5bf0ee4SLinus Walleij static int fttmr010_timer_set_periodic(struct clock_event_device *evt) 131*f5bf0ee4SLinus Walleij { 132*f5bf0ee4SLinus Walleij u32 period = DIV_ROUND_CLOSEST(tick_rate, HZ); 133*f5bf0ee4SLinus Walleij u32 cr; 134*f5bf0ee4SLinus Walleij 135*f5bf0ee4SLinus Walleij /* Stop timer and interrupt */ 136*f5bf0ee4SLinus Walleij cr = readl(base + TIMER_CR); 137*f5bf0ee4SLinus Walleij cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT); 138*f5bf0ee4SLinus Walleij writel(cr, base + TIMER_CR); 139*f5bf0ee4SLinus Walleij 140*f5bf0ee4SLinus Walleij /* Setup timer to fire at 1/HT intervals. */ 141*f5bf0ee4SLinus Walleij cr = 0xffffffff - (period - 1); 142*f5bf0ee4SLinus Walleij writel(cr, base + TIMER1_COUNT); 143*f5bf0ee4SLinus Walleij writel(cr, base + TIMER1_LOAD); 144*f5bf0ee4SLinus Walleij 145*f5bf0ee4SLinus Walleij /* enable interrupt on overflow */ 146*f5bf0ee4SLinus Walleij cr = readl(base + TIMER_INTR_MASK); 147*f5bf0ee4SLinus Walleij cr &= ~(TIMER_1_INT_MATCH1 | TIMER_1_INT_MATCH2); 148*f5bf0ee4SLinus Walleij cr |= TIMER_1_INT_OVERFLOW; 149*f5bf0ee4SLinus Walleij writel(cr, base + TIMER_INTR_MASK); 150*f5bf0ee4SLinus Walleij 151*f5bf0ee4SLinus Walleij /* Start the timer */ 152*f5bf0ee4SLinus Walleij cr = readl(base + TIMER_CR); 153*f5bf0ee4SLinus Walleij cr |= TIMER_1_CR_ENABLE; 154*f5bf0ee4SLinus Walleij cr |= TIMER_1_CR_INT; 155*f5bf0ee4SLinus Walleij writel(cr, base + TIMER_CR); 156*f5bf0ee4SLinus Walleij 157*f5bf0ee4SLinus Walleij return 0; 158*f5bf0ee4SLinus Walleij } 159*f5bf0ee4SLinus Walleij 160*f5bf0ee4SLinus Walleij /* Use TIMER1 as clock event */ 161*f5bf0ee4SLinus Walleij static struct clock_event_device fttmr010_clockevent = { 162*f5bf0ee4SLinus Walleij .name = "TIMER1", 163*f5bf0ee4SLinus Walleij /* Reasonably fast and accurate clock event */ 164*f5bf0ee4SLinus Walleij .rating = 300, 165*f5bf0ee4SLinus Walleij .shift = 32, 166*f5bf0ee4SLinus Walleij .features = CLOCK_EVT_FEAT_PERIODIC | 167*f5bf0ee4SLinus Walleij CLOCK_EVT_FEAT_ONESHOT, 168*f5bf0ee4SLinus Walleij .set_next_event = fttmr010_timer_set_next_event, 169*f5bf0ee4SLinus Walleij .set_state_shutdown = fttmr010_timer_shutdown, 170*f5bf0ee4SLinus Walleij .set_state_periodic = fttmr010_timer_set_periodic, 171*f5bf0ee4SLinus Walleij .set_state_oneshot = fttmr010_timer_shutdown, 172*f5bf0ee4SLinus Walleij .tick_resume = fttmr010_timer_shutdown, 173*f5bf0ee4SLinus Walleij }; 174*f5bf0ee4SLinus Walleij 175*f5bf0ee4SLinus Walleij /* 176*f5bf0ee4SLinus Walleij * IRQ handler for the timer 177*f5bf0ee4SLinus Walleij */ 178*f5bf0ee4SLinus Walleij static irqreturn_t fttmr010_timer_interrupt(int irq, void *dev_id) 179*f5bf0ee4SLinus Walleij { 180*f5bf0ee4SLinus Walleij struct clock_event_device *evt = &fttmr010_clockevent; 181*f5bf0ee4SLinus Walleij 182*f5bf0ee4SLinus Walleij evt->event_handler(evt); 183*f5bf0ee4SLinus Walleij return IRQ_HANDLED; 184*f5bf0ee4SLinus Walleij } 185*f5bf0ee4SLinus Walleij 186*f5bf0ee4SLinus Walleij static struct irqaction fttmr010_timer_irq = { 187*f5bf0ee4SLinus Walleij .name = "Faraday FTTMR010 Timer Tick", 188*f5bf0ee4SLinus Walleij .flags = IRQF_TIMER, 189*f5bf0ee4SLinus Walleij .handler = fttmr010_timer_interrupt, 190*f5bf0ee4SLinus Walleij }; 191*f5bf0ee4SLinus Walleij 192*f5bf0ee4SLinus Walleij static int __init gemini_timer_of_init(struct device_node *np) 193*f5bf0ee4SLinus Walleij { 194*f5bf0ee4SLinus Walleij static struct regmap *map; 195*f5bf0ee4SLinus Walleij int irq; 196*f5bf0ee4SLinus Walleij int ret; 197*f5bf0ee4SLinus Walleij u32 val; 198*f5bf0ee4SLinus Walleij 199*f5bf0ee4SLinus Walleij map = syscon_regmap_lookup_by_phandle(np, "syscon"); 200*f5bf0ee4SLinus Walleij if (IS_ERR(map)) { 201*f5bf0ee4SLinus Walleij pr_err("Can't get regmap for syscon handle"); 202*f5bf0ee4SLinus Walleij return -ENODEV; 203*f5bf0ee4SLinus Walleij } 204*f5bf0ee4SLinus Walleij ret = regmap_read(map, GLOBAL_STATUS, &val); 205*f5bf0ee4SLinus Walleij if (ret) { 206*f5bf0ee4SLinus Walleij pr_err("Can't read syscon status register"); 207*f5bf0ee4SLinus Walleij return -ENXIO; 208*f5bf0ee4SLinus Walleij } 209*f5bf0ee4SLinus Walleij 210*f5bf0ee4SLinus Walleij base = of_iomap(np, 0); 211*f5bf0ee4SLinus Walleij if (!base) { 212*f5bf0ee4SLinus Walleij pr_err("Can't remap registers"); 213*f5bf0ee4SLinus Walleij return -ENXIO; 214*f5bf0ee4SLinus Walleij } 215*f5bf0ee4SLinus Walleij /* IRQ for timer 1 */ 216*f5bf0ee4SLinus Walleij irq = irq_of_parse_and_map(np, 0); 217*f5bf0ee4SLinus Walleij if (irq <= 0) { 218*f5bf0ee4SLinus Walleij pr_err("Can't parse IRQ"); 219*f5bf0ee4SLinus Walleij return -EINVAL; 220*f5bf0ee4SLinus Walleij } 221*f5bf0ee4SLinus Walleij 222*f5bf0ee4SLinus Walleij tick_rate = REG_TO_AHB_SPEED(val) * 1000000; 223*f5bf0ee4SLinus Walleij printk(KERN_INFO "Bus: %dMHz", tick_rate / 1000000); 224*f5bf0ee4SLinus Walleij 225*f5bf0ee4SLinus Walleij tick_rate /= 6; /* APB bus run AHB*(1/6) */ 226*f5bf0ee4SLinus Walleij 227*f5bf0ee4SLinus Walleij switch (val & CPU_AHB_RATIO_MASK) { 228*f5bf0ee4SLinus Walleij case CPU_AHB_1_1: 229*f5bf0ee4SLinus Walleij printk(KERN_CONT "(1/1)\n"); 230*f5bf0ee4SLinus Walleij break; 231*f5bf0ee4SLinus Walleij case CPU_AHB_3_2: 232*f5bf0ee4SLinus Walleij printk(KERN_CONT "(3/2)\n"); 233*f5bf0ee4SLinus Walleij break; 234*f5bf0ee4SLinus Walleij case CPU_AHB_24_13: 235*f5bf0ee4SLinus Walleij printk(KERN_CONT "(24/13)\n"); 236*f5bf0ee4SLinus Walleij break; 237*f5bf0ee4SLinus Walleij case CPU_AHB_2_1: 238*f5bf0ee4SLinus Walleij printk(KERN_CONT "(2/1)\n"); 239*f5bf0ee4SLinus Walleij break; 240*f5bf0ee4SLinus Walleij } 241*f5bf0ee4SLinus Walleij 242*f5bf0ee4SLinus Walleij /* 243*f5bf0ee4SLinus Walleij * Reset the interrupt mask and status 244*f5bf0ee4SLinus Walleij */ 245*f5bf0ee4SLinus Walleij writel(TIMER_INT_ALL_MASK, base + TIMER_INTR_MASK); 246*f5bf0ee4SLinus Walleij writel(0, base + TIMER_INTR_STATE); 247*f5bf0ee4SLinus Walleij writel(TIMER_DEFAULT_FLAGS, base + TIMER_CR); 248*f5bf0ee4SLinus Walleij 249*f5bf0ee4SLinus Walleij /* 250*f5bf0ee4SLinus Walleij * Setup free-running clocksource timer (interrupts 251*f5bf0ee4SLinus Walleij * disabled.) 252*f5bf0ee4SLinus Walleij */ 253*f5bf0ee4SLinus Walleij writel(0, base + TIMER3_COUNT); 254*f5bf0ee4SLinus Walleij writel(0, base + TIMER3_LOAD); 255*f5bf0ee4SLinus Walleij writel(0, base + TIMER3_MATCH1); 256*f5bf0ee4SLinus Walleij writel(0, base + TIMER3_MATCH2); 257*f5bf0ee4SLinus Walleij clocksource_mmio_init(base + TIMER3_COUNT, 258*f5bf0ee4SLinus Walleij "fttmr010_clocksource", tick_rate, 259*f5bf0ee4SLinus Walleij 300, 32, clocksource_mmio_readl_up); 260*f5bf0ee4SLinus Walleij sched_clock_register(fttmr010_read_sched_clock, 32, tick_rate); 261*f5bf0ee4SLinus Walleij 262*f5bf0ee4SLinus Walleij /* 263*f5bf0ee4SLinus Walleij * Setup clockevent timer (interrupt-driven.) 264*f5bf0ee4SLinus Walleij */ 265*f5bf0ee4SLinus Walleij writel(0, base + TIMER1_COUNT); 266*f5bf0ee4SLinus Walleij writel(0, base + TIMER1_LOAD); 267*f5bf0ee4SLinus Walleij writel(0, base + TIMER1_MATCH1); 268*f5bf0ee4SLinus Walleij writel(0, base + TIMER1_MATCH2); 269*f5bf0ee4SLinus Walleij setup_irq(irq, &fttmr010_timer_irq); 270*f5bf0ee4SLinus Walleij fttmr010_clockevent.cpumask = cpumask_of(0); 271*f5bf0ee4SLinus Walleij clockevents_config_and_register(&fttmr010_clockevent, tick_rate, 272*f5bf0ee4SLinus Walleij 1, 0xffffffff); 273*f5bf0ee4SLinus Walleij 274*f5bf0ee4SLinus Walleij return 0; 275*f5bf0ee4SLinus Walleij } 276*f5bf0ee4SLinus Walleij CLOCKSOURCE_OF_DECLARE(gemini, "cortina,gemini-timer", gemini_timer_of_init); 277