From 7d19d521a034a8c58586814e0320463d1299a3a9 Mon Sep 17 00:00:00 2001 From: Kefeng Wang Date: Fri, 18 Sep 2020 21:22:29 +0800 Subject: clocksource/drivers/sp804: Cleanup clk_get_sys() Move the clk_get_sys() part into sp804_get_clock_rate(), cleanup the same code. Signed-off-by: Kefeng Wang Signed-off-by: Zhen Lei Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200918132237.3552-2-thunder.leizhen@huawei.com --- drivers/clocksource/timer-sp804.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c index 5cd0abf9b396..bec2d372e0df 100644 --- a/drivers/clocksource/timer-sp804.c +++ b/drivers/clocksource/timer-sp804.c @@ -22,11 +22,18 @@ #include "timer-sp.h" -static long __init sp804_get_clock_rate(struct clk *clk) +static long __init sp804_get_clock_rate(struct clk *clk, const char *name) { long rate; int err; + if (!clk) + clk = clk_get_sys("sp804", name); + if (IS_ERR(clk)) { + pr_err("sp804: %s clock not found: %ld\n", name, PTR_ERR(clk)); + return PTR_ERR(clk); + } + err = clk_prepare(clk); if (err) { pr_err("sp804: clock failed to prepare: %d\n", err); @@ -72,16 +79,7 @@ int __init __sp804_clocksource_and_sched_clock_init(void __iomem *base, { long rate; - if (!clk) { - clk = clk_get_sys("sp804", name); - if (IS_ERR(clk)) { - pr_err("sp804: clock not found: %d\n", - (int)PTR_ERR(clk)); - return PTR_ERR(clk); - } - } - - rate = sp804_get_clock_rate(clk); + rate = sp804_get_clock_rate(clk, name); if (rate < 0) return -EINVAL; @@ -173,15 +171,7 @@ int __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struct struct clock_event_device *evt = &sp804_clockevent; long rate; - if (!clk) - clk = clk_get_sys("sp804", name); - if (IS_ERR(clk)) { - pr_err("sp804: %s clock not found: %d\n", name, - (int)PTR_ERR(clk)); - return PTR_ERR(clk); - } - - rate = sp804_get_clock_rate(clk); + rate = sp804_get_clock_rate(clk, name); if (rate < 0) return -EINVAL; -- cgit v1.2.3 From 65f4d7ddc7b681001246f60c22a3cf650864da35 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Fri, 18 Sep 2020 21:22:30 +0800 Subject: clocksource/drivers/sp804: Remove unused sp804_timer_disable() and timer-sp804.h Since commit 7484c727b636 ("ARM: realview: delete the RealView board files") and commit 16956fed35fe ("ARM: versatile: switch to DT only booting and remove legacy code"), there's no one to use the functions defined or declared in include/clocksource/timer-sp804.h. Delete it. Signed-off-by: Zhen Lei Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200918132237.3552-3-thunder.leizhen@huawei.com --- drivers/clocksource/timer-sp804.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c index bec2d372e0df..97b41a493253 100644 --- a/drivers/clocksource/timer-sp804.c +++ b/drivers/clocksource/timer-sp804.c @@ -18,8 +18,6 @@ #include #include -#include - #include "timer-sp.h" static long __init sp804_get_clock_rate(struct clk *clk, const char *name) @@ -67,11 +65,6 @@ static u64 notrace sp804_read(void) return ~readl_relaxed(sched_clock_base + TIMER_VALUE); } -void __init sp804_timer_disable(void __iomem *base) -{ - writel(0, base + TIMER_CTRL); -} - int __init __sp804_clocksource_and_sched_clock_init(void __iomem *base, const char *name, struct clk *clk, -- cgit v1.2.3 From 975434f8b24a55af31daa4634972890c061a0a0c Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Fri, 18 Sep 2020 21:22:31 +0800 Subject: clocksource/drivers/sp804: Delete the leading "__" of some functions Delete the leading "__" of __sp804_clocksource_and_sched_clock_init() and __sp804_clockevents_init(), make it looks a little more comfortable. Signed-off-by: Zhen Lei Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200918132237.3552-4-thunder.leizhen@huawei.com --- drivers/clocksource/timer-sp804.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c index 97b41a493253..097f5a83163c 100644 --- a/drivers/clocksource/timer-sp804.c +++ b/drivers/clocksource/timer-sp804.c @@ -65,10 +65,10 @@ static u64 notrace sp804_read(void) return ~readl_relaxed(sched_clock_base + TIMER_VALUE); } -int __init __sp804_clocksource_and_sched_clock_init(void __iomem *base, - const char *name, - struct clk *clk, - int use_sched_clock) +int __init sp804_clocksource_and_sched_clock_init(void __iomem *base, + const char *name, + struct clk *clk, + int use_sched_clock) { long rate; @@ -159,7 +159,8 @@ static struct clock_event_device sp804_clockevent = { .rating = 300, }; -int __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struct clk *clk, const char *name) +int __init sp804_clockevents_init(void __iomem *base, unsigned int irq, + struct clk *clk, const char *name) { struct clock_event_device *evt = &sp804_clockevent; long rate; @@ -228,21 +229,22 @@ static int __init sp804_of_init(struct device_node *np) of_property_read_u32(np, "arm,sp804-has-irq", &irq_num); if (irq_num == 2) { - ret = __sp804_clockevents_init(base + TIMER_2_BASE, irq, clk2, name); + ret = sp804_clockevents_init(base + TIMER_2_BASE, irq, clk2, name); if (ret) goto err; - ret = __sp804_clocksource_and_sched_clock_init(base, name, clk1, 1); + ret = sp804_clocksource_and_sched_clock_init(base, + name, clk1, 1); if (ret) goto err; } else { - ret = __sp804_clockevents_init(base, irq, clk1 , name); + ret = sp804_clockevents_init(base, irq, clk1, name); if (ret) goto err; - ret =__sp804_clocksource_and_sched_clock_init(base + TIMER_2_BASE, - name, clk2, 1); + ret = sp804_clocksource_and_sched_clock_init(base + TIMER_2_BASE, + name, clk2, 1); if (ret) goto err; } @@ -282,7 +284,8 @@ static int __init integrator_cp_of_init(struct device_node *np) goto err; if (!init_count) { - ret = __sp804_clocksource_and_sched_clock_init(base, name, clk, 0); + ret = sp804_clocksource_and_sched_clock_init(base, + name, clk, 0); if (ret) goto err; } else { @@ -290,7 +293,7 @@ static int __init integrator_cp_of_init(struct device_node *np) if (irq <= 0) goto err; - ret = __sp804_clockevents_init(base, irq, clk, name); + ret = sp804_clockevents_init(base, irq, clk, name); if (ret) goto err; } -- cgit v1.2.3 From 2f71078e7753b2fbba62999aa46c2fad16df9d98 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Fri, 18 Sep 2020 21:22:32 +0800 Subject: clocksource/drivers/sp804: Remove a mismatched comment writel(0, base + TIMER_CTRL); ... ... writel(xxx | TIMER_CTRL_PERIODIC, base + TIMER_CTRL); The timer is just temporarily disabled, and it will be set to periodic mode later. The description of the field TimerMode of the register TimerXControl as shown below: 0 = Timer module is in free-running mode (default) 1 = Timer module is in periodic mode. Signed-off-by: Zhen Lei Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200918132237.3552-5-thunder.leizhen@huawei.com --- drivers/clocksource/timer-sp804.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c index 097f5a83163c..a443f392a8e7 100644 --- a/drivers/clocksource/timer-sp804.c +++ b/drivers/clocksource/timer-sp804.c @@ -76,7 +76,6 @@ int __init sp804_clocksource_and_sched_clock_init(void __iomem *base, if (rate < 0) return -EINVAL; - /* setup timer 0 as free-running clocksource */ writel(0, base + TIMER_CTRL); writel(0xffffffff, base + TIMER_LOAD); writel(0xffffffff, base + TIMER_VALUE); -- cgit v1.2.3 From e69aae713bef63b357d4ff85bcb3f8f63dbf4ba3 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Fri, 18 Sep 2020 21:22:33 +0800 Subject: clocksource/drivers/sp804: Prepare for support non-standard register offset Add two local variables: timer1_base and timer2_base in sp804_of_init(), to avoid repeatedly calculate the base address of timer2, and make it easier to recognize timer1. Hope to make the next patch looks more clear. No functional change. Signed-off-by: Zhen Lei Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200918132237.3552-6-thunder.leizhen@huawei.com --- drivers/clocksource/timer-sp804.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c index a443f392a8e7..471c5c6aaf51 100644 --- a/drivers/clocksource/timer-sp804.c +++ b/drivers/clocksource/timer-sp804.c @@ -188,6 +188,8 @@ static int __init sp804_of_init(struct device_node *np) { static bool initialized = false; void __iomem *base; + void __iomem *timer1_base; + void __iomem *timer2_base; int irq, ret = -EINVAL; u32 irq_num = 0; struct clk *clk1, *clk2; @@ -197,9 +199,12 @@ static int __init sp804_of_init(struct device_node *np) if (!base) return -ENXIO; + timer1_base = base; + timer2_base = base + TIMER_2_BASE; + /* Ensure timers are disabled */ - writel(0, base + TIMER_CTRL); - writel(0, base + TIMER_2_BASE + TIMER_CTRL); + writel(0, timer1_base + TIMER_CTRL); + writel(0, timer2_base + TIMER_CTRL); if (initialized || !of_device_is_available(np)) { ret = -EINVAL; @@ -228,21 +233,21 @@ static int __init sp804_of_init(struct device_node *np) of_property_read_u32(np, "arm,sp804-has-irq", &irq_num); if (irq_num == 2) { - ret = sp804_clockevents_init(base + TIMER_2_BASE, irq, clk2, name); + ret = sp804_clockevents_init(timer2_base, irq, clk2, name); if (ret) goto err; - ret = sp804_clocksource_and_sched_clock_init(base, + ret = sp804_clocksource_and_sched_clock_init(timer1_base, name, clk1, 1); if (ret) goto err; } else { - ret = sp804_clockevents_init(base, irq, clk1, name); + ret = sp804_clockevents_init(timer1_base, irq, clk1, name); if (ret) goto err; - ret = sp804_clocksource_and_sched_clock_init(base + TIMER_2_BASE, + ret = sp804_clocksource_and_sched_clock_init(timer2_base, name, clk2, 1); if (ret) goto err; -- cgit v1.2.3 From 23c788cd48db9e2646fb5455f004e4a5626e4230 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Fri, 18 Sep 2020 21:22:34 +0800 Subject: clocksource/drivers/sp804: Support non-standard register offset The ARM SP804 supports a maximum of 32-bit counter, but Hisilicon extends it to 64-bit. That means, the registers: TimerXload, TimerXValue and TimerXBGLoad are 64bits, all other registers are the same as those in the SP804. The driver code can be completely reused except that the register offset is different. Currently, we get a timer register address by: add the constant register offset to the timer base address. e.g. "base + TIMER_CTRL". It can not be dynamically adjusted at run time. So create a new structure "sp804_timer" to record the original registers offset, and create a new structure "sp804_clkevt" to record the calculated registers address. So the "base + TIMER_CTRL" is changed to "clkevt->ctrl", this will faster than "base + timer->ctrl". For example: struct sp804_timer arm_sp804_timer = { .ctrl = TIMER_CTRL, }; struct sp804_clkevt clkevt; clkevt.ctrl = base + arm_sp804_timer.ctrl. - writel(0, base + TIMER_CTRL); + writel(0, clkevt->ctrl); Signed-off-by: Zhen Lei Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200918132237.3552-7-thunder.leizhen@huawei.com --- drivers/clocksource/timer-sp.h | 26 +++++++++ drivers/clocksource/timer-sp804.c | 108 +++++++++++++++++++++++++++++--------- 2 files changed, 108 insertions(+), 26 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-sp.h b/drivers/clocksource/timer-sp.h index b2037eb94a41..1ab75cbed0e0 100644 --- a/drivers/clocksource/timer-sp.h +++ b/drivers/clocksource/timer-sp.h @@ -10,6 +10,7 @@ * * Every SP804 contains two identical timers. */ +#define NR_TIMERS 2 #define TIMER_1_BASE 0x00 #define TIMER_2_BASE 0x20 @@ -29,3 +30,28 @@ #define TIMER_RIS 0x10 /* CVR ro */ #define TIMER_MIS 0x14 /* CVR ro */ #define TIMER_BGLOAD 0x18 /* CVR rw */ + +struct sp804_timer { + int load; + int value; + int ctrl; + int intclr; + int ris; + int mis; + int bgload; + int timer_base[NR_TIMERS]; + int width; +}; + +struct sp804_clkevt { + void __iomem *base; + void __iomem *load; + void __iomem *value; + void __iomem *ctrl; + void __iomem *intclr; + void __iomem *ris; + void __iomem *mis; + void __iomem *bgload; + unsigned long reload; + int width; +}; diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c index 471c5c6aaf51..5f4f979a8ef2 100644 --- a/drivers/clocksource/timer-sp804.c +++ b/drivers/clocksource/timer-sp804.c @@ -20,6 +20,17 @@ #include "timer-sp.h" +struct sp804_timer __initdata arm_sp804_timer = { + .load = TIMER_LOAD, + .value = TIMER_VALUE, + .ctrl = TIMER_CTRL, + .intclr = TIMER_INTCLR, + .timer_base = {TIMER_1_BASE, TIMER_2_BASE}, + .width = 32, +}; + +static struct sp804_clkevt sp804_clkevt[NR_TIMERS]; + static long __init sp804_get_clock_rate(struct clk *clk, const char *name) { long rate; @@ -58,11 +69,26 @@ static long __init sp804_get_clock_rate(struct clk *clk, const char *name) return rate; } -static void __iomem *sched_clock_base; +static struct sp804_clkevt * __init sp804_clkevt_get(void __iomem *base) +{ + int i; + + for (i = 0; i < NR_TIMERS; i++) { + if (sp804_clkevt[i].base == base) + return &sp804_clkevt[i]; + } + + /* It's impossible to reach here */ + WARN_ON(1); + + return NULL; +} + +static struct sp804_clkevt *sched_clkevt; static u64 notrace sp804_read(void) { - return ~readl_relaxed(sched_clock_base + TIMER_VALUE); + return ~readl_relaxed(sched_clkevt->value); } int __init sp804_clocksource_and_sched_clock_init(void __iomem *base, @@ -71,22 +97,25 @@ int __init sp804_clocksource_and_sched_clock_init(void __iomem *base, int use_sched_clock) { long rate; + struct sp804_clkevt *clkevt; rate = sp804_get_clock_rate(clk, name); if (rate < 0) return -EINVAL; - writel(0, base + TIMER_CTRL); - writel(0xffffffff, base + TIMER_LOAD); - writel(0xffffffff, base + TIMER_VALUE); + clkevt = sp804_clkevt_get(base); + + writel(0, clkevt->ctrl); + writel(0xffffffff, clkevt->load); + writel(0xffffffff, clkevt->value); writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, - base + TIMER_CTRL); + clkevt->ctrl); - clocksource_mmio_init(base + TIMER_VALUE, name, + clocksource_mmio_init(clkevt->value, name, rate, 200, 32, clocksource_mmio_readl_down); if (use_sched_clock) { - sched_clock_base = base; + sched_clkevt = clkevt; sched_clock_register(sp804_read, 32, rate); } @@ -94,8 +123,7 @@ int __init sp804_clocksource_and_sched_clock_init(void __iomem *base, } -static void __iomem *clkevt_base; -static unsigned long clkevt_reload; +static struct sp804_clkevt *common_clkevt; /* * IRQ handler for the timer @@ -105,7 +133,7 @@ static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id) struct clock_event_device *evt = dev_id; /* clear the interrupt */ - writel(1, clkevt_base + TIMER_INTCLR); + writel(1, common_clkevt->intclr); evt->event_handler(evt); @@ -114,7 +142,7 @@ static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id) static inline void timer_shutdown(struct clock_event_device *evt) { - writel(0, clkevt_base + TIMER_CTRL); + writel(0, common_clkevt->ctrl); } static int sp804_shutdown(struct clock_event_device *evt) @@ -129,8 +157,8 @@ static int sp804_set_periodic(struct clock_event_device *evt) TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; timer_shutdown(evt); - writel(clkevt_reload, clkevt_base + TIMER_LOAD); - writel(ctrl, clkevt_base + TIMER_CTRL); + writel(common_clkevt->reload, common_clkevt->load); + writel(ctrl, common_clkevt->ctrl); return 0; } @@ -140,8 +168,8 @@ static int sp804_set_next_event(unsigned long next, unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE | TIMER_CTRL_ONESHOT | TIMER_CTRL_ENABLE; - writel(next, clkevt_base + TIMER_LOAD); - writel(ctrl, clkevt_base + TIMER_CTRL); + writel(next, common_clkevt->load); + writel(ctrl, common_clkevt->ctrl); return 0; } @@ -168,13 +196,13 @@ int __init sp804_clockevents_init(void __iomem *base, unsigned int irq, if (rate < 0) return -EINVAL; - clkevt_base = base; - clkevt_reload = DIV_ROUND_CLOSEST(rate, HZ); + common_clkevt = sp804_clkevt_get(base); + common_clkevt->reload = DIV_ROUND_CLOSEST(rate, HZ); evt->name = name; evt->irq = irq; evt->cpumask = cpu_possible_mask; - writel(0, base + TIMER_CTRL); + writel(0, common_clkevt->ctrl); if (request_irq(irq, sp804_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL, "timer", &sp804_clockevent)) @@ -184,7 +212,26 @@ int __init sp804_clockevents_init(void __iomem *base, unsigned int irq, return 0; } -static int __init sp804_of_init(struct device_node *np) +static void __init sp804_clkevt_init(struct sp804_timer *timer, void __iomem *base) +{ + int i; + + for (i = 0; i < NR_TIMERS; i++) { + void __iomem *timer_base; + struct sp804_clkevt *clkevt; + + timer_base = base + timer->timer_base[i]; + clkevt = &sp804_clkevt[i]; + clkevt->base = timer_base; + clkevt->load = timer_base + timer->load; + clkevt->value = timer_base + timer->value; + clkevt->ctrl = timer_base + timer->ctrl; + clkevt->intclr = timer_base + timer->intclr; + clkevt->width = timer->width; + } +} + +static int __init sp804_of_init(struct device_node *np, struct sp804_timer *timer) { static bool initialized = false; void __iomem *base; @@ -199,12 +246,12 @@ static int __init sp804_of_init(struct device_node *np) if (!base) return -ENXIO; - timer1_base = base; - timer2_base = base + TIMER_2_BASE; + timer1_base = base + timer->timer_base[0]; + timer2_base = base + timer->timer_base[1]; /* Ensure timers are disabled */ - writel(0, timer1_base + TIMER_CTRL); - writel(0, timer2_base + TIMER_CTRL); + writel(0, timer1_base + timer->ctrl); + writel(0, timer2_base + timer->ctrl); if (initialized || !of_device_is_available(np)) { ret = -EINVAL; @@ -230,6 +277,8 @@ static int __init sp804_of_init(struct device_node *np) if (irq <= 0) goto err; + sp804_clkevt_init(timer, base); + of_property_read_u32(np, "arm,sp804-has-irq", &irq_num); if (irq_num == 2) { @@ -259,7 +308,12 @@ err: iounmap(base); return ret; } -TIMER_OF_DECLARE(sp804, "arm,sp804", sp804_of_init); + +static int __init arm_sp804_of_init(struct device_node *np) +{ + return sp804_of_init(np, &arm_sp804_timer); +} +TIMER_OF_DECLARE(sp804, "arm,sp804", arm_sp804_of_init); static int __init integrator_cp_of_init(struct device_node *np) { @@ -282,11 +336,13 @@ static int __init integrator_cp_of_init(struct device_node *np) } /* Ensure timer is disabled */ - writel(0, base + TIMER_CTRL); + writel(0, base + arm_sp804_timer.ctrl); if (init_count == 2 || !of_device_is_available(np)) goto err; + sp804_clkevt_init(&arm_sp804_timer, base); + if (!init_count) { ret = sp804_clocksource_and_sched_clock_init(base, name, clk, 0); -- cgit v1.2.3 From bd5a1936ffa2b69032815775fa54fc1c422d49d5 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Fri, 18 Sep 2020 21:22:35 +0800 Subject: clocksource/drivers/sp804: Add support for Hisilicon sp804 timer The ARM SP804 supports a maximum of 32-bit counter, but Hisilicon extends it to 64-bit. That means, the registers: TimerXload, TimerXValue and TimerXBGLoad are 64bits, all other registers are the same as those in the SP804. The driver code can be completely reused except that the register offset is different. Use compatible = "hisilicon,sp804" mark as Hisilicon sp804 timer. Signed-off-by: Zhen Lei Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200918132237.3552-8-thunder.leizhen@huawei.com --- drivers/clocksource/timer-sp804.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c index 5f4f979a8ef2..f0783d19522f 100644 --- a/drivers/clocksource/timer-sp804.c +++ b/drivers/clocksource/timer-sp804.c @@ -20,6 +20,18 @@ #include "timer-sp.h" +/* Hisilicon 64-bit timer(a variant of ARM SP804) */ +#define HISI_TIMER_1_BASE 0x00 +#define HISI_TIMER_2_BASE 0x40 +#define HISI_TIMER_LOAD 0x00 +#define HISI_TIMER_VALUE 0x08 +#define HISI_TIMER_CTRL 0x10 +#define HISI_TIMER_INTCLR 0x14 +#define HISI_TIMER_RIS 0x18 +#define HISI_TIMER_MIS 0x1c +#define HISI_TIMER_BGLOAD 0x20 + + struct sp804_timer __initdata arm_sp804_timer = { .load = TIMER_LOAD, .value = TIMER_VALUE, @@ -29,6 +41,15 @@ struct sp804_timer __initdata arm_sp804_timer = { .width = 32, }; +struct sp804_timer __initdata hisi_sp804_timer = { + .load = HISI_TIMER_LOAD, + .value = HISI_TIMER_VALUE, + .ctrl = HISI_TIMER_CTRL, + .intclr = HISI_TIMER_INTCLR, + .timer_base = {HISI_TIMER_1_BASE, HISI_TIMER_2_BASE}, + .width = 64, +}; + static struct sp804_clkevt sp804_clkevt[NR_TIMERS]; static long __init sp804_get_clock_rate(struct clk *clk, const char *name) @@ -315,6 +336,12 @@ static int __init arm_sp804_of_init(struct device_node *np) } TIMER_OF_DECLARE(sp804, "arm,sp804", arm_sp804_of_init); +static int __init hisi_sp804_of_init(struct device_node *np) +{ + return sp804_of_init(np, &hisi_sp804_timer); +} +TIMER_OF_DECLARE(hisi_sp804, "hisilicon,sp804", hisi_sp804_of_init); + static int __init integrator_cp_of_init(struct device_node *np) { static int init_count = 0; -- cgit v1.2.3 From 549437a43f45ce70cf5012317633c635c43ba4f4 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Fri, 18 Sep 2020 21:22:36 +0800 Subject: clocksource/drivers/sp804: Enable Hisilicon sp804 timer 64bit mode A 100MHZ 32-bit timer will be wrapped up less than 43s. Although the kernel maintains a software high 32-bit count in the tick IRQ. But it's not applicable to the user mode APPs. Note: The kernel still uses the lower 32 bits of the timer. Signed-off-by: Zhen Lei Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200918132237.3552-9-thunder.leizhen@huawei.com --- drivers/clocksource/timer-sp.h | 6 ++++++ drivers/clocksource/timer-sp804.c | 11 +++++++++++ 2 files changed, 17 insertions(+) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-sp.h b/drivers/clocksource/timer-sp.h index 1ab75cbed0e0..811f840be0e5 100644 --- a/drivers/clocksource/timer-sp.h +++ b/drivers/clocksource/timer-sp.h @@ -33,12 +33,15 @@ struct sp804_timer { int load; + int load_h; int value; + int value_h; int ctrl; int intclr; int ris; int mis; int bgload; + int bgload_h; int timer_base[NR_TIMERS]; int width; }; @@ -46,12 +49,15 @@ struct sp804_timer { struct sp804_clkevt { void __iomem *base; void __iomem *load; + void __iomem *load_h; void __iomem *value; + void __iomem *value_h; void __iomem *ctrl; void __iomem *intclr; void __iomem *ris; void __iomem *mis; void __iomem *bgload; + void __iomem *bgload_h; unsigned long reload; int width; }; diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c index f0783d19522f..6e8ad4a4ea3c 100644 --- a/drivers/clocksource/timer-sp804.c +++ b/drivers/clocksource/timer-sp804.c @@ -24,12 +24,15 @@ #define HISI_TIMER_1_BASE 0x00 #define HISI_TIMER_2_BASE 0x40 #define HISI_TIMER_LOAD 0x00 +#define HISI_TIMER_LOAD_H 0x04 #define HISI_TIMER_VALUE 0x08 +#define HISI_TIMER_VALUE_H 0x0c #define HISI_TIMER_CTRL 0x10 #define HISI_TIMER_INTCLR 0x14 #define HISI_TIMER_RIS 0x18 #define HISI_TIMER_MIS 0x1c #define HISI_TIMER_BGLOAD 0x20 +#define HISI_TIMER_BGLOAD_H 0x24 struct sp804_timer __initdata arm_sp804_timer = { @@ -43,7 +46,9 @@ struct sp804_timer __initdata arm_sp804_timer = { struct sp804_timer __initdata hisi_sp804_timer = { .load = HISI_TIMER_LOAD, + .load_h = HISI_TIMER_LOAD_H, .value = HISI_TIMER_VALUE, + .value_h = HISI_TIMER_VALUE_H, .ctrl = HISI_TIMER_CTRL, .intclr = HISI_TIMER_INTCLR, .timer_base = {HISI_TIMER_1_BASE, HISI_TIMER_2_BASE}, @@ -129,6 +134,10 @@ int __init sp804_clocksource_and_sched_clock_init(void __iomem *base, writel(0, clkevt->ctrl); writel(0xffffffff, clkevt->load); writel(0xffffffff, clkevt->value); + if (clkevt->width == 64) { + writel(0xffffffff, clkevt->load_h); + writel(0xffffffff, clkevt->value_h); + } writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, clkevt->ctrl); @@ -245,7 +254,9 @@ static void __init sp804_clkevt_init(struct sp804_timer *timer, void __iomem *ba clkevt = &sp804_clkevt[i]; clkevt->base = timer_base; clkevt->load = timer_base + timer->load; + clkevt->load_h = timer_base + timer->load_h; clkevt->value = timer_base + timer->value; + clkevt->value_h = timer_base + timer->value_h; clkevt->ctrl = timer_base + timer->ctrl; clkevt->intclr = timer_base + timer->intclr; clkevt->width = timer->width; -- cgit v1.2.3 From 0d555b3ac49b40f94c270681b697d45dcae9faa6 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 27 Sep 2020 21:12:21 +0200 Subject: clocksource/drivers/mps2-timer: Use semicolons rather than commas to separate statements Replace commas with semicolons. What is done is essentially described by the following Coccinelle semantic patch (http://coccinelle.lip6.fr/): // @@ expression e1,e2; @@ e1 -, +; e2 ... when any // Signed-off-by: Julia Lawall Signed-off-by: Thomas Gleixner Cc: Daniel Lezcano Link: https://lore.kernel.org/r/1601233948-11629-12-git-send-email-Julia.Lawall@inria.fr --- drivers/clocksource/mps2-timer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/mps2-timer.c b/drivers/clocksource/mps2-timer.c index 2e64d984c83a..efe8cad8f2a5 100644 --- a/drivers/clocksource/mps2-timer.c +++ b/drivers/clocksource/mps2-timer.c @@ -149,9 +149,9 @@ static int __init mps2_clockevent_init(struct device_node *np) ce->clkevt.rating = 200; ce->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; ce->clkevt.cpumask = cpu_possible_mask; - ce->clkevt.set_state_shutdown = mps2_timer_shutdown, - ce->clkevt.set_state_periodic = mps2_timer_set_periodic, - ce->clkevt.set_state_oneshot = mps2_timer_shutdown, + ce->clkevt.set_state_shutdown = mps2_timer_shutdown; + ce->clkevt.set_state_periodic = mps2_timer_set_periodic; + ce->clkevt.set_state_oneshot = mps2_timer_shutdown; ce->clkevt.set_next_event = mps2_timer_set_next_event; /* Ensure timer is disabled */ -- cgit v1.2.3 From 1b80043ed21894eca888157145b955df02887995 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 27 Sep 2020 21:12:26 +0200 Subject: clocksource/drivers/armada-370-xp: Use semicolons rather than commas to separate statements Replace commas with semicolons. What is done is essentially described by the following Coccinelle semantic patch (http://coccinelle.lip6.fr/): // @@ expression e1,e2; @@ e1 -, +; e2 ... when any // Signed-off-by: Julia Lawall Signed-off-by: Thomas Gleixner Cc: Daniel Lezcano Link: https://lore.kernel.org/r/1601233948-11629-17-git-send-email-Julia.Lawall@inria.fr --- drivers/clocksource/timer-armada-370-xp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-armada-370-xp.c b/drivers/clocksource/timer-armada-370-xp.c index edf1a46269f1..e3acc3c631b7 100644 --- a/drivers/clocksource/timer-armada-370-xp.c +++ b/drivers/clocksource/timer-armada-370-xp.c @@ -181,12 +181,12 @@ static int armada_370_xp_timer_starting_cpu(unsigned int cpu) clr = TIMER0_25MHZ; local_timer_ctrl_clrset(clr, set); - evt->name = "armada_370_xp_per_cpu_tick", + evt->name = "armada_370_xp_per_cpu_tick"; evt->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC; - evt->shift = 32, - evt->rating = 300, - evt->set_next_event = armada_370_xp_clkevt_next_event, + evt->shift = 32; + evt->rating = 300; + evt->set_next_event = armada_370_xp_clkevt_next_event; evt->set_state_shutdown = armada_370_xp_clkevt_shutdown; evt->set_state_periodic = armada_370_xp_clkevt_set_periodic; evt->set_state_oneshot = armada_370_xp_clkevt_shutdown; -- cgit v1.2.3