Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'timers-v5.10' of https://git.linaro.org/people/daniel.lezcano/linux into timers/core

Pull clocksource/event updates from Daniel Lezcano:

- Add DT binding documentation to support the r8a7742 and r8a774e1
platforms (Lad Prabhakar)

- Add sp804 variant support for the Hisilicon platforms (Kefeng Wang)

+185 -94
+4
Documentation/devicetree/bindings/timer/renesas,cmt.yaml
··· 39 39 - items: 40 40 - enum: 41 41 - renesas,r8a73a4-cmt0 # 32-bit CMT0 on R-Mobile APE6 42 + - renesas,r8a7742-cmt0 # 32-bit CMT0 on RZ/G1H 42 43 - renesas,r8a7743-cmt0 # 32-bit CMT0 on RZ/G1M 43 44 - renesas,r8a7744-cmt0 # 32-bit CMT0 on RZ/G1N 44 45 - renesas,r8a7745-cmt0 # 32-bit CMT0 on RZ/G1E ··· 54 53 - items: 55 54 - enum: 56 55 - renesas,r8a73a4-cmt1 # 48-bit CMT1 on R-Mobile APE6 56 + - renesas,r8a7742-cmt1 # 48-bit CMT1 on RZ/G1H 57 57 - renesas,r8a7743-cmt1 # 48-bit CMT1 on RZ/G1M 58 58 - renesas,r8a7744-cmt1 # 48-bit CMT1 on RZ/G1N 59 59 - renesas,r8a7745-cmt1 # 48-bit CMT1 on RZ/G1E ··· 71 69 - renesas,r8a774a1-cmt0 # 32-bit CMT0 on RZ/G2M 72 70 - renesas,r8a774b1-cmt0 # 32-bit CMT0 on RZ/G2N 73 71 - renesas,r8a774c0-cmt0 # 32-bit CMT0 on RZ/G2E 72 + - renesas,r8a774e1-cmt0 # 32-bit CMT0 on RZ/G2H 74 73 - renesas,r8a7795-cmt0 # 32-bit CMT0 on R-Car H3 75 74 - renesas,r8a7796-cmt0 # 32-bit CMT0 on R-Car M3-W 76 75 - renesas,r8a77965-cmt0 # 32-bit CMT0 on R-Car M3-N ··· 86 83 - renesas,r8a774a1-cmt1 # 48-bit CMT on RZ/G2M 87 84 - renesas,r8a774b1-cmt1 # 48-bit CMT on RZ/G2N 88 85 - renesas,r8a774c0-cmt1 # 48-bit CMT on RZ/G2E 86 + - renesas,r8a774e1-cmt1 # 48-bit CMT on RZ/G2H 89 87 - renesas,r8a7795-cmt1 # 48-bit CMT on R-Car H3 90 88 - renesas,r8a7796-cmt1 # 48-bit CMT on R-Car M3-W 91 89 - renesas,r8a77965-cmt1 # 48-bit CMT on R-Car M3-N
+32
drivers/clocksource/timer-sp.h
··· 10 10 * 11 11 * Every SP804 contains two identical timers. 12 12 */ 13 + #define NR_TIMERS 2 13 14 #define TIMER_1_BASE 0x00 14 15 #define TIMER_2_BASE 0x20 15 16 ··· 30 29 #define TIMER_RIS 0x10 /* CVR ro */ 31 30 #define TIMER_MIS 0x14 /* CVR ro */ 32 31 #define TIMER_BGLOAD 0x18 /* CVR rw */ 32 + 33 + struct sp804_timer { 34 + int load; 35 + int load_h; 36 + int value; 37 + int value_h; 38 + int ctrl; 39 + int intclr; 40 + int ris; 41 + int mis; 42 + int bgload; 43 + int bgload_h; 44 + int timer_base[NR_TIMERS]; 45 + int width; 46 + }; 47 + 48 + struct sp804_clkevt { 49 + void __iomem *base; 50 + void __iomem *load; 51 + void __iomem *load_h; 52 + void __iomem *value; 53 + void __iomem *value_h; 54 + void __iomem *ctrl; 55 + void __iomem *intclr; 56 + void __iomem *ris; 57 + void __iomem *mis; 58 + void __iomem *bgload; 59 + void __iomem *bgload_h; 60 + unsigned long reload; 61 + int width; 62 + };
+149 -65
drivers/clocksource/timer-sp804.c
··· 18 18 #include <linux/of_irq.h> 19 19 #include <linux/sched_clock.h> 20 20 21 - #include <clocksource/timer-sp804.h> 22 - 23 21 #include "timer-sp.h" 24 22 25 - static long __init sp804_get_clock_rate(struct clk *clk) 23 + /* Hisilicon 64-bit timer(a variant of ARM SP804) */ 24 + #define HISI_TIMER_1_BASE 0x00 25 + #define HISI_TIMER_2_BASE 0x40 26 + #define HISI_TIMER_LOAD 0x00 27 + #define HISI_TIMER_LOAD_H 0x04 28 + #define HISI_TIMER_VALUE 0x08 29 + #define HISI_TIMER_VALUE_H 0x0c 30 + #define HISI_TIMER_CTRL 0x10 31 + #define HISI_TIMER_INTCLR 0x14 32 + #define HISI_TIMER_RIS 0x18 33 + #define HISI_TIMER_MIS 0x1c 34 + #define HISI_TIMER_BGLOAD 0x20 35 + #define HISI_TIMER_BGLOAD_H 0x24 36 + 37 + 38 + struct sp804_timer __initdata arm_sp804_timer = { 39 + .load = TIMER_LOAD, 40 + .value = TIMER_VALUE, 41 + .ctrl = TIMER_CTRL, 42 + .intclr = TIMER_INTCLR, 43 + .timer_base = {TIMER_1_BASE, TIMER_2_BASE}, 44 + .width = 32, 45 + }; 46 + 47 + struct sp804_timer __initdata hisi_sp804_timer = { 48 + .load = HISI_TIMER_LOAD, 49 + .load_h = HISI_TIMER_LOAD_H, 50 + .value = HISI_TIMER_VALUE, 51 + .value_h = HISI_TIMER_VALUE_H, 52 + .ctrl = HISI_TIMER_CTRL, 53 + .intclr = HISI_TIMER_INTCLR, 54 + .timer_base = {HISI_TIMER_1_BASE, HISI_TIMER_2_BASE}, 55 + .width = 64, 56 + }; 57 + 58 + static struct sp804_clkevt sp804_clkevt[NR_TIMERS]; 59 + 60 + static long __init sp804_get_clock_rate(struct clk *clk, const char *name) 26 61 { 27 62 long rate; 28 63 int err; 64 + 65 + if (!clk) 66 + clk = clk_get_sys("sp804", name); 67 + if (IS_ERR(clk)) { 68 + pr_err("sp804: %s clock not found: %ld\n", name, PTR_ERR(clk)); 69 + return PTR_ERR(clk); 70 + } 29 71 30 72 err = clk_prepare(clk); 31 73 if (err) { ··· 95 53 return rate; 96 54 } 97 55 98 - static void __iomem *sched_clock_base; 56 + static struct sp804_clkevt * __init sp804_clkevt_get(void __iomem *base) 57 + { 58 + int i; 59 + 60 + for (i = 0; i < NR_TIMERS; i++) { 61 + if (sp804_clkevt[i].base == base) 62 + return &sp804_clkevt[i]; 63 + } 64 + 65 + /* It's impossible to reach here */ 66 + WARN_ON(1); 67 + 68 + return NULL; 69 + } 70 + 71 + static struct sp804_clkevt *sched_clkevt; 99 72 100 73 static u64 notrace sp804_read(void) 101 74 { 102 - return ~readl_relaxed(sched_clock_base + TIMER_VALUE); 75 + return ~readl_relaxed(sched_clkevt->value); 103 76 } 104 77 105 - void __init sp804_timer_disable(void __iomem *base) 106 - { 107 - writel(0, base + TIMER_CTRL); 108 - } 109 - 110 - int __init __sp804_clocksource_and_sched_clock_init(void __iomem *base, 111 - const char *name, 112 - struct clk *clk, 113 - int use_sched_clock) 78 + int __init sp804_clocksource_and_sched_clock_init(void __iomem *base, 79 + const char *name, 80 + struct clk *clk, 81 + int use_sched_clock) 114 82 { 115 83 long rate; 84 + struct sp804_clkevt *clkevt; 116 85 117 - if (!clk) { 118 - clk = clk_get_sys("sp804", name); 119 - if (IS_ERR(clk)) { 120 - pr_err("sp804: clock not found: %d\n", 121 - (int)PTR_ERR(clk)); 122 - return PTR_ERR(clk); 123 - } 124 - } 125 - 126 - rate = sp804_get_clock_rate(clk); 86 + rate = sp804_get_clock_rate(clk, name); 127 87 if (rate < 0) 128 88 return -EINVAL; 129 89 130 - /* setup timer 0 as free-running clocksource */ 131 - writel(0, base + TIMER_CTRL); 132 - writel(0xffffffff, base + TIMER_LOAD); 133 - writel(0xffffffff, base + TIMER_VALUE); 134 - writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, 135 - base + TIMER_CTRL); 90 + clkevt = sp804_clkevt_get(base); 136 91 137 - clocksource_mmio_init(base + TIMER_VALUE, name, 92 + writel(0, clkevt->ctrl); 93 + writel(0xffffffff, clkevt->load); 94 + writel(0xffffffff, clkevt->value); 95 + if (clkevt->width == 64) { 96 + writel(0xffffffff, clkevt->load_h); 97 + writel(0xffffffff, clkevt->value_h); 98 + } 99 + writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, 100 + clkevt->ctrl); 101 + 102 + clocksource_mmio_init(clkevt->value, name, 138 103 rate, 200, 32, clocksource_mmio_readl_down); 139 104 140 105 if (use_sched_clock) { 141 - sched_clock_base = base; 106 + sched_clkevt = clkevt; 142 107 sched_clock_register(sp804_read, 32, rate); 143 108 } 144 109 ··· 153 104 } 154 105 155 106 156 - static void __iomem *clkevt_base; 157 - static unsigned long clkevt_reload; 107 + static struct sp804_clkevt *common_clkevt; 158 108 159 109 /* 160 110 * IRQ handler for the timer ··· 163 115 struct clock_event_device *evt = dev_id; 164 116 165 117 /* clear the interrupt */ 166 - writel(1, clkevt_base + TIMER_INTCLR); 118 + writel(1, common_clkevt->intclr); 167 119 168 120 evt->event_handler(evt); 169 121 ··· 172 124 173 125 static inline void timer_shutdown(struct clock_event_device *evt) 174 126 { 175 - writel(0, clkevt_base + TIMER_CTRL); 127 + writel(0, common_clkevt->ctrl); 176 128 } 177 129 178 130 static int sp804_shutdown(struct clock_event_device *evt) ··· 187 139 TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; 188 140 189 141 timer_shutdown(evt); 190 - writel(clkevt_reload, clkevt_base + TIMER_LOAD); 191 - writel(ctrl, clkevt_base + TIMER_CTRL); 142 + writel(common_clkevt->reload, common_clkevt->load); 143 + writel(ctrl, common_clkevt->ctrl); 192 144 return 0; 193 145 } 194 146 ··· 198 150 unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE | 199 151 TIMER_CTRL_ONESHOT | TIMER_CTRL_ENABLE; 200 152 201 - writel(next, clkevt_base + TIMER_LOAD); 202 - writel(ctrl, clkevt_base + TIMER_CTRL); 153 + writel(next, common_clkevt->load); 154 + writel(ctrl, common_clkevt->ctrl); 203 155 204 156 return 0; 205 157 } ··· 216 168 .rating = 300, 217 169 }; 218 170 219 - int __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struct clk *clk, const char *name) 171 + int __init sp804_clockevents_init(void __iomem *base, unsigned int irq, 172 + struct clk *clk, const char *name) 220 173 { 221 174 struct clock_event_device *evt = &sp804_clockevent; 222 175 long rate; 223 176 224 - if (!clk) 225 - clk = clk_get_sys("sp804", name); 226 - if (IS_ERR(clk)) { 227 - pr_err("sp804: %s clock not found: %d\n", name, 228 - (int)PTR_ERR(clk)); 229 - return PTR_ERR(clk); 230 - } 231 - 232 - rate = sp804_get_clock_rate(clk); 177 + rate = sp804_get_clock_rate(clk, name); 233 178 if (rate < 0) 234 179 return -EINVAL; 235 180 236 - clkevt_base = base; 237 - clkevt_reload = DIV_ROUND_CLOSEST(rate, HZ); 181 + common_clkevt = sp804_clkevt_get(base); 182 + common_clkevt->reload = DIV_ROUND_CLOSEST(rate, HZ); 238 183 evt->name = name; 239 184 evt->irq = irq; 240 185 evt->cpumask = cpu_possible_mask; 241 186 242 - writel(0, base + TIMER_CTRL); 187 + writel(0, common_clkevt->ctrl); 243 188 244 189 if (request_irq(irq, sp804_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL, 245 190 "timer", &sp804_clockevent)) ··· 242 201 return 0; 243 202 } 244 203 245 - static int __init sp804_of_init(struct device_node *np) 204 + static void __init sp804_clkevt_init(struct sp804_timer *timer, void __iomem *base) 205 + { 206 + int i; 207 + 208 + for (i = 0; i < NR_TIMERS; i++) { 209 + void __iomem *timer_base; 210 + struct sp804_clkevt *clkevt; 211 + 212 + timer_base = base + timer->timer_base[i]; 213 + clkevt = &sp804_clkevt[i]; 214 + clkevt->base = timer_base; 215 + clkevt->load = timer_base + timer->load; 216 + clkevt->load_h = timer_base + timer->load_h; 217 + clkevt->value = timer_base + timer->value; 218 + clkevt->value_h = timer_base + timer->value_h; 219 + clkevt->ctrl = timer_base + timer->ctrl; 220 + clkevt->intclr = timer_base + timer->intclr; 221 + clkevt->width = timer->width; 222 + } 223 + } 224 + 225 + static int __init sp804_of_init(struct device_node *np, struct sp804_timer *timer) 246 226 { 247 227 static bool initialized = false; 248 228 void __iomem *base; 229 + void __iomem *timer1_base; 230 + void __iomem *timer2_base; 249 231 int irq, ret = -EINVAL; 250 232 u32 irq_num = 0; 251 233 struct clk *clk1, *clk2; ··· 278 214 if (!base) 279 215 return -ENXIO; 280 216 217 + timer1_base = base + timer->timer_base[0]; 218 + timer2_base = base + timer->timer_base[1]; 219 + 281 220 /* Ensure timers are disabled */ 282 - writel(0, base + TIMER_CTRL); 283 - writel(0, base + TIMER_2_BASE + TIMER_CTRL); 221 + writel(0, timer1_base + timer->ctrl); 222 + writel(0, timer2_base + timer->ctrl); 284 223 285 224 if (initialized || !of_device_is_available(np)) { 286 225 ret = -EINVAL; ··· 309 242 if (irq <= 0) 310 243 goto err; 311 244 245 + sp804_clkevt_init(timer, base); 246 + 312 247 of_property_read_u32(np, "arm,sp804-has-irq", &irq_num); 313 248 if (irq_num == 2) { 314 249 315 - ret = __sp804_clockevents_init(base + TIMER_2_BASE, irq, clk2, name); 250 + ret = sp804_clockevents_init(timer2_base, irq, clk2, name); 316 251 if (ret) 317 252 goto err; 318 253 319 - ret = __sp804_clocksource_and_sched_clock_init(base, name, clk1, 1); 254 + ret = sp804_clocksource_and_sched_clock_init(timer1_base, 255 + name, clk1, 1); 320 256 if (ret) 321 257 goto err; 322 258 } else { 323 259 324 - ret = __sp804_clockevents_init(base, irq, clk1 , name); 260 + ret = sp804_clockevents_init(timer1_base, irq, clk1, name); 325 261 if (ret) 326 262 goto err; 327 263 328 - ret =__sp804_clocksource_and_sched_clock_init(base + TIMER_2_BASE, 329 - name, clk2, 1); 264 + ret = sp804_clocksource_and_sched_clock_init(timer2_base, 265 + name, clk2, 1); 330 266 if (ret) 331 267 goto err; 332 268 } ··· 340 270 iounmap(base); 341 271 return ret; 342 272 } 343 - TIMER_OF_DECLARE(sp804, "arm,sp804", sp804_of_init); 273 + 274 + static int __init arm_sp804_of_init(struct device_node *np) 275 + { 276 + return sp804_of_init(np, &arm_sp804_timer); 277 + } 278 + TIMER_OF_DECLARE(sp804, "arm,sp804", arm_sp804_of_init); 279 + 280 + static int __init hisi_sp804_of_init(struct device_node *np) 281 + { 282 + return sp804_of_init(np, &hisi_sp804_timer); 283 + } 284 + TIMER_OF_DECLARE(hisi_sp804, "hisilicon,sp804", hisi_sp804_of_init); 344 285 345 286 static int __init integrator_cp_of_init(struct device_node *np) 346 287 { ··· 374 293 } 375 294 376 295 /* Ensure timer is disabled */ 377 - writel(0, base + TIMER_CTRL); 296 + writel(0, base + arm_sp804_timer.ctrl); 378 297 379 298 if (init_count == 2 || !of_device_is_available(np)) 380 299 goto err; 381 300 301 + sp804_clkevt_init(&arm_sp804_timer, base); 302 + 382 303 if (!init_count) { 383 - ret = __sp804_clocksource_and_sched_clock_init(base, name, clk, 0); 304 + ret = sp804_clocksource_and_sched_clock_init(base, 305 + name, clk, 0); 384 306 if (ret) 385 307 goto err; 386 308 } else { ··· 391 307 if (irq <= 0) 392 308 goto err; 393 309 394 - ret = __sp804_clockevents_init(base, irq, clk, name); 310 + ret = sp804_clockevents_init(base, irq, clk, name); 395 311 if (ret) 396 312 goto err; 397 313 }
-29
include/clocksource/timer-sp804.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef __CLKSOURCE_TIMER_SP804_H 3 - #define __CLKSOURCE_TIMER_SP804_H 4 - 5 - struct clk; 6 - 7 - int __sp804_clocksource_and_sched_clock_init(void __iomem *, 8 - const char *, struct clk *, int); 9 - int __sp804_clockevents_init(void __iomem *, unsigned int, 10 - struct clk *, const char *); 11 - void sp804_timer_disable(void __iomem *); 12 - 13 - static inline void sp804_clocksource_init(void __iomem *base, const char *name) 14 - { 15 - __sp804_clocksource_and_sched_clock_init(base, name, NULL, 0); 16 - } 17 - 18 - static inline void sp804_clocksource_and_sched_clock_init(void __iomem *base, 19 - const char *name) 20 - { 21 - __sp804_clocksource_and_sched_clock_init(base, name, NULL, 1); 22 - } 23 - 24 - static inline void sp804_clockevents_init(void __iomem *base, unsigned int irq, const char *name) 25 - { 26 - __sp804_clockevents_init(base, irq, NULL, name); 27 - 28 - } 29 - #endif