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