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

Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull clocksource updates from Ingo Molnar:
"The main change in this tree is the addition of various new SoC
clocksource/clockevents drivers: Conexant Digicolor SoCs, rockchip
rk3288 board, asm9260 for MIPS and versatile AB/PB boards"

* 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
dts: versatile: Add sysregs node
clocksource: versatile: Adapt for Versatile AB and PB boards
dt/bindings: Add binding for Versatile system registers
clocksource: Driver for Conexant Digicolor SoC timer
clocksource: devicetree: Document Conexant Digicolor timer binding
clockevents: rockchip: Add rockchip timer for rk3288
ARM: clocksource: Add asm9260_timer driver
clocksource: marco: Rename marco to atlas7
clocksource: sirf: Remove unused variable

+683 -11
+10
Documentation/devicetree/bindings/arm/versatile-sysreg.txt
··· 1 + ARM Versatile system registers 2 + -------------------------------------- 3 + 4 + This is a system control registers block, providing multiple low level 5 + platform functions like board detection and identification, software 6 + interrupt generation, MMC and NOR Flash control etc. 7 + 8 + Required node properties: 9 + - compatible value : = "arm,versatile-sysreg", "syscon" 10 + - reg : physical base address and the size of the registers window
+18
Documentation/devicetree/bindings/timer/digicolor-timer.txt
··· 1 + Conexant Digicolor SoCs Timer Controller 2 + 3 + Required properties: 4 + 5 + - compatible : should be "cnxt,cx92755-timer" 6 + - reg : Specifies base physical address and size of the "Agent Communication" 7 + timer registers 8 + - interrupts : Contains 8 interrupts, one for each timer 9 + - clocks: phandle to the main clock 10 + 11 + Example: 12 + 13 + timer@f0000fc0 { 14 + compatible = "cnxt,cx92755-timer"; 15 + reg = <0xf0000fc0 0x40>; 16 + interrupts = <19>, <31>, <34>, <35>, <52>, <53>, <54>, <55>; 17 + clocks = <&main_clk>; 18 + };
+18
Documentation/devicetree/bindings/timer/rockchip,rk3288-timer.txt
··· 1 + Rockchip rk3288 timer 2 + 3 + Required properties: 4 + - compatible: shall be "rockchip,rk3288-timer" 5 + - reg: base address of the timer register starting with TIMERS CONTROL register 6 + - interrupts: should contain the interrupts for Timer0 7 + - clocks : must contain an entry for each entry in clock-names 8 + - clock-names : must include the following entries: 9 + "timer", "pclk" 10 + 11 + Example: 12 + timer: timer@ff810000 { 13 + compatible = "rockchip,rk3288-timer"; 14 + reg = <0xff810000 0x20>; 15 + interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>; 16 + clocks = <&xin24m>, <&cru PCLK_TIMER>; 17 + clock-names = "timer", "pclk"; 18 + };
+1 -1
MAINTAINERS
··· 974 974 F: arch/arm/mach-prima2/ 975 975 F: drivers/clk/sirf/ 976 976 F: drivers/clocksource/timer-prima2.c 977 - F: drivers/clocksource/timer-marco.c 977 + F: drivers/clocksource/timer-atlas7.c 978 978 N: [^a-z]sirf 979 979 980 980 ARM/EBSA110 MACHINE SUPPORT
+5
arch/arm/boot/dts/versatile-ab.dts
··· 252 252 #size-cells = <1>; 253 253 ranges = <0 0x10000000 0x10000>; 254 254 255 + sysreg@0 { 256 + compatible = "arm,versatile-sysreg", "syscon"; 257 + reg = <0x00000 0x1000>; 258 + }; 259 + 255 260 aaci@4000 { 256 261 compatible = "arm,primecell"; 257 262 reg = <0x4000 0x1000>;
+1
arch/arm/mach-rockchip/Kconfig
··· 11 11 select HAVE_ARM_SCU if SMP 12 12 select HAVE_ARM_TWD if SMP 13 13 select DW_APB_TIMER_OF 14 + select ROCKCHIP_TIMER 14 15 select ARM_GLOBAL_TIMER 15 16 select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK 16 17 help
+17
drivers/clocksource/Kconfig
··· 18 18 config CLKSRC_MMIO 19 19 bool 20 20 21 + config DIGICOLOR_TIMER 22 + bool 23 + 21 24 config DW_APB_TIMER 22 25 bool 23 26 24 27 config DW_APB_TIMER_OF 25 28 bool 26 29 select DW_APB_TIMER 30 + select CLKSRC_OF 31 + 32 + config ROCKCHIP_TIMER 33 + bool 27 34 select CLKSRC_OF 28 35 29 36 config ARMADA_370_XP_TIMER ··· 242 235 help 243 236 This enables OST0 support available on PXA and SA-11x0 244 237 platforms. 238 + 239 + config ASM9260_TIMER 240 + bool "Alphascale ASM9260 timer driver" 241 + depends on GENERIC_CLOCKEVENTS 242 + select CLKSRC_MMIO 243 + select CLKSRC_OF 244 + default y if MACH_ASM9260 245 + help 246 + This enables build of a clocksource and clockevent driver for 247 + the 32-bit System Timer hardware available on a Alphascale ASM9260. 245 248 246 249 endmenu
+4 -1
drivers/clocksource/Makefile
··· 10 10 obj-$(CONFIG_EM_TIMER_STI) += em_sti.o 11 11 obj-$(CONFIG_CLKBLD_I8253) += i8253.o 12 12 obj-$(CONFIG_CLKSRC_MMIO) += mmio.o 13 + obj-$(CONFIG_DIGICOLOR_TIMER) += timer-digicolor.o 13 14 obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o 14 15 obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_timer_of.o 16 + obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o 15 17 obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.o 16 18 obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o 17 19 obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o 18 20 obj-$(CONFIG_ORION_TIMER) += time-orion.o 19 21 obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o 20 22 obj-$(CONFIG_ARCH_CLPS711X) += clps711x-timer.o 21 - obj-$(CONFIG_ARCH_MARCO) += timer-marco.o 23 + obj-$(CONFIG_ARCH_ATLAS7) += timer-atlas7.o 22 24 obj-$(CONFIG_ARCH_MOXART) += moxart_timer.o 23 25 obj-$(CONFIG_ARCH_MXS) += mxs_timer.o 24 26 obj-$(CONFIG_CLKSRC_PXA) += pxa_timer.o ··· 50 48 obj-$(CONFIG_ARCH_INTEGRATOR_AP) += timer-integrator-ap.o 51 49 obj-$(CONFIG_CLKSRC_VERSATILE) += versatile.o 52 50 obj-$(CONFIG_CLKSRC_MIPS_GIC) += mips-gic-timer.o 51 + obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o
+220
drivers/clocksource/asm9260_timer.c
··· 1 + /* 2 + * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de> 3 + * 4 + * This program is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU General Public License 6 + * as published by the Free Software Foundation; either version 2 7 + * of the License, or (at your option) any later version. 8 + */ 9 + 10 + #include <linux/kernel.h> 11 + #include <linux/init.h> 12 + #include <linux/interrupt.h> 13 + #include <linux/sched.h> 14 + #include <linux/clk.h> 15 + #include <linux/clocksource.h> 16 + #include <linux/clockchips.h> 17 + #include <linux/io.h> 18 + #include <linux/of.h> 19 + #include <linux/of_address.h> 20 + #include <linux/of_irq.h> 21 + #include <linux/bitops.h> 22 + 23 + #define DRIVER_NAME "asm9260-timer" 24 + 25 + /* 26 + * this device provide 4 offsets for each register: 27 + * 0x0 - plain read write mode 28 + * 0x4 - set mode, OR logic. 29 + * 0x8 - clr mode, XOR logic. 30 + * 0xc - togle mode. 31 + */ 32 + #define SET_REG 4 33 + #define CLR_REG 8 34 + 35 + #define HW_IR 0x0000 /* RW. Interrupt */ 36 + #define BM_IR_CR0 BIT(4) 37 + #define BM_IR_MR3 BIT(3) 38 + #define BM_IR_MR2 BIT(2) 39 + #define BM_IR_MR1 BIT(1) 40 + #define BM_IR_MR0 BIT(0) 41 + 42 + #define HW_TCR 0x0010 /* RW. Timer controller */ 43 + /* BM_C*_RST 44 + * Timer Counter and the Prescale Counter are synchronously reset on the 45 + * next positive edge of PCLK. The counters remain reset until TCR[1] is 46 + * returned to zero. */ 47 + #define BM_C3_RST BIT(7) 48 + #define BM_C2_RST BIT(6) 49 + #define BM_C1_RST BIT(5) 50 + #define BM_C0_RST BIT(4) 51 + /* BM_C*_EN 52 + * 1 - Timer Counter and Prescale Counter are enabled for counting 53 + * 0 - counters are disabled */ 54 + #define BM_C3_EN BIT(3) 55 + #define BM_C2_EN BIT(2) 56 + #define BM_C1_EN BIT(1) 57 + #define BM_C0_EN BIT(0) 58 + 59 + #define HW_DIR 0x0020 /* RW. Direction? */ 60 + /* 00 - count up 61 + * 01 - count down 62 + * 10 - ?? 2^n/2 */ 63 + #define BM_DIR_COUNT_UP 0 64 + #define BM_DIR_COUNT_DOWN 1 65 + #define BM_DIR0_SHIFT 0 66 + #define BM_DIR1_SHIFT 4 67 + #define BM_DIR2_SHIFT 8 68 + #define BM_DIR3_SHIFT 12 69 + #define BM_DIR_DEFAULT (BM_DIR_COUNT_UP << BM_DIR0_SHIFT | \ 70 + BM_DIR_COUNT_UP << BM_DIR1_SHIFT | \ 71 + BM_DIR_COUNT_UP << BM_DIR2_SHIFT | \ 72 + BM_DIR_COUNT_UP << BM_DIR3_SHIFT) 73 + 74 + #define HW_TC0 0x0030 /* RO. Timer counter 0 */ 75 + /* HW_TC*. Timer counter owerflow (0xffff.ffff to 0x0000.0000) do not generate 76 + * interrupt. This registers can be used to detect overflow */ 77 + #define HW_TC1 0x0040 78 + #define HW_TC2 0x0050 79 + #define HW_TC3 0x0060 80 + 81 + #define HW_PR 0x0070 /* RW. prescaler */ 82 + #define BM_PR_DISABLE 0 83 + #define HW_PC 0x0080 /* RO. Prescaler counter */ 84 + #define HW_MCR 0x0090 /* RW. Match control */ 85 + /* enable interrupt on match */ 86 + #define BM_MCR_INT_EN(n) (1 << (n * 3 + 0)) 87 + /* enable TC reset on match */ 88 + #define BM_MCR_RES_EN(n) (1 << (n * 3 + 1)) 89 + /* enable stop TC on match */ 90 + #define BM_MCR_STOP_EN(n) (1 << (n * 3 + 2)) 91 + 92 + #define HW_MR0 0x00a0 /* RW. Match reg */ 93 + #define HW_MR1 0x00b0 94 + #define HW_MR2 0x00C0 95 + #define HW_MR3 0x00D0 96 + 97 + #define HW_CTCR 0x0180 /* Counter control */ 98 + #define BM_CTCR0_SHIFT 0 99 + #define BM_CTCR1_SHIFT 2 100 + #define BM_CTCR2_SHIFT 4 101 + #define BM_CTCR3_SHIFT 6 102 + #define BM_CTCR_TM 0 /* Timer mode. Every rising PCLK edge. */ 103 + #define BM_CTCR_DEFAULT (BM_CTCR_TM << BM_CTCR0_SHIFT | \ 104 + BM_CTCR_TM << BM_CTCR1_SHIFT | \ 105 + BM_CTCR_TM << BM_CTCR2_SHIFT | \ 106 + BM_CTCR_TM << BM_CTCR3_SHIFT) 107 + 108 + static struct asm9260_timer_priv { 109 + void __iomem *base; 110 + unsigned long ticks_per_jiffy; 111 + } priv; 112 + 113 + static int asm9260_timer_set_next_event(unsigned long delta, 114 + struct clock_event_device *evt) 115 + { 116 + /* configure match count for TC0 */ 117 + writel_relaxed(delta, priv.base + HW_MR0); 118 + /* enable TC0 */ 119 + writel_relaxed(BM_C0_EN, priv.base + HW_TCR + SET_REG); 120 + return 0; 121 + } 122 + 123 + static void asm9260_timer_set_mode(enum clock_event_mode mode, 124 + struct clock_event_device *evt) 125 + { 126 + /* stop timer0 */ 127 + writel_relaxed(BM_C0_EN, priv.base + HW_TCR + CLR_REG); 128 + 129 + switch (mode) { 130 + case CLOCK_EVT_MODE_PERIODIC: 131 + /* disable reset and stop on match */ 132 + writel_relaxed(BM_MCR_RES_EN(0) | BM_MCR_STOP_EN(0), 133 + priv.base + HW_MCR + CLR_REG); 134 + /* configure match count for TC0 */ 135 + writel_relaxed(priv.ticks_per_jiffy, priv.base + HW_MR0); 136 + /* enable TC0 */ 137 + writel_relaxed(BM_C0_EN, priv.base + HW_TCR + SET_REG); 138 + break; 139 + case CLOCK_EVT_MODE_ONESHOT: 140 + /* enable reset and stop on match */ 141 + writel_relaxed(BM_MCR_RES_EN(0) | BM_MCR_STOP_EN(0), 142 + priv.base + HW_MCR + SET_REG); 143 + break; 144 + default: 145 + break; 146 + } 147 + } 148 + 149 + static struct clock_event_device event_dev = { 150 + .name = DRIVER_NAME, 151 + .rating = 200, 152 + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, 153 + .set_next_event = asm9260_timer_set_next_event, 154 + .set_mode = asm9260_timer_set_mode, 155 + }; 156 + 157 + static irqreturn_t asm9260_timer_interrupt(int irq, void *dev_id) 158 + { 159 + struct clock_event_device *evt = dev_id; 160 + 161 + evt->event_handler(evt); 162 + 163 + writel_relaxed(BM_IR_MR0, priv.base + HW_IR); 164 + 165 + return IRQ_HANDLED; 166 + } 167 + 168 + /* 169 + * --------------------------------------------------------------------------- 170 + * Timer initialization 171 + * --------------------------------------------------------------------------- 172 + */ 173 + static void __init asm9260_timer_init(struct device_node *np) 174 + { 175 + int irq; 176 + struct clk *clk; 177 + int ret; 178 + unsigned long rate; 179 + 180 + priv.base = of_io_request_and_map(np, 0, np->name); 181 + if (!priv.base) 182 + panic("%s: unable to map resource", np->name); 183 + 184 + clk = of_clk_get(np, 0); 185 + 186 + ret = clk_prepare_enable(clk); 187 + if (ret) 188 + panic("Failed to enable clk!\n"); 189 + 190 + irq = irq_of_parse_and_map(np, 0); 191 + ret = request_irq(irq, asm9260_timer_interrupt, IRQF_TIMER, 192 + DRIVER_NAME, &event_dev); 193 + if (ret) 194 + panic("Failed to setup irq!\n"); 195 + 196 + /* set all timers for count-up */ 197 + writel_relaxed(BM_DIR_DEFAULT, priv.base + HW_DIR); 198 + /* disable divider */ 199 + writel_relaxed(BM_PR_DISABLE, priv.base + HW_PR); 200 + /* make sure all timers use every rising PCLK edge. */ 201 + writel_relaxed(BM_CTCR_DEFAULT, priv.base + HW_CTCR); 202 + /* enable interrupt for TC0 and clean setting for all other lines */ 203 + writel_relaxed(BM_MCR_INT_EN(0) , priv.base + HW_MCR); 204 + 205 + rate = clk_get_rate(clk); 206 + clocksource_mmio_init(priv.base + HW_TC1, DRIVER_NAME, rate, 207 + 200, 32, clocksource_mmio_readl_up); 208 + 209 + /* Seems like we can't use counter without match register even if 210 + * actions for MR are disabled. So, set MR to max value. */ 211 + writel_relaxed(0xffffffff, priv.base + HW_MR1); 212 + /* enable TC1 */ 213 + writel_relaxed(BM_C1_EN, priv.base + HW_TCR + SET_REG); 214 + 215 + priv.ticks_per_jiffy = DIV_ROUND_CLOSEST(rate, HZ); 216 + event_dev.cpumask = cpumask_of(0); 217 + clockevents_config_and_register(&event_dev, rate, 0x2c00, 0xfffffffe); 218 + } 219 + CLOCKSOURCE_OF_DECLARE(asm9260_timer, "alphascale,asm9260-timer", 220 + asm9260_timer_init);
+180
drivers/clocksource/rockchip_timer.c
··· 1 + /* 2 + * Rockchip timer support 3 + * 4 + * Copyright (C) Daniel Lezcano <daniel.lezcano@linaro.org> 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + */ 10 + #include <linux/clk.h> 11 + #include <linux/clockchips.h> 12 + #include <linux/init.h> 13 + #include <linux/interrupt.h> 14 + #include <linux/of.h> 15 + #include <linux/of_address.h> 16 + #include <linux/of_irq.h> 17 + 18 + #define TIMER_NAME "rk_timer" 19 + 20 + #define TIMER_LOAD_COUNT0 0x00 21 + #define TIMER_LOAD_COUNT1 0x04 22 + #define TIMER_CONTROL_REG 0x10 23 + #define TIMER_INT_STATUS 0x18 24 + 25 + #define TIMER_DISABLE 0x0 26 + #define TIMER_ENABLE 0x1 27 + #define TIMER_MODE_FREE_RUNNING (0 << 1) 28 + #define TIMER_MODE_USER_DEFINED_COUNT (1 << 1) 29 + #define TIMER_INT_UNMASK (1 << 2) 30 + 31 + struct bc_timer { 32 + struct clock_event_device ce; 33 + void __iomem *base; 34 + u32 freq; 35 + }; 36 + 37 + static struct bc_timer bc_timer; 38 + 39 + static inline struct bc_timer *rk_timer(struct clock_event_device *ce) 40 + { 41 + return container_of(ce, struct bc_timer, ce); 42 + } 43 + 44 + static inline void __iomem *rk_base(struct clock_event_device *ce) 45 + { 46 + return rk_timer(ce)->base; 47 + } 48 + 49 + static inline void rk_timer_disable(struct clock_event_device *ce) 50 + { 51 + writel_relaxed(TIMER_DISABLE, rk_base(ce) + TIMER_CONTROL_REG); 52 + dsb(); 53 + } 54 + 55 + static inline void rk_timer_enable(struct clock_event_device *ce, u32 flags) 56 + { 57 + writel_relaxed(TIMER_ENABLE | TIMER_INT_UNMASK | flags, 58 + rk_base(ce) + TIMER_CONTROL_REG); 59 + dsb(); 60 + } 61 + 62 + static void rk_timer_update_counter(unsigned long cycles, 63 + struct clock_event_device *ce) 64 + { 65 + writel_relaxed(cycles, rk_base(ce) + TIMER_LOAD_COUNT0); 66 + writel_relaxed(0, rk_base(ce) + TIMER_LOAD_COUNT1); 67 + dsb(); 68 + } 69 + 70 + static void rk_timer_interrupt_clear(struct clock_event_device *ce) 71 + { 72 + writel_relaxed(1, rk_base(ce) + TIMER_INT_STATUS); 73 + dsb(); 74 + } 75 + 76 + static inline int rk_timer_set_next_event(unsigned long cycles, 77 + struct clock_event_device *ce) 78 + { 79 + rk_timer_disable(ce); 80 + rk_timer_update_counter(cycles, ce); 81 + rk_timer_enable(ce, TIMER_MODE_USER_DEFINED_COUNT); 82 + return 0; 83 + } 84 + 85 + static inline void rk_timer_set_mode(enum clock_event_mode mode, 86 + struct clock_event_device *ce) 87 + { 88 + switch (mode) { 89 + case CLOCK_EVT_MODE_PERIODIC: 90 + rk_timer_disable(ce); 91 + rk_timer_update_counter(rk_timer(ce)->freq / HZ - 1, ce); 92 + rk_timer_enable(ce, TIMER_MODE_FREE_RUNNING); 93 + break; 94 + case CLOCK_EVT_MODE_ONESHOT: 95 + case CLOCK_EVT_MODE_RESUME: 96 + break; 97 + case CLOCK_EVT_MODE_UNUSED: 98 + case CLOCK_EVT_MODE_SHUTDOWN: 99 + rk_timer_disable(ce); 100 + break; 101 + } 102 + } 103 + 104 + static irqreturn_t rk_timer_interrupt(int irq, void *dev_id) 105 + { 106 + struct clock_event_device *ce = dev_id; 107 + 108 + rk_timer_interrupt_clear(ce); 109 + 110 + if (ce->mode == CLOCK_EVT_MODE_ONESHOT) 111 + rk_timer_disable(ce); 112 + 113 + ce->event_handler(ce); 114 + 115 + return IRQ_HANDLED; 116 + } 117 + 118 + static void __init rk_timer_init(struct device_node *np) 119 + { 120 + struct clock_event_device *ce = &bc_timer.ce; 121 + struct clk *timer_clk; 122 + struct clk *pclk; 123 + int ret, irq; 124 + 125 + bc_timer.base = of_iomap(np, 0); 126 + if (!bc_timer.base) { 127 + pr_err("Failed to get base address for '%s'\n", TIMER_NAME); 128 + return; 129 + } 130 + 131 + pclk = of_clk_get_by_name(np, "pclk"); 132 + if (IS_ERR(pclk)) { 133 + pr_err("Failed to get pclk for '%s'\n", TIMER_NAME); 134 + return; 135 + } 136 + 137 + if (clk_prepare_enable(pclk)) { 138 + pr_err("Failed to enable pclk for '%s'\n", TIMER_NAME); 139 + return; 140 + } 141 + 142 + timer_clk = of_clk_get_by_name(np, "timer"); 143 + if (IS_ERR(timer_clk)) { 144 + pr_err("Failed to get timer clock for '%s'\n", TIMER_NAME); 145 + return; 146 + } 147 + 148 + if (clk_prepare_enable(timer_clk)) { 149 + pr_err("Failed to enable timer clock\n"); 150 + return; 151 + } 152 + 153 + bc_timer.freq = clk_get_rate(timer_clk); 154 + 155 + irq = irq_of_parse_and_map(np, 0); 156 + if (irq == NO_IRQ) { 157 + pr_err("Failed to map interrupts for '%s'\n", TIMER_NAME); 158 + return; 159 + } 160 + 161 + ce->name = TIMER_NAME; 162 + ce->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; 163 + ce->set_next_event = rk_timer_set_next_event; 164 + ce->set_mode = rk_timer_set_mode; 165 + ce->irq = irq; 166 + ce->cpumask = cpumask_of(0); 167 + ce->rating = 250; 168 + 169 + rk_timer_interrupt_clear(ce); 170 + rk_timer_disable(ce); 171 + 172 + ret = request_irq(irq, rk_timer_interrupt, IRQF_TIMER, TIMER_NAME, ce); 173 + if (ret) { 174 + pr_err("Failed to initialize '%s': %d\n", TIMER_NAME, ret); 175 + return; 176 + } 177 + 178 + clockevents_config_and_register(ce, bc_timer.freq, 1, UINT_MAX); 179 + } 180 + CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,rk3288-timer", rk_timer_init);
+199
drivers/clocksource/timer-digicolor.c
··· 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/of.h> 36 + #include <linux/of_address.h> 37 + #include <linux/of_irq.h> 38 + 39 + enum { 40 + TIMER_A, 41 + TIMER_B, 42 + TIMER_C, 43 + TIMER_D, 44 + TIMER_E, 45 + TIMER_F, 46 + TIMER_G, 47 + TIMER_H, 48 + }; 49 + 50 + #define CONTROL(t) ((t)*8) 51 + #define COUNT(t) ((t)*8 + 4) 52 + 53 + #define CONTROL_DISABLE 0 54 + #define CONTROL_ENABLE BIT(0) 55 + #define CONTROL_MODE(m) ((m) << 4) 56 + #define CONTROL_MODE_ONESHOT CONTROL_MODE(1) 57 + #define CONTROL_MODE_PERIODIC CONTROL_MODE(2) 58 + 59 + struct digicolor_timer { 60 + struct clock_event_device ce; 61 + void __iomem *base; 62 + u32 ticks_per_jiffy; 63 + int timer_id; /* one of TIMER_* */ 64 + }; 65 + 66 + struct digicolor_timer *dc_timer(struct clock_event_device *ce) 67 + { 68 + return container_of(ce, struct digicolor_timer, ce); 69 + } 70 + 71 + static inline void dc_timer_disable(struct clock_event_device *ce) 72 + { 73 + struct digicolor_timer *dt = dc_timer(ce); 74 + writeb(CONTROL_DISABLE, dt->base + CONTROL(dt->timer_id)); 75 + } 76 + 77 + static inline void dc_timer_enable(struct clock_event_device *ce, u32 mode) 78 + { 79 + struct digicolor_timer *dt = dc_timer(ce); 80 + writeb(CONTROL_ENABLE | mode, dt->base + CONTROL(dt->timer_id)); 81 + } 82 + 83 + static inline void dc_timer_set_count(struct clock_event_device *ce, 84 + unsigned long count) 85 + { 86 + struct digicolor_timer *dt = dc_timer(ce); 87 + writel(count, dt->base + COUNT(dt->timer_id)); 88 + } 89 + 90 + static void digicolor_clkevt_mode(enum clock_event_mode mode, 91 + struct clock_event_device *ce) 92 + { 93 + struct digicolor_timer *dt = dc_timer(ce); 94 + 95 + switch (mode) { 96 + case CLOCK_EVT_MODE_PERIODIC: 97 + dc_timer_disable(ce); 98 + dc_timer_set_count(ce, dt->ticks_per_jiffy); 99 + dc_timer_enable(ce, CONTROL_MODE_PERIODIC); 100 + break; 101 + case CLOCK_EVT_MODE_ONESHOT: 102 + dc_timer_disable(ce); 103 + dc_timer_enable(ce, CONTROL_MODE_ONESHOT); 104 + break; 105 + case CLOCK_EVT_MODE_UNUSED: 106 + case CLOCK_EVT_MODE_SHUTDOWN: 107 + default: 108 + dc_timer_disable(ce); 109 + break; 110 + } 111 + } 112 + 113 + static int digicolor_clkevt_next_event(unsigned long evt, 114 + struct clock_event_device *ce) 115 + { 116 + dc_timer_disable(ce); 117 + dc_timer_set_count(ce, evt); 118 + dc_timer_enable(ce, CONTROL_MODE_ONESHOT); 119 + 120 + return 0; 121 + } 122 + 123 + static struct digicolor_timer dc_timer_dev = { 124 + .ce = { 125 + .name = "digicolor_tick", 126 + .rating = 340, 127 + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, 128 + .set_mode = digicolor_clkevt_mode, 129 + .set_next_event = digicolor_clkevt_next_event, 130 + }, 131 + .timer_id = TIMER_C, 132 + }; 133 + 134 + static irqreturn_t digicolor_timer_interrupt(int irq, void *dev_id) 135 + { 136 + struct clock_event_device *evt = dev_id; 137 + 138 + evt->event_handler(evt); 139 + 140 + return IRQ_HANDLED; 141 + } 142 + 143 + static u64 digicolor_timer_sched_read(void) 144 + { 145 + return ~readl(dc_timer_dev.base + COUNT(TIMER_B)); 146 + } 147 + 148 + static void __init digicolor_timer_init(struct device_node *node) 149 + { 150 + unsigned long rate; 151 + struct clk *clk; 152 + int ret, irq; 153 + 154 + /* 155 + * timer registers are shared with the watchdog timer; 156 + * don't map exclusively 157 + */ 158 + dc_timer_dev.base = of_iomap(node, 0); 159 + if (!dc_timer_dev.base) { 160 + pr_err("Can't map registers"); 161 + return; 162 + } 163 + 164 + irq = irq_of_parse_and_map(node, dc_timer_dev.timer_id); 165 + if (irq <= 0) { 166 + pr_err("Can't parse IRQ"); 167 + return; 168 + } 169 + 170 + clk = of_clk_get(node, 0); 171 + if (IS_ERR(clk)) { 172 + pr_err("Can't get timer clock"); 173 + return; 174 + } 175 + clk_prepare_enable(clk); 176 + rate = clk_get_rate(clk); 177 + dc_timer_dev.ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); 178 + 179 + writeb(CONTROL_DISABLE, dc_timer_dev.base + CONTROL(TIMER_B)); 180 + writel(UINT_MAX, dc_timer_dev.base + COUNT(TIMER_B)); 181 + writeb(CONTROL_ENABLE, dc_timer_dev.base + CONTROL(TIMER_B)); 182 + 183 + sched_clock_register(digicolor_timer_sched_read, 32, rate); 184 + clocksource_mmio_init(dc_timer_dev.base + COUNT(TIMER_B), node->name, 185 + rate, 340, 32, clocksource_mmio_readl_down); 186 + 187 + ret = request_irq(irq, digicolor_timer_interrupt, 188 + IRQF_TIMER | IRQF_IRQPOLL, "digicolor_timerC", 189 + &dc_timer_dev.ce); 190 + if (ret) 191 + pr_warn("request of timer irq %d failed (%d)\n", irq, ret); 192 + 193 + dc_timer_dev.ce.cpumask = cpu_possible_mask; 194 + dc_timer_dev.ce.irq = irq; 195 + 196 + clockevents_config_and_register(&dc_timer_dev.ce, rate, 0, 0xffffffff); 197 + } 198 + CLOCKSOURCE_OF_DECLARE(conexant_digicolor, "cnxt,cx92755-timer", 199 + digicolor_timer_init);
+7 -8
drivers/clocksource/timer-marco.c drivers/clocksource/timer-atlas7.c
··· 38 38 39 39 #define SIRFSOC_TIMER_REG_CNT 6 40 40 41 - static unsigned long marco_timer_rate; 41 + static unsigned long atlas7_timer_rate; 42 42 43 43 static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = { 44 44 SIRFSOC_TIMER_WATCHDOG_EN, ··· 195 195 ce->rating = 200; 196 196 ce->set_mode = sirfsoc_timer_set_mode; 197 197 ce->set_next_event = sirfsoc_timer_set_next_event; 198 - clockevents_calc_mult_shift(ce, marco_timer_rate, 60); 198 + clockevents_calc_mult_shift(ce, atlas7_timer_rate, 60); 199 199 ce->max_delta_ns = clockevent_delta2ns(-2, ce); 200 200 ce->min_delta_ns = clockevent_delta2ns(2, ce); 201 201 ce->cpumask = cpumask_of(cpu); ··· 255 255 } 256 256 257 257 /* initialize the kernel jiffy timer source */ 258 - static void __init sirfsoc_marco_timer_init(struct device_node *np) 258 + static void __init sirfsoc_atlas7_timer_init(struct device_node *np) 259 259 { 260 - u32 timer_div; 261 260 struct clk *clk; 262 261 263 262 clk = of_clk_get(np, 0); ··· 264 265 265 266 BUG_ON(clk_prepare_enable(clk)); 266 267 267 - marco_timer_rate = clk_get_rate(clk); 268 + atlas7_timer_rate = clk_get_rate(clk); 268 269 269 270 /* timer dividers: 0, not divided */ 270 271 writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL); ··· 282 283 /* Clear all interrupts */ 283 284 writel_relaxed(0xFFFF, sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS); 284 285 285 - BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, marco_timer_rate)); 286 + BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, atlas7_timer_rate)); 286 287 287 288 sirfsoc_clockevent_init(); 288 289 } ··· 301 302 if (!sirfsoc_timer1_irq.irq) 302 303 panic("No irq passed for timer1 via DT\n"); 303 304 304 - sirfsoc_marco_timer_init(np); 305 + sirfsoc_atlas7_timer_init(np); 305 306 } 306 - CLOCKSOURCE_OF_DECLARE(sirfsoc_marco_timer, "sirf,marco-tick", sirfsoc_of_timer_init ); 307 + CLOCKSOURCE_OF_DECLARE(sirfsoc_atlas7_timer, "sirf,atlas7-tick", sirfsoc_of_timer_init);
+3 -1
drivers/clocksource/versatile.c
··· 36 36 37 37 sched_clock_register(versatile_sys_24mhz_read, 32, 24000000); 38 38 } 39 - CLOCKSOURCE_OF_DECLARE(versatile, "arm,vexpress-sysreg", 39 + CLOCKSOURCE_OF_DECLARE(vexpress, "arm,vexpress-sysreg", 40 + versatile_sched_clock_init); 41 + CLOCKSOURCE_OF_DECLARE(versatile, "arm,versatile-sysreg", 40 42 versatile_sched_clock_init);