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