1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Conexant Digicolor timer driver 4 * 5 * Author: Baruch Siach <baruch@tkos.co.il> 6 * 7 * Copyright (C) 2014 Paradox Innovation Ltd. 8 * 9 * Based on: 10 * Allwinner SoCs hstimer driver 11 * 12 * Copyright (C) 2013 Maxime Ripard 13 * 14 * Maxime Ripard <maxime.ripard@free-electrons.com> 15 */ 16 17 /* 18 * Conexant Digicolor SoCs have 8 configurable timers, named from "Timer A" to 19 * "Timer H". Timer A is the only one with watchdog support, so it is dedicated 20 * to the watchdog driver. This driver uses Timer B for sched_clock(), and 21 * Timer C for clockevents. 22 */ 23 24 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 25 26 #include <linux/clk.h> 27 #include <linux/clockchips.h> 28 #include <linux/interrupt.h> 29 #include <linux/irq.h> 30 #include <linux/irqreturn.h> 31 #include <linux/sched/clock.h> 32 #include <linux/sched_clock.h> 33 #include <linux/of.h> 34 #include <linux/of_address.h> 35 #include <linux/of_irq.h> 36 37 enum { 38 TIMER_A, 39 TIMER_B, 40 TIMER_C, 41 TIMER_D, 42 TIMER_E, 43 TIMER_F, 44 TIMER_G, 45 TIMER_H, 46 }; 47 48 #define CONTROL(t) ((t)*8) 49 #define COUNT(t) ((t)*8 + 4) 50 51 #define CONTROL_DISABLE 0 52 #define CONTROL_ENABLE BIT(0) 53 #define CONTROL_MODE(m) ((m) << 4) 54 #define CONTROL_MODE_ONESHOT CONTROL_MODE(1) 55 #define CONTROL_MODE_PERIODIC CONTROL_MODE(2) 56 57 struct digicolor_timer { 58 struct clock_event_device ce; 59 void __iomem *base; 60 u32 ticks_per_jiffy; 61 int timer_id; /* one of TIMER_* */ 62 }; 63 64 static struct digicolor_timer *dc_timer(struct clock_event_device *ce) 65 { 66 return container_of(ce, struct digicolor_timer, ce); 67 } 68 69 static inline void dc_timer_disable(struct clock_event_device *ce) 70 { 71 struct digicolor_timer *dt = dc_timer(ce); 72 writeb(CONTROL_DISABLE, dt->base + CONTROL(dt->timer_id)); 73 } 74 75 static inline void dc_timer_enable(struct clock_event_device *ce, u32 mode) 76 { 77 struct digicolor_timer *dt = dc_timer(ce); 78 writeb(CONTROL_ENABLE | mode, dt->base + CONTROL(dt->timer_id)); 79 } 80 81 static inline void dc_timer_set_count(struct clock_event_device *ce, 82 unsigned long count) 83 { 84 struct digicolor_timer *dt = dc_timer(ce); 85 writel(count, dt->base + COUNT(dt->timer_id)); 86 } 87 88 static int digicolor_clkevt_shutdown(struct clock_event_device *ce) 89 { 90 dc_timer_disable(ce); 91 return 0; 92 } 93 94 static int digicolor_clkevt_set_oneshot(struct clock_event_device *ce) 95 { 96 dc_timer_disable(ce); 97 dc_timer_enable(ce, CONTROL_MODE_ONESHOT); 98 return 0; 99 } 100 101 static int digicolor_clkevt_set_periodic(struct clock_event_device *ce) 102 { 103 struct digicolor_timer *dt = dc_timer(ce); 104 105 dc_timer_disable(ce); 106 dc_timer_set_count(ce, dt->ticks_per_jiffy); 107 dc_timer_enable(ce, CONTROL_MODE_PERIODIC); 108 return 0; 109 } 110 111 static int digicolor_clkevt_next_event(unsigned long evt, 112 struct clock_event_device *ce) 113 { 114 dc_timer_disable(ce); 115 dc_timer_set_count(ce, evt); 116 dc_timer_enable(ce, CONTROL_MODE_ONESHOT); 117 118 return 0; 119 } 120 121 static struct digicolor_timer dc_timer_dev = { 122 .ce = { 123 .name = "digicolor_tick", 124 .rating = 340, 125 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, 126 .set_state_shutdown = digicolor_clkevt_shutdown, 127 .set_state_periodic = digicolor_clkevt_set_periodic, 128 .set_state_oneshot = digicolor_clkevt_set_oneshot, 129 .tick_resume = digicolor_clkevt_shutdown, 130 .set_next_event = digicolor_clkevt_next_event, 131 }, 132 .timer_id = TIMER_C, 133 }; 134 135 static irqreturn_t digicolor_timer_interrupt(int irq, void *dev_id) 136 { 137 struct clock_event_device *evt = dev_id; 138 139 evt->event_handler(evt); 140 141 return IRQ_HANDLED; 142 } 143 144 static u64 notrace digicolor_timer_sched_read(void) 145 { 146 return ~readl(dc_timer_dev.base + COUNT(TIMER_B)); 147 } 148 149 static int __init digicolor_timer_init(struct device_node *node) 150 { 151 unsigned long rate; 152 struct clk *clk; 153 int ret, irq; 154 155 /* 156 * timer registers are shared with the watchdog timer; 157 * don't map exclusively 158 */ 159 dc_timer_dev.base = of_iomap(node, 0); 160 if (!dc_timer_dev.base) { 161 pr_err("Can't map registers\n"); 162 return -ENXIO; 163 } 164 165 irq = irq_of_parse_and_map(node, dc_timer_dev.timer_id); 166 if (irq <= 0) { 167 pr_err("Can't parse IRQ\n"); 168 return -EINVAL; 169 } 170 171 clk = of_clk_get(node, 0); 172 if (IS_ERR(clk)) { 173 pr_err("Can't get timer clock\n"); 174 return PTR_ERR(clk); 175 } 176 clk_prepare_enable(clk); 177 rate = clk_get_rate(clk); 178 dc_timer_dev.ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); 179 180 writeb(CONTROL_DISABLE, dc_timer_dev.base + CONTROL(TIMER_B)); 181 writel(UINT_MAX, dc_timer_dev.base + COUNT(TIMER_B)); 182 writeb(CONTROL_ENABLE, dc_timer_dev.base + CONTROL(TIMER_B)); 183 184 sched_clock_register(digicolor_timer_sched_read, 32, rate); 185 clocksource_mmio_init(dc_timer_dev.base + COUNT(TIMER_B), node->name, 186 rate, 340, 32, clocksource_mmio_readl_down); 187 188 ret = request_irq(irq, digicolor_timer_interrupt, 189 IRQF_TIMER | IRQF_IRQPOLL, "digicolor_timerC", 190 &dc_timer_dev.ce); 191 if (ret) { 192 pr_warn("request of timer irq %d failed (%d)\n", irq, ret); 193 return ret; 194 } 195 196 dc_timer_dev.ce.cpumask = cpu_possible_mask; 197 dc_timer_dev.ce.irq = irq; 198 199 clockevents_config_and_register(&dc_timer_dev.ce, rate, 0, 0xffffffff); 200 201 return 0; 202 } 203 TIMER_OF_DECLARE(conexant_digicolor, "cnxt,cx92755-timer", 204 digicolor_timer_init); 205