root/drivers/clocksource/timer-ixp4xx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. to_ixp4xx_timer
  2. ixp4xx_read_timer
  3. ixp4xx_read_sched_clock
  4. ixp4xx_clocksource_read
  5. ixp4xx_timer_interrupt
  6. ixp4xx_set_next_event
  7. ixp4xx_shutdown
  8. ixp4xx_set_oneshot
  9. ixp4xx_set_periodic
  10. ixp4xx_resume
  11. ixp4xx_timer_register
  12. ixp4xx_timer_setup
  13. ixp4xx_of_timer_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * IXP4 timer driver
   4  * Copyright (C) 2019 Linus Walleij <linus.walleij@linaro.org>
   5  *
   6  * Based on arch/arm/mach-ixp4xx/common.c
   7  * Copyright 2002 (C) Intel Corporation
   8  * Copyright 2003-2004 (C) MontaVista, Software, Inc.
   9  * Copyright (C) Deepak Saxena <dsaxena@plexity.net>
  10  */
  11 #include <linux/interrupt.h>
  12 #include <linux/io.h>
  13 #include <linux/clockchips.h>
  14 #include <linux/clocksource.h>
  15 #include <linux/sched_clock.h>
  16 #include <linux/slab.h>
  17 #include <linux/bitops.h>
  18 #include <linux/delay.h>
  19 #include <linux/of_address.h>
  20 #include <linux/of_irq.h>
  21 /* Goes away with OF conversion */
  22 #include <linux/platform_data/timer-ixp4xx.h>
  23 
  24 /*
  25  * Constants to make it easy to access Timer Control/Status registers
  26  */
  27 #define IXP4XX_OSTS_OFFSET      0x00  /* Continuous Timestamp */
  28 #define IXP4XX_OST1_OFFSET      0x04  /* Timer 1 Timestamp */
  29 #define IXP4XX_OSRT1_OFFSET     0x08  /* Timer 1 Reload */
  30 #define IXP4XX_OST2_OFFSET      0x0C  /* Timer 2 Timestamp */
  31 #define IXP4XX_OSRT2_OFFSET     0x10  /* Timer 2 Reload */
  32 #define IXP4XX_OSWT_OFFSET      0x14  /* Watchdog Timer */
  33 #define IXP4XX_OSWE_OFFSET      0x18  /* Watchdog Enable */
  34 #define IXP4XX_OSWK_OFFSET      0x1C  /* Watchdog Key */
  35 #define IXP4XX_OSST_OFFSET      0x20  /* Timer Status */
  36 
  37 /*
  38  * Timer register values and bit definitions
  39  */
  40 #define IXP4XX_OST_ENABLE               0x00000001
  41 #define IXP4XX_OST_ONE_SHOT             0x00000002
  42 /* Low order bits of reload value ignored */
  43 #define IXP4XX_OST_RELOAD_MASK          0x00000003
  44 #define IXP4XX_OST_DISABLED             0x00000000
  45 #define IXP4XX_OSST_TIMER_1_PEND        0x00000001
  46 #define IXP4XX_OSST_TIMER_2_PEND        0x00000002
  47 #define IXP4XX_OSST_TIMER_TS_PEND       0x00000004
  48 #define IXP4XX_OSST_TIMER_WDOG_PEND     0x00000008
  49 #define IXP4XX_OSST_TIMER_WARM_RESET    0x00000010
  50 
  51 #define IXP4XX_WDT_KEY                  0x0000482E
  52 #define IXP4XX_WDT_RESET_ENABLE         0x00000001
  53 #define IXP4XX_WDT_IRQ_ENABLE           0x00000002
  54 #define IXP4XX_WDT_COUNT_ENABLE         0x00000004
  55 
  56 struct ixp4xx_timer {
  57         void __iomem *base;
  58         unsigned int tick_rate;
  59         u32 latch;
  60         struct clock_event_device clkevt;
  61 #ifdef CONFIG_ARM
  62         struct delay_timer delay_timer;
  63 #endif
  64 };
  65 
  66 /*
  67  * A local singleton used by sched_clock and delay timer reads, which are
  68  * fast and stateless
  69  */
  70 static struct ixp4xx_timer *local_ixp4xx_timer;
  71 
  72 static inline struct ixp4xx_timer *
  73 to_ixp4xx_timer(struct clock_event_device *evt)
  74 {
  75         return container_of(evt, struct ixp4xx_timer, clkevt);
  76 }
  77 
  78 static unsigned long ixp4xx_read_timer(void)
  79 {
  80         return __raw_readl(local_ixp4xx_timer->base + IXP4XX_OSTS_OFFSET);
  81 }
  82 
  83 static u64 notrace ixp4xx_read_sched_clock(void)
  84 {
  85         return ixp4xx_read_timer();
  86 }
  87 
  88 static u64 ixp4xx_clocksource_read(struct clocksource *c)
  89 {
  90         return ixp4xx_read_timer();
  91 }
  92 
  93 static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id)
  94 {
  95         struct ixp4xx_timer *tmr = dev_id;
  96         struct clock_event_device *evt = &tmr->clkevt;
  97 
  98         /* Clear Pending Interrupt */
  99         __raw_writel(IXP4XX_OSST_TIMER_1_PEND,
 100                      tmr->base + IXP4XX_OSST_OFFSET);
 101 
 102         evt->event_handler(evt);
 103 
 104         return IRQ_HANDLED;
 105 }
 106 
 107 static int ixp4xx_set_next_event(unsigned long cycles,
 108                                  struct clock_event_device *evt)
 109 {
 110         struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
 111         u32 val;
 112 
 113         val = __raw_readl(tmr->base + IXP4XX_OSRT1_OFFSET);
 114         /* Keep enable/oneshot bits */
 115         val &= IXP4XX_OST_RELOAD_MASK;
 116         __raw_writel((cycles & ~IXP4XX_OST_RELOAD_MASK) | val,
 117                      tmr->base + IXP4XX_OSRT1_OFFSET);
 118 
 119         return 0;
 120 }
 121 
 122 static int ixp4xx_shutdown(struct clock_event_device *evt)
 123 {
 124         struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
 125         u32 val;
 126 
 127         val = __raw_readl(tmr->base + IXP4XX_OSRT1_OFFSET);
 128         val &= ~IXP4XX_OST_ENABLE;
 129         __raw_writel(val, tmr->base + IXP4XX_OSRT1_OFFSET);
 130 
 131         return 0;
 132 }
 133 
 134 static int ixp4xx_set_oneshot(struct clock_event_device *evt)
 135 {
 136         struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
 137 
 138         __raw_writel(IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT,
 139                      tmr->base + IXP4XX_OSRT1_OFFSET);
 140 
 141         return 0;
 142 }
 143 
 144 static int ixp4xx_set_periodic(struct clock_event_device *evt)
 145 {
 146         struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
 147         u32 val;
 148 
 149         val = tmr->latch & ~IXP4XX_OST_RELOAD_MASK;
 150         val |= IXP4XX_OST_ENABLE;
 151         __raw_writel(val, tmr->base + IXP4XX_OSRT1_OFFSET);
 152 
 153         return 0;
 154 }
 155 
 156 static int ixp4xx_resume(struct clock_event_device *evt)
 157 {
 158         struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
 159         u32 val;
 160 
 161         val = __raw_readl(tmr->base + IXP4XX_OSRT1_OFFSET);
 162         val |= IXP4XX_OST_ENABLE;
 163         __raw_writel(val, tmr->base + IXP4XX_OSRT1_OFFSET);
 164 
 165         return 0;
 166 }
 167 
 168 /*
 169  * IXP4xx timer tick
 170  * We use OS timer1 on the CPU for the timer tick and the timestamp
 171  * counter as a source of real clock ticks to account for missed jiffies.
 172  */
 173 static __init int ixp4xx_timer_register(void __iomem *base,
 174                                         int timer_irq,
 175                                         unsigned int timer_freq)
 176 {
 177         struct ixp4xx_timer *tmr;
 178         int ret;
 179 
 180         tmr = kzalloc(sizeof(*tmr), GFP_KERNEL);
 181         if (!tmr)
 182                 return -ENOMEM;
 183         tmr->base = base;
 184         tmr->tick_rate = timer_freq;
 185 
 186         /*
 187          * The timer register doesn't allow to specify the two least
 188          * significant bits of the timeout value and assumes them being zero.
 189          * So make sure the latch is the best value with the two least
 190          * significant bits unset.
 191          */
 192         tmr->latch = DIV_ROUND_CLOSEST(timer_freq,
 193                                        (IXP4XX_OST_RELOAD_MASK + 1) * HZ)
 194                 * (IXP4XX_OST_RELOAD_MASK + 1);
 195 
 196         local_ixp4xx_timer = tmr;
 197 
 198         /* Reset/disable counter */
 199         __raw_writel(0, tmr->base + IXP4XX_OSRT1_OFFSET);
 200 
 201         /* Clear any pending interrupt on timer 1 */
 202         __raw_writel(IXP4XX_OSST_TIMER_1_PEND,
 203                      tmr->base + IXP4XX_OSST_OFFSET);
 204 
 205         /* Reset time-stamp counter */
 206         __raw_writel(0, tmr->base + IXP4XX_OSTS_OFFSET);
 207 
 208         clocksource_mmio_init(NULL, "OSTS", timer_freq, 200, 32,
 209                               ixp4xx_clocksource_read);
 210 
 211         tmr->clkevt.name = "ixp4xx timer1";
 212         tmr->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
 213         tmr->clkevt.rating = 200;
 214         tmr->clkevt.set_state_shutdown = ixp4xx_shutdown;
 215         tmr->clkevt.set_state_periodic = ixp4xx_set_periodic;
 216         tmr->clkevt.set_state_oneshot = ixp4xx_set_oneshot;
 217         tmr->clkevt.tick_resume = ixp4xx_resume;
 218         tmr->clkevt.set_next_event = ixp4xx_set_next_event;
 219         tmr->clkevt.cpumask = cpumask_of(0);
 220         tmr->clkevt.irq = timer_irq;
 221         ret = request_irq(timer_irq, ixp4xx_timer_interrupt,
 222                           IRQF_TIMER, "IXP4XX-TIMER1", tmr);
 223         if (ret) {
 224                 pr_crit("no timer IRQ\n");
 225                 return -ENODEV;
 226         }
 227         clockevents_config_and_register(&tmr->clkevt, timer_freq,
 228                                         0xf, 0xfffffffe);
 229 
 230         sched_clock_register(ixp4xx_read_sched_clock, 32, timer_freq);
 231 
 232 #ifdef CONFIG_ARM
 233         /* Also use this timer for delays */
 234         tmr->delay_timer.read_current_timer = ixp4xx_read_timer;
 235         tmr->delay_timer.freq = timer_freq;
 236         register_current_timer_delay(&tmr->delay_timer);
 237 #endif
 238 
 239         return 0;
 240 }
 241 
 242 /**
 243  * ixp4xx_timer_setup() - Timer setup function to be called from boardfiles
 244  * @timerbase: physical base of timer block
 245  * @timer_irq: Linux IRQ number for the timer
 246  * @timer_freq: Fixed frequency of the timer
 247  */
 248 void __init ixp4xx_timer_setup(resource_size_t timerbase,
 249                                int timer_irq,
 250                                unsigned int timer_freq)
 251 {
 252         void __iomem *base;
 253 
 254         base = ioremap(timerbase, 0x100);
 255         if (!base) {
 256                 pr_crit("IXP4xx: can't remap timer\n");
 257                 return;
 258         }
 259         ixp4xx_timer_register(base, timer_irq, timer_freq);
 260 }
 261 EXPORT_SYMBOL_GPL(ixp4xx_timer_setup);
 262 
 263 #ifdef CONFIG_OF
 264 static __init int ixp4xx_of_timer_init(struct device_node *np)
 265 {
 266         void __iomem *base;
 267         int irq;
 268         int ret;
 269 
 270         base = of_iomap(np, 0);
 271         if (!base) {
 272                 pr_crit("IXP4xx: can't remap timer\n");
 273                 return -ENODEV;
 274         }
 275 
 276         irq = irq_of_parse_and_map(np, 0);
 277         if (irq <= 0) {
 278                 pr_err("Can't parse IRQ\n");
 279                 ret = -EINVAL;
 280                 goto out_unmap;
 281         }
 282 
 283         /* TODO: get some fixed clocks into the device tree */
 284         ret = ixp4xx_timer_register(base, irq, 66666000);
 285         if (ret)
 286                 goto out_unmap;
 287         return 0;
 288 
 289 out_unmap:
 290         iounmap(base);
 291         return ret;
 292 }
 293 TIMER_OF_DECLARE(ixp4xx, "intel,ixp4xx-timer", ixp4xx_of_timer_init);
 294 #endif

/* [<][>][^][v][top][bottom][index][help] */