Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Conexant Digicolor timer driver
0004  *
0005  * Author: Baruch Siach <baruch@tkos.co.il>
0006  *
0007  * Copyright (C) 2014 Paradox Innovation Ltd.
0008  *
0009  * Based on:
0010  *  Allwinner SoCs hstimer driver
0011  *
0012  * Copyright (C) 2013 Maxime Ripard
0013  *
0014  * Maxime Ripard <maxime.ripard@free-electrons.com>
0015  */
0016 
0017 /*
0018  * Conexant Digicolor SoCs have 8 configurable timers, named from "Timer A" to
0019  * "Timer H". Timer A is the only one with watchdog support, so it is dedicated
0020  * to the watchdog driver. This driver uses Timer B for sched_clock(), and
0021  * Timer C for clockevents.
0022  */
0023 
0024 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0025 
0026 #include <linux/clk.h>
0027 #include <linux/clockchips.h>
0028 #include <linux/interrupt.h>
0029 #include <linux/irq.h>
0030 #include <linux/irqreturn.h>
0031 #include <linux/sched/clock.h>
0032 #include <linux/sched_clock.h>
0033 #include <linux/of.h>
0034 #include <linux/of_address.h>
0035 #include <linux/of_irq.h>
0036 
0037 enum {
0038     TIMER_A,
0039     TIMER_B,
0040     TIMER_C,
0041     TIMER_D,
0042     TIMER_E,
0043     TIMER_F,
0044     TIMER_G,
0045     TIMER_H,
0046 };
0047 
0048 #define CONTROL(t)  ((t)*8)
0049 #define COUNT(t)    ((t)*8 + 4)
0050 
0051 #define CONTROL_DISABLE     0
0052 #define CONTROL_ENABLE      BIT(0)
0053 #define CONTROL_MODE(m)     ((m) << 4)
0054 #define CONTROL_MODE_ONESHOT    CONTROL_MODE(1)
0055 #define CONTROL_MODE_PERIODIC   CONTROL_MODE(2)
0056 
0057 struct digicolor_timer {
0058     struct clock_event_device ce;
0059     void __iomem *base;
0060     u32 ticks_per_jiffy;
0061     int timer_id; /* one of TIMER_* */
0062 };
0063 
0064 static struct digicolor_timer *dc_timer(struct clock_event_device *ce)
0065 {
0066     return container_of(ce, struct digicolor_timer, ce);
0067 }
0068 
0069 static inline void dc_timer_disable(struct clock_event_device *ce)
0070 {
0071     struct digicolor_timer *dt = dc_timer(ce);
0072     writeb(CONTROL_DISABLE, dt->base + CONTROL(dt->timer_id));
0073 }
0074 
0075 static inline void dc_timer_enable(struct clock_event_device *ce, u32 mode)
0076 {
0077     struct digicolor_timer *dt = dc_timer(ce);
0078     writeb(CONTROL_ENABLE | mode, dt->base + CONTROL(dt->timer_id));
0079 }
0080 
0081 static inline void dc_timer_set_count(struct clock_event_device *ce,
0082                       unsigned long count)
0083 {
0084     struct digicolor_timer *dt = dc_timer(ce);
0085     writel(count, dt->base + COUNT(dt->timer_id));
0086 }
0087 
0088 static int digicolor_clkevt_shutdown(struct clock_event_device *ce)
0089 {
0090     dc_timer_disable(ce);
0091     return 0;
0092 }
0093 
0094 static int digicolor_clkevt_set_oneshot(struct clock_event_device *ce)
0095 {
0096     dc_timer_disable(ce);
0097     dc_timer_enable(ce, CONTROL_MODE_ONESHOT);
0098     return 0;
0099 }
0100 
0101 static int digicolor_clkevt_set_periodic(struct clock_event_device *ce)
0102 {
0103     struct digicolor_timer *dt = dc_timer(ce);
0104 
0105     dc_timer_disable(ce);
0106     dc_timer_set_count(ce, dt->ticks_per_jiffy);
0107     dc_timer_enable(ce, CONTROL_MODE_PERIODIC);
0108     return 0;
0109 }
0110 
0111 static int digicolor_clkevt_next_event(unsigned long evt,
0112                        struct clock_event_device *ce)
0113 {
0114     dc_timer_disable(ce);
0115     dc_timer_set_count(ce, evt);
0116     dc_timer_enable(ce, CONTROL_MODE_ONESHOT);
0117 
0118     return 0;
0119 }
0120 
0121 static struct digicolor_timer dc_timer_dev = {
0122     .ce = {
0123         .name = "digicolor_tick",
0124         .rating = 340,
0125         .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
0126         .set_state_shutdown = digicolor_clkevt_shutdown,
0127         .set_state_periodic = digicolor_clkevt_set_periodic,
0128         .set_state_oneshot = digicolor_clkevt_set_oneshot,
0129         .tick_resume = digicolor_clkevt_shutdown,
0130         .set_next_event = digicolor_clkevt_next_event,
0131     },
0132     .timer_id = TIMER_C,
0133 };
0134 
0135 static irqreturn_t digicolor_timer_interrupt(int irq, void *dev_id)
0136 {
0137     struct clock_event_device *evt = dev_id;
0138 
0139     evt->event_handler(evt);
0140 
0141     return IRQ_HANDLED;
0142 }
0143 
0144 static u64 notrace digicolor_timer_sched_read(void)
0145 {
0146     return ~readl(dc_timer_dev.base + COUNT(TIMER_B));
0147 }
0148 
0149 static int __init digicolor_timer_init(struct device_node *node)
0150 {
0151     unsigned long rate;
0152     struct clk *clk;
0153     int ret, irq;
0154 
0155     /*
0156      * timer registers are shared with the watchdog timer;
0157      * don't map exclusively
0158      */
0159     dc_timer_dev.base = of_iomap(node, 0);
0160     if (!dc_timer_dev.base) {
0161         pr_err("Can't map registers\n");
0162         return -ENXIO;
0163     }
0164 
0165     irq = irq_of_parse_and_map(node, dc_timer_dev.timer_id);
0166     if (irq <= 0) {
0167         pr_err("Can't parse IRQ\n");
0168         return -EINVAL;
0169     }
0170 
0171     clk = of_clk_get(node, 0);
0172     if (IS_ERR(clk)) {
0173         pr_err("Can't get timer clock\n");
0174         return PTR_ERR(clk);
0175     }
0176     clk_prepare_enable(clk);
0177     rate = clk_get_rate(clk);
0178     dc_timer_dev.ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
0179 
0180     writeb(CONTROL_DISABLE, dc_timer_dev.base + CONTROL(TIMER_B));
0181     writel(UINT_MAX, dc_timer_dev.base + COUNT(TIMER_B));
0182     writeb(CONTROL_ENABLE, dc_timer_dev.base + CONTROL(TIMER_B));
0183 
0184     sched_clock_register(digicolor_timer_sched_read, 32, rate);
0185     clocksource_mmio_init(dc_timer_dev.base + COUNT(TIMER_B), node->name,
0186                   rate, 340, 32, clocksource_mmio_readl_down);
0187 
0188     ret = request_irq(irq, digicolor_timer_interrupt,
0189               IRQF_TIMER | IRQF_IRQPOLL, "digicolor_timerC",
0190               &dc_timer_dev.ce);
0191     if (ret) {
0192         pr_warn("request of timer irq %d failed (%d)\n", irq, ret);
0193         return ret;
0194     }
0195 
0196     dc_timer_dev.ce.cpumask = cpu_possible_mask;
0197     dc_timer_dev.ce.irq = irq;
0198 
0199     clockevents_config_and_register(&dc_timer_dev.ce, rate, 0, 0xffffffff);
0200 
0201     return 0;
0202 }
0203 TIMER_OF_DECLARE(conexant_digicolor, "cnxt,cx92755-timer",
0204                digicolor_timer_init);