Re: [PATCH 2/2] clocksource: sprd: Add timer driver for Spreadtrum SC9860 platform
On 25 November 2017 at 13:00, kbuild test robotwrote: > Hi Baolin, > > Thank you for the patch! Perhaps something to improve: > > [auto build test WARNING on tip/timers/core] > [also build test WARNING on v4.14 next-20171124] > [if your patch is applied to the wrong git tree, please drop us a note to > help improve the system] > > url: > https://github.com/0day-ci/linux/commits/Baolin-Wang/dt-bindings-clocksource-Add-Spreadtrum-SC9860-timer/20171125-090749 > config: arm-allmodconfig (attached as .config) > compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0 > reproduce: > wget > https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O > ~/bin/make.cross > chmod +x ~/bin/make.cross > # save the attached .config to linux build tree > make.cross ARCH=arm > > All warnings (new ones prefixed by >>): > >In file included from include/linux/swab.h:4:0, > from include/uapi/linux/byteorder/big_endian.h:12, > from include/linux/byteorder/big_endian.h:4, > from arch/arm/include/uapi/asm/byteorder.h:19, > from include/asm-generic/bitops/le.h:5, > from arch/arm/include/asm/bitops.h:340, > from include/linux/bitops.h:37, > from include/linux/kernel.h:10, > from include/linux/list.h:8, > from include/linux/preempt.h:10, > from include/linux/spinlock.h:50, > from include/linux/seqlock.h:35, > from include/linux/time.h:5, > from include/uapi/linux/timex.h:56, > from include/linux/timex.h:56, > from include/linux/clocksource.h:12, > from drivers/clocksource/sprd-timer.c:7: >drivers/clocksource/sprd-timer.c: In function 'sprd_timer_update_counter': >drivers/clocksource/sprd-timer.c:85:24: warning: right shift count >= > width of type [-Wshift-count-overflow] > writel_relaxed(cycles >> TIMER_VALUE_HI_SHIFT, OK. I will fix this warning in next version. Thanks. >^ >include/uapi/linux/swab.h:113:54: note: in definition of macro '__swab32' > #define __swab32(x) (__u32)__builtin_bswap32((__u32)(x)) > ^ >include/linux/byteorder/generic.h:87:21: note: in expansion of macro > '__cpu_to_le32' > #define cpu_to_le32 __cpu_to_le32 > ^ >>> drivers/clocksource/sprd-timer.c:85:2: note: in expansion of macro >>> 'writel_relaxed' > writel_relaxed(cycles >> TIMER_VALUE_HI_SHIFT, > ^~ > > vim +/writel_relaxed +85 drivers/clocksource/sprd-timer.c > > 79 > 80 static void sprd_timer_update_counter(struct sprd_timer_device *timer, > 81unsigned long cycles) > 82 { > 83 writel_relaxed(cycles & TIMER_VALUE_LO_MASK, > 84 timer->base + TIMER_LOAD_LO); > > 85 writel_relaxed(cycles >> TIMER_VALUE_HI_SHIFT, > 86 timer->base + TIMER_LOAD_HI); > 87 } > 88 > > --- > 0-DAY kernel test infrastructureOpen Source Technology Center > https://lists.01.org/pipermail/kbuild-all Intel Corporation -- Baolin.wang Best Regards
Re: [PATCH 2/2] clocksource: sprd: Add timer driver for Spreadtrum SC9860 platform
On 25 November 2017 at 13:00, kbuild test robot wrote: > Hi Baolin, > > Thank you for the patch! Perhaps something to improve: > > [auto build test WARNING on tip/timers/core] > [also build test WARNING on v4.14 next-20171124] > [if your patch is applied to the wrong git tree, please drop us a note to > help improve the system] > > url: > https://github.com/0day-ci/linux/commits/Baolin-Wang/dt-bindings-clocksource-Add-Spreadtrum-SC9860-timer/20171125-090749 > config: arm-allmodconfig (attached as .config) > compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0 > reproduce: > wget > https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O > ~/bin/make.cross > chmod +x ~/bin/make.cross > # save the attached .config to linux build tree > make.cross ARCH=arm > > All warnings (new ones prefixed by >>): > >In file included from include/linux/swab.h:4:0, > from include/uapi/linux/byteorder/big_endian.h:12, > from include/linux/byteorder/big_endian.h:4, > from arch/arm/include/uapi/asm/byteorder.h:19, > from include/asm-generic/bitops/le.h:5, > from arch/arm/include/asm/bitops.h:340, > from include/linux/bitops.h:37, > from include/linux/kernel.h:10, > from include/linux/list.h:8, > from include/linux/preempt.h:10, > from include/linux/spinlock.h:50, > from include/linux/seqlock.h:35, > from include/linux/time.h:5, > from include/uapi/linux/timex.h:56, > from include/linux/timex.h:56, > from include/linux/clocksource.h:12, > from drivers/clocksource/sprd-timer.c:7: >drivers/clocksource/sprd-timer.c: In function 'sprd_timer_update_counter': >drivers/clocksource/sprd-timer.c:85:24: warning: right shift count >= > width of type [-Wshift-count-overflow] > writel_relaxed(cycles >> TIMER_VALUE_HI_SHIFT, OK. I will fix this warning in next version. Thanks. >^ >include/uapi/linux/swab.h:113:54: note: in definition of macro '__swab32' > #define __swab32(x) (__u32)__builtin_bswap32((__u32)(x)) > ^ >include/linux/byteorder/generic.h:87:21: note: in expansion of macro > '__cpu_to_le32' > #define cpu_to_le32 __cpu_to_le32 > ^ >>> drivers/clocksource/sprd-timer.c:85:2: note: in expansion of macro >>> 'writel_relaxed' > writel_relaxed(cycles >> TIMER_VALUE_HI_SHIFT, > ^~ > > vim +/writel_relaxed +85 drivers/clocksource/sprd-timer.c > > 79 > 80 static void sprd_timer_update_counter(struct sprd_timer_device *timer, > 81unsigned long cycles) > 82 { > 83 writel_relaxed(cycles & TIMER_VALUE_LO_MASK, > 84 timer->base + TIMER_LOAD_LO); > > 85 writel_relaxed(cycles >> TIMER_VALUE_HI_SHIFT, > 86 timer->base + TIMER_LOAD_HI); > 87 } > 88 > > --- > 0-DAY kernel test infrastructureOpen Source Technology Center > https://lists.01.org/pipermail/kbuild-all Intel Corporation -- Baolin.wang Best Regards
Re: [PATCH 2/2] clocksource: sprd: Add timer driver for Spreadtrum SC9860 platform
Hi Baolin, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on tip/timers/core] [also build test WARNING on v4.14 next-20171124] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Baolin-Wang/dt-bindings-clocksource-Add-Spreadtrum-SC9860-timer/20171125-090749 config: arm-allmodconfig (attached as .config) compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=arm All warnings (new ones prefixed by >>): In file included from include/linux/swab.h:4:0, from include/uapi/linux/byteorder/big_endian.h:12, from include/linux/byteorder/big_endian.h:4, from arch/arm/include/uapi/asm/byteorder.h:19, from include/asm-generic/bitops/le.h:5, from arch/arm/include/asm/bitops.h:340, from include/linux/bitops.h:37, from include/linux/kernel.h:10, from include/linux/list.h:8, from include/linux/preempt.h:10, from include/linux/spinlock.h:50, from include/linux/seqlock.h:35, from include/linux/time.h:5, from include/uapi/linux/timex.h:56, from include/linux/timex.h:56, from include/linux/clocksource.h:12, from drivers/clocksource/sprd-timer.c:7: drivers/clocksource/sprd-timer.c: In function 'sprd_timer_update_counter': drivers/clocksource/sprd-timer.c:85:24: warning: right shift count >= width of type [-Wshift-count-overflow] writel_relaxed(cycles >> TIMER_VALUE_HI_SHIFT, ^ include/uapi/linux/swab.h:113:54: note: in definition of macro '__swab32' #define __swab32(x) (__u32)__builtin_bswap32((__u32)(x)) ^ include/linux/byteorder/generic.h:87:21: note: in expansion of macro '__cpu_to_le32' #define cpu_to_le32 __cpu_to_le32 ^ >> drivers/clocksource/sprd-timer.c:85:2: note: in expansion of macro >> 'writel_relaxed' writel_relaxed(cycles >> TIMER_VALUE_HI_SHIFT, ^~ vim +/writel_relaxed +85 drivers/clocksource/sprd-timer.c 79 80 static void sprd_timer_update_counter(struct sprd_timer_device *timer, 81unsigned long cycles) 82 { 83 writel_relaxed(cycles & TIMER_VALUE_LO_MASK, 84 timer->base + TIMER_LOAD_LO); > 85 writel_relaxed(cycles >> TIMER_VALUE_HI_SHIFT, 86 timer->base + TIMER_LOAD_HI); 87 } 88 --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation .config.gz Description: application/gzip
Re: [PATCH 2/2] clocksource: sprd: Add timer driver for Spreadtrum SC9860 platform
Hi Baolin, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on tip/timers/core] [also build test WARNING on v4.14 next-20171124] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Baolin-Wang/dt-bindings-clocksource-Add-Spreadtrum-SC9860-timer/20171125-090749 config: arm-allmodconfig (attached as .config) compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=arm All warnings (new ones prefixed by >>): In file included from include/linux/swab.h:4:0, from include/uapi/linux/byteorder/big_endian.h:12, from include/linux/byteorder/big_endian.h:4, from arch/arm/include/uapi/asm/byteorder.h:19, from include/asm-generic/bitops/le.h:5, from arch/arm/include/asm/bitops.h:340, from include/linux/bitops.h:37, from include/linux/kernel.h:10, from include/linux/list.h:8, from include/linux/preempt.h:10, from include/linux/spinlock.h:50, from include/linux/seqlock.h:35, from include/linux/time.h:5, from include/uapi/linux/timex.h:56, from include/linux/timex.h:56, from include/linux/clocksource.h:12, from drivers/clocksource/sprd-timer.c:7: drivers/clocksource/sprd-timer.c: In function 'sprd_timer_update_counter': drivers/clocksource/sprd-timer.c:85:24: warning: right shift count >= width of type [-Wshift-count-overflow] writel_relaxed(cycles >> TIMER_VALUE_HI_SHIFT, ^ include/uapi/linux/swab.h:113:54: note: in definition of macro '__swab32' #define __swab32(x) (__u32)__builtin_bswap32((__u32)(x)) ^ include/linux/byteorder/generic.h:87:21: note: in expansion of macro '__cpu_to_le32' #define cpu_to_le32 __cpu_to_le32 ^ >> drivers/clocksource/sprd-timer.c:85:2: note: in expansion of macro >> 'writel_relaxed' writel_relaxed(cycles >> TIMER_VALUE_HI_SHIFT, ^~ vim +/writel_relaxed +85 drivers/clocksource/sprd-timer.c 79 80 static void sprd_timer_update_counter(struct sprd_timer_device *timer, 81unsigned long cycles) 82 { 83 writel_relaxed(cycles & TIMER_VALUE_LO_MASK, 84 timer->base + TIMER_LOAD_LO); > 85 writel_relaxed(cycles >> TIMER_VALUE_HI_SHIFT, 86 timer->base + TIMER_LOAD_HI); 87 } 88 --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation .config.gz Description: application/gzip
Re: [PATCH 2/2] clocksource: sprd: Add timer driver for Spreadtrum SC9860 platform
Hi Baolin, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on tip/timers/core] [also build test WARNING on v4.14 next-20171124] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Baolin-Wang/dt-bindings-clocksource-Add-Spreadtrum-SC9860-timer/20171125-090749 config: i386-allmodconfig (attached as .config) compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026 reproduce: # save the attached .config to linux build tree make ARCH=i386 All warnings (new ones prefixed by >>): In file included from arch/x86/include/asm/realmode.h:14:0, from arch/x86/include/asm/acpi.h:33, from arch/x86/include/asm/fixmap.h:19, from arch/x86/include/asm/apic.h:10, from arch/x86/include/asm/smp.h:12, from include/linux/smp.h:63, from include/linux/topology.h:33, from include/linux/gfp.h:8, from include/linux/idr.h:16, from include/linux/kernfs.h:14, from include/linux/sysfs.h:15, from include/linux/kobject.h:21, from include/linux/of.h:21, from include/linux/clocksource.h:18, from drivers/clocksource/sprd-timer.c:7: drivers/clocksource/sprd-timer.c: In function 'sprd_timer_update_counter': >> drivers/clocksource/sprd-timer.c:85:24: warning: right shift count >= width >> of type [-Wshift-count-overflow] writel_relaxed(cycles >> TIMER_VALUE_HI_SHIFT, ^ arch/x86/include/asm/io.h:87:39: note: in definition of macro 'writel_relaxed' #define writel_relaxed(v, a) __writel(v, a) ^ vim +85 drivers/clocksource/sprd-timer.c > 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include 13 #include 14 #include 15 #include 16 17 #define TIMER_NAME "sprd_timer" 18 19 #define TIMER_LOAD_LO 0x0 20 #define TIMER_LOAD_HI 0x4 21 #define TIMER_VALUE_LO 0x8 22 #define TIMER_VALUE_HI 0xc 23 24 #define TIMER_CTL 0x10 25 #define TIMER_CTL_PERIOD_MODE BIT(0) 26 #define TIMER_CTL_ENABLEBIT(1) 27 #define TIMER_CTL_64BIT_WIDTH BIT(16) 28 29 #define TIMER_INT 0x14 30 #define TIMER_INT_ENBIT(0) 31 #define TIMER_INT_RAW_STS BIT(1) 32 #define TIMER_INT_MASK_STS BIT(2) 33 #define TIMER_INT_CLR BIT(3) 34 35 #define TIMER_VALUE_SHDW_LO 0x18 36 #define TIMER_VALUE_SHDW_HI 0x1c 37 38 #define TIMER_VALUE_LO_MASK GENMASK(31, 0) 39 #define TIMER_VALUE_HI_SHIFT32 40 41 struct sprd_timer_device { 42 struct clock_event_device ce; 43 void __iomem *base; 44 u32 freq; 45 int irq; 46 }; 47 48 static inline struct sprd_timer_device * 49 to_sprd_timer(struct clock_event_device *c) 50 { 51 return container_of(c, struct sprd_timer_device, ce); 52 } 53 54 static void sprd_timer_enable(struct sprd_timer_device *timer, u32 flag) 55 { 56 u32 val = readl_relaxed(timer->base + TIMER_CTL); 57 58 val |= TIMER_CTL_ENABLE; 59 if (flag & TIMER_CTL_64BIT_WIDTH) 60 val |= TIMER_CTL_64BIT_WIDTH; 61 else 62 val &= ~TIMER_CTL_64BIT_WIDTH; 63 64 if (flag & TIMER_CTL_PERIOD_MODE) 65 val |= TIMER_CTL_PERIOD_MODE; 66 else 67 val &= ~TIMER_CTL_PERIOD_MODE; 68 69 writel_relaxed(val, timer->base + TIMER_CTL); 70 } 71 72 static void sprd_timer_disable(struct sprd_timer_device *timer) 73 { 74 u32 val = readl_relaxed(timer->base + TIMER_CTL); 75 76 val &= ~TIMER_CTL_ENABLE; 77 writel_relaxed(val, timer->base + TIMER_CTL); 78 } 79 80 static void sprd_timer_update_counter(struct sprd_timer_device *timer, 81unsigned long cycles) 82 { 83 writel_relaxed(cycles & TIMER_VALUE_LO_MASK, 84 timer->base + TIMER_LOAD_LO); > 85 writel_relaxed(cycles >> TIMER_VALUE_HI_SHIFT, 86 timer->base + TIMER_LOAD_HI); 87 } 88 --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation .config.gz Description: application/gzip
Re: [PATCH 2/2] clocksource: sprd: Add timer driver for Spreadtrum SC9860 platform
Hi Baolin, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on tip/timers/core] [also build test WARNING on v4.14 next-20171124] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Baolin-Wang/dt-bindings-clocksource-Add-Spreadtrum-SC9860-timer/20171125-090749 config: i386-allmodconfig (attached as .config) compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026 reproduce: # save the attached .config to linux build tree make ARCH=i386 All warnings (new ones prefixed by >>): In file included from arch/x86/include/asm/realmode.h:14:0, from arch/x86/include/asm/acpi.h:33, from arch/x86/include/asm/fixmap.h:19, from arch/x86/include/asm/apic.h:10, from arch/x86/include/asm/smp.h:12, from include/linux/smp.h:63, from include/linux/topology.h:33, from include/linux/gfp.h:8, from include/linux/idr.h:16, from include/linux/kernfs.h:14, from include/linux/sysfs.h:15, from include/linux/kobject.h:21, from include/linux/of.h:21, from include/linux/clocksource.h:18, from drivers/clocksource/sprd-timer.c:7: drivers/clocksource/sprd-timer.c: In function 'sprd_timer_update_counter': >> drivers/clocksource/sprd-timer.c:85:24: warning: right shift count >= width >> of type [-Wshift-count-overflow] writel_relaxed(cycles >> TIMER_VALUE_HI_SHIFT, ^ arch/x86/include/asm/io.h:87:39: note: in definition of macro 'writel_relaxed' #define writel_relaxed(v, a) __writel(v, a) ^ vim +85 drivers/clocksource/sprd-timer.c > 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include 13 #include 14 #include 15 #include 16 17 #define TIMER_NAME "sprd_timer" 18 19 #define TIMER_LOAD_LO 0x0 20 #define TIMER_LOAD_HI 0x4 21 #define TIMER_VALUE_LO 0x8 22 #define TIMER_VALUE_HI 0xc 23 24 #define TIMER_CTL 0x10 25 #define TIMER_CTL_PERIOD_MODE BIT(0) 26 #define TIMER_CTL_ENABLEBIT(1) 27 #define TIMER_CTL_64BIT_WIDTH BIT(16) 28 29 #define TIMER_INT 0x14 30 #define TIMER_INT_ENBIT(0) 31 #define TIMER_INT_RAW_STS BIT(1) 32 #define TIMER_INT_MASK_STS BIT(2) 33 #define TIMER_INT_CLR BIT(3) 34 35 #define TIMER_VALUE_SHDW_LO 0x18 36 #define TIMER_VALUE_SHDW_HI 0x1c 37 38 #define TIMER_VALUE_LO_MASK GENMASK(31, 0) 39 #define TIMER_VALUE_HI_SHIFT32 40 41 struct sprd_timer_device { 42 struct clock_event_device ce; 43 void __iomem *base; 44 u32 freq; 45 int irq; 46 }; 47 48 static inline struct sprd_timer_device * 49 to_sprd_timer(struct clock_event_device *c) 50 { 51 return container_of(c, struct sprd_timer_device, ce); 52 } 53 54 static void sprd_timer_enable(struct sprd_timer_device *timer, u32 flag) 55 { 56 u32 val = readl_relaxed(timer->base + TIMER_CTL); 57 58 val |= TIMER_CTL_ENABLE; 59 if (flag & TIMER_CTL_64BIT_WIDTH) 60 val |= TIMER_CTL_64BIT_WIDTH; 61 else 62 val &= ~TIMER_CTL_64BIT_WIDTH; 63 64 if (flag & TIMER_CTL_PERIOD_MODE) 65 val |= TIMER_CTL_PERIOD_MODE; 66 else 67 val &= ~TIMER_CTL_PERIOD_MODE; 68 69 writel_relaxed(val, timer->base + TIMER_CTL); 70 } 71 72 static void sprd_timer_disable(struct sprd_timer_device *timer) 73 { 74 u32 val = readl_relaxed(timer->base + TIMER_CTL); 75 76 val &= ~TIMER_CTL_ENABLE; 77 writel_relaxed(val, timer->base + TIMER_CTL); 78 } 79 80 static void sprd_timer_update_counter(struct sprd_timer_device *timer, 81unsigned long cycles) 82 { 83 writel_relaxed(cycles & TIMER_VALUE_LO_MASK, 84 timer->base + TIMER_LOAD_LO); > 85 writel_relaxed(cycles >> TIMER_VALUE_HI_SHIFT, 86 timer->base + TIMER_LOAD_HI); 87 } 88 --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation .config.gz Description: application/gzip
[PATCH 2/2] clocksource: sprd: Add timer driver for Spreadtrum SC9860 platform
The Spreadtrum SC9860 platform will use the architected timers as local clock events, but we also need a broadcast timer device to wakeup the cpus when the cpus are in sleep mode. Thus this patch registers the timer0 to be a broadcast timer supporting periodic and oneshot events. Signed-off-by: Baolin Wang--- drivers/clocksource/Kconfig |8 ++ drivers/clocksource/Makefile |1 + drivers/clocksource/sprd-timer.c | 213 ++ 3 files changed, 222 insertions(+) create mode 100644 drivers/clocksource/sprd-timer.c diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index cc60620..aa05132 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -467,6 +467,14 @@ config MTK_TIMER help Support for Mediatek timer driver. +config SPRD_TIMER + bool "Spreadtrum timer driver" + depends on GENERIC_CLOCKEVENTS + depends on ARCH_SPRD || COMPILE_TEST + select TIMER_OF + help + Enables the support for the Spreadtrum timer driver. + config SYS_SUPPORTS_SH_MTU2 bool diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index dbc1ad1..c657d3d 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_CLKSRC_TI_32K) += timer-ti-32k.o obj-$(CONFIG_CLKSRC_NPS) += timer-nps.o obj-$(CONFIG_OXNAS_RPS_TIMER) += timer-oxnas-rps.o obj-$(CONFIG_OWL_TIMER)+= owl-timer.o +obj-$(CONFIG_SPRD_TIMER) += sprd-timer.o obj-$(CONFIG_ARC_TIMERS) += arc_timer.o obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o diff --git a/drivers/clocksource/sprd-timer.c b/drivers/clocksource/sprd-timer.c new file mode 100644 index 000..6fec0c5 --- /dev/null +++ b/drivers/clocksource/sprd-timer.c @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2017 Spreadtrum Communications Inc. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TIMER_NAME "sprd_timer" + +#define TIMER_LOAD_LO 0x0 +#define TIMER_LOAD_HI 0x4 +#define TIMER_VALUE_LO 0x8 +#define TIMER_VALUE_HI 0xc + +#define TIMER_CTL 0x10 +#define TIMER_CTL_PERIOD_MODE BIT(0) +#define TIMER_CTL_ENABLE BIT(1) +#define TIMER_CTL_64BIT_WIDTH BIT(16) + +#define TIMER_INT 0x14 +#define TIMER_INT_EN BIT(0) +#define TIMER_INT_RAW_STS BIT(1) +#define TIMER_INT_MASK_STS BIT(2) +#define TIMER_INT_CLR BIT(3) + +#define TIMER_VALUE_SHDW_LO0x18 +#define TIMER_VALUE_SHDW_HI0x1c + +#define TIMER_VALUE_LO_MASKGENMASK(31, 0) +#define TIMER_VALUE_HI_SHIFT 32 + +struct sprd_timer_device { + struct clock_event_device ce; + void __iomem *base; + u32 freq; + int irq; +}; + +static inline struct sprd_timer_device * +to_sprd_timer(struct clock_event_device *c) +{ + return container_of(c, struct sprd_timer_device, ce); +} + +static void sprd_timer_enable(struct sprd_timer_device *timer, u32 flag) +{ + u32 val = readl_relaxed(timer->base + TIMER_CTL); + + val |= TIMER_CTL_ENABLE; + if (flag & TIMER_CTL_64BIT_WIDTH) + val |= TIMER_CTL_64BIT_WIDTH; + else + val &= ~TIMER_CTL_64BIT_WIDTH; + + if (flag & TIMER_CTL_PERIOD_MODE) + val |= TIMER_CTL_PERIOD_MODE; + else + val &= ~TIMER_CTL_PERIOD_MODE; + + writel_relaxed(val, timer->base + TIMER_CTL); +} + +static void sprd_timer_disable(struct sprd_timer_device *timer) +{ + u32 val = readl_relaxed(timer->base + TIMER_CTL); + + val &= ~TIMER_CTL_ENABLE; + writel_relaxed(val, timer->base + TIMER_CTL); +} + +static void sprd_timer_update_counter(struct sprd_timer_device *timer, + unsigned long cycles) +{ + writel_relaxed(cycles & TIMER_VALUE_LO_MASK, + timer->base + TIMER_LOAD_LO); + writel_relaxed(cycles >> TIMER_VALUE_HI_SHIFT, + timer->base + TIMER_LOAD_HI); +} + +static void sprd_timer_enable_interrupt(struct sprd_timer_device *timer) +{ + writel_relaxed(TIMER_INT_EN, timer->base + TIMER_INT); +} + +static void sprd_timer_clear_interrupt(struct sprd_timer_device *timer) +{ + u32 val = readl_relaxed(timer->base + TIMER_INT); + + val |= TIMER_INT_CLR; + writel_relaxed(val, timer->base + TIMER_INT); +} + +static int sprd_timer_set_next_event(unsigned long cycles, +struct clock_event_device *ce) +{ + struct sprd_timer_device *timer = to_sprd_timer(ce); + + sprd_timer_disable(timer); + sprd_timer_update_counter(timer, cycles); + sprd_timer_enable(timer, TIMER_CTL_64BIT_WIDTH); + + return 0; +} + +static int sprd_timer_set_periodic(struct
[PATCH 2/2] clocksource: sprd: Add timer driver for Spreadtrum SC9860 platform
The Spreadtrum SC9860 platform will use the architected timers as local clock events, but we also need a broadcast timer device to wakeup the cpus when the cpus are in sleep mode. Thus this patch registers the timer0 to be a broadcast timer supporting periodic and oneshot events. Signed-off-by: Baolin Wang --- drivers/clocksource/Kconfig |8 ++ drivers/clocksource/Makefile |1 + drivers/clocksource/sprd-timer.c | 213 ++ 3 files changed, 222 insertions(+) create mode 100644 drivers/clocksource/sprd-timer.c diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index cc60620..aa05132 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -467,6 +467,14 @@ config MTK_TIMER help Support for Mediatek timer driver. +config SPRD_TIMER + bool "Spreadtrum timer driver" + depends on GENERIC_CLOCKEVENTS + depends on ARCH_SPRD || COMPILE_TEST + select TIMER_OF + help + Enables the support for the Spreadtrum timer driver. + config SYS_SUPPORTS_SH_MTU2 bool diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index dbc1ad1..c657d3d 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_CLKSRC_TI_32K) += timer-ti-32k.o obj-$(CONFIG_CLKSRC_NPS) += timer-nps.o obj-$(CONFIG_OXNAS_RPS_TIMER) += timer-oxnas-rps.o obj-$(CONFIG_OWL_TIMER)+= owl-timer.o +obj-$(CONFIG_SPRD_TIMER) += sprd-timer.o obj-$(CONFIG_ARC_TIMERS) += arc_timer.o obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o diff --git a/drivers/clocksource/sprd-timer.c b/drivers/clocksource/sprd-timer.c new file mode 100644 index 000..6fec0c5 --- /dev/null +++ b/drivers/clocksource/sprd-timer.c @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2017 Spreadtrum Communications Inc. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TIMER_NAME "sprd_timer" + +#define TIMER_LOAD_LO 0x0 +#define TIMER_LOAD_HI 0x4 +#define TIMER_VALUE_LO 0x8 +#define TIMER_VALUE_HI 0xc + +#define TIMER_CTL 0x10 +#define TIMER_CTL_PERIOD_MODE BIT(0) +#define TIMER_CTL_ENABLE BIT(1) +#define TIMER_CTL_64BIT_WIDTH BIT(16) + +#define TIMER_INT 0x14 +#define TIMER_INT_EN BIT(0) +#define TIMER_INT_RAW_STS BIT(1) +#define TIMER_INT_MASK_STS BIT(2) +#define TIMER_INT_CLR BIT(3) + +#define TIMER_VALUE_SHDW_LO0x18 +#define TIMER_VALUE_SHDW_HI0x1c + +#define TIMER_VALUE_LO_MASKGENMASK(31, 0) +#define TIMER_VALUE_HI_SHIFT 32 + +struct sprd_timer_device { + struct clock_event_device ce; + void __iomem *base; + u32 freq; + int irq; +}; + +static inline struct sprd_timer_device * +to_sprd_timer(struct clock_event_device *c) +{ + return container_of(c, struct sprd_timer_device, ce); +} + +static void sprd_timer_enable(struct sprd_timer_device *timer, u32 flag) +{ + u32 val = readl_relaxed(timer->base + TIMER_CTL); + + val |= TIMER_CTL_ENABLE; + if (flag & TIMER_CTL_64BIT_WIDTH) + val |= TIMER_CTL_64BIT_WIDTH; + else + val &= ~TIMER_CTL_64BIT_WIDTH; + + if (flag & TIMER_CTL_PERIOD_MODE) + val |= TIMER_CTL_PERIOD_MODE; + else + val &= ~TIMER_CTL_PERIOD_MODE; + + writel_relaxed(val, timer->base + TIMER_CTL); +} + +static void sprd_timer_disable(struct sprd_timer_device *timer) +{ + u32 val = readl_relaxed(timer->base + TIMER_CTL); + + val &= ~TIMER_CTL_ENABLE; + writel_relaxed(val, timer->base + TIMER_CTL); +} + +static void sprd_timer_update_counter(struct sprd_timer_device *timer, + unsigned long cycles) +{ + writel_relaxed(cycles & TIMER_VALUE_LO_MASK, + timer->base + TIMER_LOAD_LO); + writel_relaxed(cycles >> TIMER_VALUE_HI_SHIFT, + timer->base + TIMER_LOAD_HI); +} + +static void sprd_timer_enable_interrupt(struct sprd_timer_device *timer) +{ + writel_relaxed(TIMER_INT_EN, timer->base + TIMER_INT); +} + +static void sprd_timer_clear_interrupt(struct sprd_timer_device *timer) +{ + u32 val = readl_relaxed(timer->base + TIMER_INT); + + val |= TIMER_INT_CLR; + writel_relaxed(val, timer->base + TIMER_INT); +} + +static int sprd_timer_set_next_event(unsigned long cycles, +struct clock_event_device *ce) +{ + struct sprd_timer_device *timer = to_sprd_timer(ce); + + sprd_timer_disable(timer); + sprd_timer_update_counter(timer, cycles); + sprd_timer_enable(timer, TIMER_CTL_64BIT_WIDTH); + + return 0; +} + +static int sprd_timer_set_periodic(struct clock_event_device *ce) +{ +