1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2017 Spreadtrum Communications Inc. 4 */ 5 6 #include <linux/init.h> 7 #include <linux/interrupt.h> 8 9 #include "timer-of.h" 10 11 #define TIMER_NAME "sprd_timer" 12 13 #define TIMER_LOAD_LO 0x0 14 #define TIMER_LOAD_HI 0x4 15 #define TIMER_VALUE_LO 0x8 16 #define TIMER_VALUE_HI 0xc 17 18 #define TIMER_CTL 0x10 19 #define TIMER_CTL_PERIOD_MODE BIT(0) 20 #define TIMER_CTL_ENABLE BIT(1) 21 #define TIMER_CTL_64BIT_WIDTH BIT(16) 22 23 #define TIMER_INT 0x14 24 #define TIMER_INT_EN BIT(0) 25 #define TIMER_INT_RAW_STS BIT(1) 26 #define TIMER_INT_MASK_STS BIT(2) 27 #define TIMER_INT_CLR BIT(3) 28 29 #define TIMER_VALUE_SHDW_LO 0x18 30 #define TIMER_VALUE_SHDW_HI 0x1c 31 32 #define TIMER_VALUE_LO_MASK GENMASK(31, 0) 33 34 static void sprd_timer_enable(void __iomem *base, u32 flag) 35 { 36 u32 val = readl_relaxed(base + TIMER_CTL); 37 38 val |= TIMER_CTL_ENABLE; 39 if (flag & TIMER_CTL_64BIT_WIDTH) 40 val |= TIMER_CTL_64BIT_WIDTH; 41 else 42 val &= ~TIMER_CTL_64BIT_WIDTH; 43 44 if (flag & TIMER_CTL_PERIOD_MODE) 45 val |= TIMER_CTL_PERIOD_MODE; 46 else 47 val &= ~TIMER_CTL_PERIOD_MODE; 48 49 writel_relaxed(val, base + TIMER_CTL); 50 } 51 52 static void sprd_timer_disable(void __iomem *base) 53 { 54 u32 val = readl_relaxed(base + TIMER_CTL); 55 56 val &= ~TIMER_CTL_ENABLE; 57 writel_relaxed(val, base + TIMER_CTL); 58 } 59 60 static void sprd_timer_update_counter(void __iomem *base, unsigned long cycles) 61 { 62 writel_relaxed(cycles & TIMER_VALUE_LO_MASK, base + TIMER_LOAD_LO); 63 writel_relaxed(0, base + TIMER_LOAD_HI); 64 } 65 66 static void sprd_timer_enable_interrupt(void __iomem *base) 67 { 68 writel_relaxed(TIMER_INT_EN, base + TIMER_INT); 69 } 70 71 static void sprd_timer_clear_interrupt(void __iomem *base) 72 { 73 u32 val = readl_relaxed(base + TIMER_INT); 74 75 val |= TIMER_INT_CLR; 76 writel_relaxed(val, base + TIMER_INT); 77 } 78 79 static int sprd_timer_set_next_event(unsigned long cycles, 80 struct clock_event_device *ce) 81 { 82 struct timer_of *to = to_timer_of(ce); 83 84 sprd_timer_disable(timer_of_base(to)); 85 sprd_timer_update_counter(timer_of_base(to), cycles); 86 sprd_timer_enable(timer_of_base(to), 0); 87 88 return 0; 89 } 90 91 static int sprd_timer_set_periodic(struct clock_event_device *ce) 92 { 93 struct timer_of *to = to_timer_of(ce); 94 95 sprd_timer_disable(timer_of_base(to)); 96 sprd_timer_update_counter(timer_of_base(to), timer_of_period(to)); 97 sprd_timer_enable(timer_of_base(to), TIMER_CTL_PERIOD_MODE); 98 99 return 0; 100 } 101 102 static int sprd_timer_shutdown(struct clock_event_device *ce) 103 { 104 struct timer_of *to = to_timer_of(ce); 105 106 sprd_timer_disable(timer_of_base(to)); 107 return 0; 108 } 109 110 static irqreturn_t sprd_timer_interrupt(int irq, void *dev_id) 111 { 112 struct clock_event_device *ce = (struct clock_event_device *)dev_id; 113 struct timer_of *to = to_timer_of(ce); 114 115 sprd_timer_clear_interrupt(timer_of_base(to)); 116 117 if (clockevent_state_oneshot(ce)) 118 sprd_timer_disable(timer_of_base(to)); 119 120 ce->event_handler(ce); 121 return IRQ_HANDLED; 122 } 123 124 static struct timer_of to = { 125 .flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK, 126 127 .clkevt = { 128 .name = TIMER_NAME, 129 .rating = 300, 130 .features = CLOCK_EVT_FEAT_DYNIRQ | CLOCK_EVT_FEAT_PERIODIC | 131 CLOCK_EVT_FEAT_ONESHOT, 132 .set_state_shutdown = sprd_timer_shutdown, 133 .set_state_periodic = sprd_timer_set_periodic, 134 .set_next_event = sprd_timer_set_next_event, 135 .cpumask = cpu_possible_mask, 136 }, 137 138 .of_irq = { 139 .handler = sprd_timer_interrupt, 140 .flags = IRQF_TIMER | IRQF_IRQPOLL, 141 }, 142 }; 143 144 static int __init sprd_timer_init(struct device_node *np) 145 { 146 int ret; 147 148 ret = timer_of_init(np, &to); 149 if (ret) 150 return ret; 151 152 sprd_timer_enable_interrupt(timer_of_base(&to)); 153 clockevents_config_and_register(&to.clkevt, timer_of_rate(&to), 154 1, UINT_MAX); 155 156 return 0; 157 } 158 159 static struct timer_of suspend_to = { 160 .flags = TIMER_OF_BASE | TIMER_OF_CLOCK, 161 }; 162 163 static u64 sprd_suspend_timer_read(struct clocksource *cs) 164 { 165 return ~(u64)readl_relaxed(timer_of_base(&suspend_to) + 166 TIMER_VALUE_SHDW_LO) & cs->mask; 167 } 168 169 static int sprd_suspend_timer_enable(struct clocksource *cs) 170 { 171 sprd_timer_update_counter(timer_of_base(&suspend_to), 172 TIMER_VALUE_LO_MASK); 173 sprd_timer_enable(timer_of_base(&suspend_to), TIMER_CTL_PERIOD_MODE); 174 175 return 0; 176 } 177 178 static void sprd_suspend_timer_disable(struct clocksource *cs) 179 { 180 sprd_timer_disable(timer_of_base(&suspend_to)); 181 } 182 183 static struct clocksource suspend_clocksource = { 184 .name = "sprd_suspend_timer", 185 .rating = 200, 186 .read = sprd_suspend_timer_read, 187 .enable = sprd_suspend_timer_enable, 188 .disable = sprd_suspend_timer_disable, 189 .mask = CLOCKSOURCE_MASK(32), 190 .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP, 191 }; 192 193 static int __init sprd_suspend_timer_init(struct device_node *np) 194 { 195 int ret; 196 197 ret = timer_of_init(np, &suspend_to); 198 if (ret) 199 return ret; 200 201 clocksource_register_hz(&suspend_clocksource, 202 timer_of_rate(&suspend_to)); 203 204 return 0; 205 } 206 207 TIMER_OF_DECLARE(sc9860_timer, "sprd,sc9860-timer", sprd_timer_init); 208 TIMER_OF_DECLARE(sc9860_persistent_timer, "sprd,sc9860-suspend-timer", 209 sprd_suspend_timer_init); 210