Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * (C) Copyright 2009 Intel Corporation
0004  * Author: Jacob Pan (jacob.jun.pan@intel.com)
0005  *
0006  * Shared with ARM platforms, Jamie Iles, Picochip 2011
0007  *
0008  * Support for the Synopsys DesignWare APB Timers.
0009  */
0010 #include <linux/dw_apb_timer.h>
0011 #include <linux/delay.h>
0012 #include <linux/kernel.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/irq.h>
0015 #include <linux/io.h>
0016 #include <linux/slab.h>
0017 
0018 #define APBT_MIN_PERIOD         4
0019 #define APBT_MIN_DELTA_USEC     200
0020 
0021 #define APBTMR_N_LOAD_COUNT     0x00
0022 #define APBTMR_N_CURRENT_VALUE      0x04
0023 #define APBTMR_N_CONTROL        0x08
0024 #define APBTMR_N_EOI            0x0c
0025 #define APBTMR_N_INT_STATUS     0x10
0026 
0027 #define APBTMRS_INT_STATUS      0xa0
0028 #define APBTMRS_EOI         0xa4
0029 #define APBTMRS_RAW_INT_STATUS      0xa8
0030 #define APBTMRS_COMP_VERSION        0xac
0031 
0032 #define APBTMR_CONTROL_ENABLE       (1 << 0)
0033 /* 1: periodic, 0:free running. */
0034 #define APBTMR_CONTROL_MODE_PERIODIC    (1 << 1)
0035 #define APBTMR_CONTROL_INT      (1 << 2)
0036 
0037 static inline struct dw_apb_clock_event_device *
0038 ced_to_dw_apb_ced(struct clock_event_device *evt)
0039 {
0040     return container_of(evt, struct dw_apb_clock_event_device, ced);
0041 }
0042 
0043 static inline struct dw_apb_clocksource *
0044 clocksource_to_dw_apb_clocksource(struct clocksource *cs)
0045 {
0046     return container_of(cs, struct dw_apb_clocksource, cs);
0047 }
0048 
0049 static inline u32 apbt_readl(struct dw_apb_timer *timer, unsigned long offs)
0050 {
0051     return readl(timer->base + offs);
0052 }
0053 
0054 static inline void apbt_writel(struct dw_apb_timer *timer, u32 val,
0055             unsigned long offs)
0056 {
0057     writel(val, timer->base + offs);
0058 }
0059 
0060 static inline u32 apbt_readl_relaxed(struct dw_apb_timer *timer, unsigned long offs)
0061 {
0062     return readl_relaxed(timer->base + offs);
0063 }
0064 
0065 static inline void apbt_writel_relaxed(struct dw_apb_timer *timer, u32 val,
0066             unsigned long offs)
0067 {
0068     writel_relaxed(val, timer->base + offs);
0069 }
0070 
0071 static void apbt_disable_int(struct dw_apb_timer *timer)
0072 {
0073     u32 ctrl = apbt_readl(timer, APBTMR_N_CONTROL);
0074 
0075     ctrl |= APBTMR_CONTROL_INT;
0076     apbt_writel(timer, ctrl, APBTMR_N_CONTROL);
0077 }
0078 
0079 /**
0080  * dw_apb_clockevent_pause() - stop the clock_event_device from running
0081  *
0082  * @dw_ced: The APB clock to stop generating events.
0083  */
0084 void dw_apb_clockevent_pause(struct dw_apb_clock_event_device *dw_ced)
0085 {
0086     disable_irq(dw_ced->timer.irq);
0087     apbt_disable_int(&dw_ced->timer);
0088 }
0089 
0090 static void apbt_eoi(struct dw_apb_timer *timer)
0091 {
0092     apbt_readl_relaxed(timer, APBTMR_N_EOI);
0093 }
0094 
0095 static irqreturn_t dw_apb_clockevent_irq(int irq, void *data)
0096 {
0097     struct clock_event_device *evt = data;
0098     struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
0099 
0100     if (!evt->event_handler) {
0101         pr_info("Spurious APBT timer interrupt %d\n", irq);
0102         return IRQ_NONE;
0103     }
0104 
0105     if (dw_ced->eoi)
0106         dw_ced->eoi(&dw_ced->timer);
0107 
0108     evt->event_handler(evt);
0109     return IRQ_HANDLED;
0110 }
0111 
0112 static void apbt_enable_int(struct dw_apb_timer *timer)
0113 {
0114     u32 ctrl = apbt_readl(timer, APBTMR_N_CONTROL);
0115     /* clear pending intr */
0116     apbt_readl(timer, APBTMR_N_EOI);
0117     ctrl &= ~APBTMR_CONTROL_INT;
0118     apbt_writel(timer, ctrl, APBTMR_N_CONTROL);
0119 }
0120 
0121 static int apbt_shutdown(struct clock_event_device *evt)
0122 {
0123     struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
0124     u32 ctrl;
0125 
0126     pr_debug("%s CPU %d state=shutdown\n", __func__,
0127          cpumask_first(evt->cpumask));
0128 
0129     ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
0130     ctrl &= ~APBTMR_CONTROL_ENABLE;
0131     apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
0132     return 0;
0133 }
0134 
0135 static int apbt_set_oneshot(struct clock_event_device *evt)
0136 {
0137     struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
0138     u32 ctrl;
0139 
0140     pr_debug("%s CPU %d state=oneshot\n", __func__,
0141          cpumask_first(evt->cpumask));
0142 
0143     ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
0144     /*
0145      * set free running mode, this mode will let timer reload max
0146      * timeout which will give time (3min on 25MHz clock) to rearm
0147      * the next event, therefore emulate the one-shot mode.
0148      */
0149     ctrl &= ~APBTMR_CONTROL_ENABLE;
0150     ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
0151 
0152     apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
0153     /* write again to set free running mode */
0154     apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
0155 
0156     /*
0157      * DW APB p. 46, load counter with all 1s before starting free
0158      * running mode.
0159      */
0160     apbt_writel(&dw_ced->timer, ~0, APBTMR_N_LOAD_COUNT);
0161     ctrl &= ~APBTMR_CONTROL_INT;
0162     ctrl |= APBTMR_CONTROL_ENABLE;
0163     apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
0164     return 0;
0165 }
0166 
0167 static int apbt_set_periodic(struct clock_event_device *evt)
0168 {
0169     struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
0170     unsigned long period = DIV_ROUND_UP(dw_ced->timer.freq, HZ);
0171     u32 ctrl;
0172 
0173     pr_debug("%s CPU %d state=periodic\n", __func__,
0174          cpumask_first(evt->cpumask));
0175 
0176     ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
0177     ctrl |= APBTMR_CONTROL_MODE_PERIODIC;
0178     apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
0179     /*
0180      * DW APB p. 46, have to disable timer before load counter,
0181      * may cause sync problem.
0182      */
0183     ctrl &= ~APBTMR_CONTROL_ENABLE;
0184     apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
0185     udelay(1);
0186     pr_debug("Setting clock period %lu for HZ %d\n", period, HZ);
0187     apbt_writel(&dw_ced->timer, period, APBTMR_N_LOAD_COUNT);
0188     ctrl |= APBTMR_CONTROL_ENABLE;
0189     apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
0190     return 0;
0191 }
0192 
0193 static int apbt_resume(struct clock_event_device *evt)
0194 {
0195     struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
0196 
0197     pr_debug("%s CPU %d state=resume\n", __func__,
0198          cpumask_first(evt->cpumask));
0199 
0200     apbt_enable_int(&dw_ced->timer);
0201     return 0;
0202 }
0203 
0204 static int apbt_next_event(unsigned long delta,
0205                struct clock_event_device *evt)
0206 {
0207     u32 ctrl;
0208     struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
0209 
0210     /* Disable timer */
0211     ctrl = apbt_readl_relaxed(&dw_ced->timer, APBTMR_N_CONTROL);
0212     ctrl &= ~APBTMR_CONTROL_ENABLE;
0213     apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
0214     /* write new count */
0215     apbt_writel_relaxed(&dw_ced->timer, delta, APBTMR_N_LOAD_COUNT);
0216     ctrl |= APBTMR_CONTROL_ENABLE;
0217     apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
0218 
0219     return 0;
0220 }
0221 
0222 /**
0223  * dw_apb_clockevent_init() - use an APB timer as a clock_event_device
0224  *
0225  * @cpu:    The CPU the events will be targeted at or -1 if CPU affiliation
0226  *      isn't required.
0227  * @name:   The name used for the timer and the IRQ for it.
0228  * @rating: The rating to give the timer.
0229  * @base:   I/O base for the timer registers.
0230  * @irq:    The interrupt number to use for the timer.
0231  * @freq:   The frequency that the timer counts at.
0232  *
0233  * This creates a clock_event_device for using with the generic clock layer
0234  * but does not start and register it.  This should be done with
0235  * dw_apb_clockevent_register() as the next step.  If this is the first time
0236  * it has been called for a timer then the IRQ will be requested, if not it
0237  * just be enabled to allow CPU hotplug to avoid repeatedly requesting and
0238  * releasing the IRQ.
0239  */
0240 struct dw_apb_clock_event_device *
0241 dw_apb_clockevent_init(int cpu, const char *name, unsigned rating,
0242                void __iomem *base, int irq, unsigned long freq)
0243 {
0244     struct dw_apb_clock_event_device *dw_ced =
0245         kzalloc(sizeof(*dw_ced), GFP_KERNEL);
0246     int err;
0247 
0248     if (!dw_ced)
0249         return NULL;
0250 
0251     dw_ced->timer.base = base;
0252     dw_ced->timer.irq = irq;
0253     dw_ced->timer.freq = freq;
0254 
0255     clockevents_calc_mult_shift(&dw_ced->ced, freq, APBT_MIN_PERIOD);
0256     dw_ced->ced.max_delta_ns = clockevent_delta2ns(0x7fffffff,
0257                                &dw_ced->ced);
0258     dw_ced->ced.max_delta_ticks = 0x7fffffff;
0259     dw_ced->ced.min_delta_ns = clockevent_delta2ns(5000, &dw_ced->ced);
0260     dw_ced->ced.min_delta_ticks = 5000;
0261     dw_ced->ced.cpumask = cpu < 0 ? cpu_possible_mask : cpumask_of(cpu);
0262     dw_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC |
0263                 CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_DYNIRQ;
0264     dw_ced->ced.set_state_shutdown = apbt_shutdown;
0265     dw_ced->ced.set_state_periodic = apbt_set_periodic;
0266     dw_ced->ced.set_state_oneshot = apbt_set_oneshot;
0267     dw_ced->ced.set_state_oneshot_stopped = apbt_shutdown;
0268     dw_ced->ced.tick_resume = apbt_resume;
0269     dw_ced->ced.set_next_event = apbt_next_event;
0270     dw_ced->ced.irq = dw_ced->timer.irq;
0271     dw_ced->ced.rating = rating;
0272     dw_ced->ced.name = name;
0273 
0274     dw_ced->eoi = apbt_eoi;
0275     err = request_irq(irq, dw_apb_clockevent_irq,
0276               IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
0277               dw_ced->ced.name, &dw_ced->ced);
0278     if (err) {
0279         pr_err("failed to request timer irq\n");
0280         kfree(dw_ced);
0281         dw_ced = NULL;
0282     }
0283 
0284     return dw_ced;
0285 }
0286 
0287 /**
0288  * dw_apb_clockevent_resume() - resume a clock that has been paused.
0289  *
0290  * @dw_ced: The APB clock to resume.
0291  */
0292 void dw_apb_clockevent_resume(struct dw_apb_clock_event_device *dw_ced)
0293 {
0294     enable_irq(dw_ced->timer.irq);
0295 }
0296 
0297 /**
0298  * dw_apb_clockevent_stop() - stop the clock_event_device and release the IRQ.
0299  *
0300  * @dw_ced: The APB clock to stop generating the events.
0301  */
0302 void dw_apb_clockevent_stop(struct dw_apb_clock_event_device *dw_ced)
0303 {
0304     free_irq(dw_ced->timer.irq, &dw_ced->ced);
0305 }
0306 
0307 /**
0308  * dw_apb_clockevent_register() - register the clock with the generic layer
0309  *
0310  * @dw_ced: The APB clock to register as a clock_event_device.
0311  */
0312 void dw_apb_clockevent_register(struct dw_apb_clock_event_device *dw_ced)
0313 {
0314     apbt_writel(&dw_ced->timer, 0, APBTMR_N_CONTROL);
0315     clockevents_register_device(&dw_ced->ced);
0316     apbt_enable_int(&dw_ced->timer);
0317 }
0318 
0319 /**
0320  * dw_apb_clocksource_start() - start the clocksource counting.
0321  *
0322  * @dw_cs:  The clocksource to start.
0323  *
0324  * This is used to start the clocksource before registration and can be used
0325  * to enable calibration of timers.
0326  */
0327 void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs)
0328 {
0329     /*
0330      * start count down from 0xffff_ffff. this is done by toggling the
0331      * enable bit then load initial load count to ~0.
0332      */
0333     u32 ctrl = apbt_readl(&dw_cs->timer, APBTMR_N_CONTROL);
0334 
0335     ctrl &= ~APBTMR_CONTROL_ENABLE;
0336     apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL);
0337     apbt_writel(&dw_cs->timer, ~0, APBTMR_N_LOAD_COUNT);
0338     /* enable, mask interrupt */
0339     ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
0340     ctrl |= (APBTMR_CONTROL_ENABLE | APBTMR_CONTROL_INT);
0341     apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL);
0342     /* read it once to get cached counter value initialized */
0343     dw_apb_clocksource_read(dw_cs);
0344 }
0345 
0346 static u64 __apbt_read_clocksource(struct clocksource *cs)
0347 {
0348     u32 current_count;
0349     struct dw_apb_clocksource *dw_cs =
0350         clocksource_to_dw_apb_clocksource(cs);
0351 
0352     current_count = apbt_readl_relaxed(&dw_cs->timer,
0353                     APBTMR_N_CURRENT_VALUE);
0354 
0355     return (u64)~current_count;
0356 }
0357 
0358 static void apbt_restart_clocksource(struct clocksource *cs)
0359 {
0360     struct dw_apb_clocksource *dw_cs =
0361         clocksource_to_dw_apb_clocksource(cs);
0362 
0363     dw_apb_clocksource_start(dw_cs);
0364 }
0365 
0366 /**
0367  * dw_apb_clocksource_init() - use an APB timer as a clocksource.
0368  *
0369  * @rating: The rating to give the clocksource.
0370  * @name:   The name for the clocksource.
0371  * @base:   The I/O base for the timer registers.
0372  * @freq:   The frequency that the timer counts at.
0373  *
0374  * This creates a clocksource using an APB timer but does not yet register it
0375  * with the clocksource system.  This should be done with
0376  * dw_apb_clocksource_register() as the next step.
0377  */
0378 struct dw_apb_clocksource *
0379 dw_apb_clocksource_init(unsigned rating, const char *name, void __iomem *base,
0380             unsigned long freq)
0381 {
0382     struct dw_apb_clocksource *dw_cs = kzalloc(sizeof(*dw_cs), GFP_KERNEL);
0383 
0384     if (!dw_cs)
0385         return NULL;
0386 
0387     dw_cs->timer.base = base;
0388     dw_cs->timer.freq = freq;
0389     dw_cs->cs.name = name;
0390     dw_cs->cs.rating = rating;
0391     dw_cs->cs.read = __apbt_read_clocksource;
0392     dw_cs->cs.mask = CLOCKSOURCE_MASK(32);
0393     dw_cs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
0394     dw_cs->cs.resume = apbt_restart_clocksource;
0395 
0396     return dw_cs;
0397 }
0398 
0399 /**
0400  * dw_apb_clocksource_register() - register the APB clocksource.
0401  *
0402  * @dw_cs:  The clocksource to register.
0403  */
0404 void dw_apb_clocksource_register(struct dw_apb_clocksource *dw_cs)
0405 {
0406     clocksource_register_hz(&dw_cs->cs, dw_cs->timer.freq);
0407 }
0408 
0409 /**
0410  * dw_apb_clocksource_read() - read the current value of a clocksource.
0411  *
0412  * @dw_cs:  The clocksource to read.
0413  */
0414 u64 dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs)
0415 {
0416     return (u64)~apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE);
0417 }