From 890f423b266623e1cfb3a97b864f3e5039bdfbb9 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Mon, 6 Feb 2017 22:11:59 +0100 Subject: clocksource: sh_cmt: Compute rate before registration again With the upcoming NTP correction related rate adjustments to be implemented in the clockevents core, the latter needs to get informed about every rate change of a clockevent device made after its registration. Currently, sh_cmt violates this requirement in that it registers its clockevent device with a dummy rate and sets its final ->mult and ->shift values from its ->set_state_oneshot() and ->set_state_periodic() functions respectively. This patch moves the setting of the clockevent device's ->mult and ->shift values to before its registration. Note that there has been some back and forth regarding this question with respect to the clocksource also provided by this driver: commit f4d7c3565c16 ("clocksource: sh_cmt: compute mult and shift before registration") moves the rate determination from the clocksource's ->enable() function to before its registration. OTOH, the later commit 3593f5fe40a1 ("clocksource: sh_cmt: __clocksource_updatefreq_hz() update") basically reverts this, saying "Without this patch the old code uses clocksource_register() together with a hack that assumes a never changing clock rate." However, I checked all current sh_cmt users in arch/sh as well as in arch/arm/mach-shmobile carefully and right now, none of them changes any rate in any clock tree relevant to sh_cmt after their respective time_init(). Since all sh_cmt instances are created after time_init(), none of them should ever observe any clock rate changes. What's more, both, a clocksource as well as a clockevent device, can immediately get selected for use at their registration and thus, enabled at this point already. So it's probably safer to assume a "never changing clock rate" here. - Move the struct sh_cmt_channel's ->rate member to struct sh_cmt_device: it's a property of the underlying clock which is in turn specific to the sh_cmt_device. - Determine the ->rate value in sh_cmt_setup() at device probing rather than at first usage. - Set the clockevent device's ->mult and ->shift values right before its registration. - Although not strictly necessary for the upcoming clockevent core changes, set the clocksource's rate at its registration for consistency. Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- drivers/clocksource/sh_cmt.c | 45 ++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 28757edf6aca..e3bf3baa12cc 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -103,7 +103,6 @@ struct sh_cmt_channel { unsigned long match_value; unsigned long next_match_value; unsigned long max_match_value; - unsigned long rate; raw_spinlock_t lock; struct clock_event_device ced; struct clocksource cs; @@ -118,6 +117,7 @@ struct sh_cmt_device { void __iomem *mapbase; struct clk *clk; + unsigned long rate; raw_spinlock_t lock; /* Protect the shared start/stop register */ @@ -320,7 +320,7 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_channel *ch, int start) raw_spin_unlock_irqrestore(&ch->cmt->lock, flags); } -static int sh_cmt_enable(struct sh_cmt_channel *ch, unsigned long *rate) +static int sh_cmt_enable(struct sh_cmt_channel *ch) { int k, ret; @@ -340,11 +340,9 @@ static int sh_cmt_enable(struct sh_cmt_channel *ch, unsigned long *rate) /* configure channel, periodic mode and maximum timeout */ if (ch->cmt->info->width == 16) { - *rate = clk_get_rate(ch->cmt->clk) / 512; sh_cmt_write_cmcsr(ch, SH_CMT16_CMCSR_CMIE | SH_CMT16_CMCSR_CKS512); } else { - *rate = clk_get_rate(ch->cmt->clk) / 8; sh_cmt_write_cmcsr(ch, SH_CMT32_CMCSR_CMM | SH_CMT32_CMCSR_CMTOUT_IE | SH_CMT32_CMCSR_CMR_IRQ | @@ -572,7 +570,7 @@ static int sh_cmt_start(struct sh_cmt_channel *ch, unsigned long flag) raw_spin_lock_irqsave(&ch->lock, flags); if (!(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) - ret = sh_cmt_enable(ch, &ch->rate); + ret = sh_cmt_enable(ch); if (ret) goto out; @@ -640,10 +638,9 @@ static int sh_cmt_clocksource_enable(struct clocksource *cs) ch->total_cycles = 0; ret = sh_cmt_start(ch, FLAG_CLOCKSOURCE); - if (!ret) { - __clocksource_update_freq_hz(cs, ch->rate); + if (!ret) ch->cs_enabled = true; - } + return ret; } @@ -697,8 +694,7 @@ static int sh_cmt_register_clocksource(struct sh_cmt_channel *ch, dev_info(&ch->cmt->pdev->dev, "ch%u: used as clock source\n", ch->index); - /* Register with dummy 1 Hz value, gets updated in ->enable() */ - clocksource_register_hz(cs, 1); + clocksource_register_hz(cs, ch->cmt->rate); return 0; } @@ -709,19 +705,10 @@ static struct sh_cmt_channel *ced_to_sh_cmt(struct clock_event_device *ced) static void sh_cmt_clock_event_start(struct sh_cmt_channel *ch, int periodic) { - struct clock_event_device *ced = &ch->ced; - sh_cmt_start(ch, FLAG_CLOCKEVENT); - /* TODO: calculate good shift from rate and counter bit width */ - - ced->shift = 32; - ced->mult = div_sc(ch->rate, NSEC_PER_SEC, ced->shift); - ced->max_delta_ns = clockevent_delta2ns(ch->max_match_value, ced); - ced->min_delta_ns = clockevent_delta2ns(0x1f, ced); - if (periodic) - sh_cmt_set_next(ch, ((ch->rate + HZ/2) / HZ) - 1); + sh_cmt_set_next(ch, ((ch->cmt->rate + HZ/2) / HZ) - 1); else sh_cmt_set_next(ch, ch->max_match_value); } @@ -824,6 +811,12 @@ static int sh_cmt_register_clockevent(struct sh_cmt_channel *ch, ced->suspend = sh_cmt_clock_event_suspend; ced->resume = sh_cmt_clock_event_resume; + /* TODO: calculate good shift from rate and counter bit width */ + ced->shift = 32; + ced->mult = div_sc(ch->cmt->rate, NSEC_PER_SEC, ced->shift); + ced->max_delta_ns = clockevent_delta2ns(ch->max_match_value, ced); + ced->min_delta_ns = clockevent_delta2ns(0x1f, ced); + dev_info(&ch->cmt->pdev->dev, "ch%u: used for clock events\n", ch->index); clockevents_register_device(ced); @@ -996,6 +989,18 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev) if (ret < 0) goto err_clk_put; + /* Determine clock rate. */ + ret = clk_enable(cmt->clk); + if (ret < 0) + goto err_clk_unprepare; + + if (cmt->info->width == 16) + cmt->rate = clk_get_rate(cmt->clk) / 512; + else + cmt->rate = clk_get_rate(cmt->clk) / 8; + + clk_disable(cmt->clk); + /* Map the memory resource(s). */ ret = sh_cmt_map_memory(cmt); if (ret < 0) -- cgit v1.2.3 From c3c0a20df9fc55e2243a31f91a943b3e8ba61289 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Mon, 6 Feb 2017 22:12:00 +0100 Subject: clocksource: sh_tmu: Compute rate before registration again With the upcoming NTP correction related rate adjustments to be implemented in the clockevents core, the latter needs to get informed about every rate change of a clockevent device made after its registration. Currently, sh_tmu violates this requirement in that it registers its clockevent device with a dummy rate and sets its final rate through clockevents_config() called from its ->set_state_oneshot() and ->set_state_periodic() functions respectively. This patch moves the setting of the clockevent device's rate to its registration. Note that there has been some back and forth regarding this question with respect to the clocksource also provided by this driver: commit 66f49121ffa4 ("clocksource: sh_tmu: compute mult and shift before registration") moves the rate determination from the clocksource's ->enable() function to before its registration. OTOH, the later commit 0aeac458d9eb ("clocksource: sh_tmu: __clocksource_updatefreq_hz() update") basically reverts this, saying "Without this patch the old code uses clocksource_register() together with a hack that assumes a never changing clock rate." However, I checked all current sh_tmu users in arch/sh as well as in arch/arm/mach-shmobile carefully and right now, none of them changes any rate in any clock tree relevant to sh_tmu after their respective time_init(). Since all sh_tmu instances are created after time_init(), none of them should ever observe any clock rate changes. What's more, both, a clocksource as well as a clockevent device, can immediately get selected for use at their registration and thus, enabled at this point already. So it's probably safer to assume a "never changing clock rate" here. - Move the struct sh_tmu_channel's ->rate member to struct sh_tmu_device: it's a property of the underlying clock which is in turn specific to the sh_tmu_device. - Determine the ->rate value in sh_tmu_setup() at device probing rather than at first usage. - Set the clockevent device's rate at its registration. - Although not strictly necessary for the upcoming clockevent core changes, set the clocksource's rate at its registration for consistency. Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- drivers/clocksource/sh_tmu.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 1fbf2aadcfd4..31d881621e41 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -46,7 +46,6 @@ struct sh_tmu_channel { void __iomem *base; int irq; - unsigned long rate; unsigned long periodic; struct clock_event_device ced; struct clocksource cs; @@ -59,6 +58,7 @@ struct sh_tmu_device { void __iomem *mapbase; struct clk *clk; + unsigned long rate; enum sh_tmu_model model; @@ -165,7 +165,6 @@ static int __sh_tmu_enable(struct sh_tmu_channel *ch) sh_tmu_write(ch, TCNT, 0xffffffff); /* configure channel to parent clock / 4, irq off */ - ch->rate = clk_get_rate(ch->tmu->clk) / 4; sh_tmu_write(ch, TCR, TCR_TPSC_CLK4); /* enable channel */ @@ -271,10 +270,8 @@ static int sh_tmu_clocksource_enable(struct clocksource *cs) return 0; ret = sh_tmu_enable(ch); - if (!ret) { - __clocksource_update_freq_hz(cs, ch->rate); + if (!ret) ch->cs_enabled = true; - } return ret; } @@ -334,8 +331,7 @@ static int sh_tmu_register_clocksource(struct sh_tmu_channel *ch, dev_info(&ch->tmu->pdev->dev, "ch%u: used as clock source\n", ch->index); - /* Register with dummy 1 Hz value, gets updated in ->enable() */ - clocksource_register_hz(cs, 1); + clocksource_register_hz(cs, ch->tmu->rate); return 0; } @@ -346,14 +342,10 @@ static struct sh_tmu_channel *ced_to_sh_tmu(struct clock_event_device *ced) static void sh_tmu_clock_event_start(struct sh_tmu_channel *ch, int periodic) { - struct clock_event_device *ced = &ch->ced; - sh_tmu_enable(ch); - clockevents_config(ced, ch->rate); - if (periodic) { - ch->periodic = (ch->rate + HZ/2) / HZ; + ch->periodic = (ch->tmu->rate + HZ/2) / HZ; sh_tmu_set_next(ch, ch->periodic, 1); } } @@ -435,7 +427,7 @@ static void sh_tmu_register_clockevent(struct sh_tmu_channel *ch, dev_info(&ch->tmu->pdev->dev, "ch%u: used for clock events\n", ch->index); - clockevents_config_and_register(ced, 1, 0x300, 0xffffffff); + clockevents_config_and_register(ced, ch->tmu->rate, 0x300, 0xffffffff); ret = request_irq(ch->irq, sh_tmu_interrupt, IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING, @@ -561,6 +553,14 @@ static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev) if (ret < 0) goto err_clk_put; + /* Determine clock rate. */ + ret = clk_enable(tmu->clk); + if (ret < 0) + goto err_clk_unprepare; + + tmu->rate = clk_get_rate(tmu->clk) / 4; + clk_disable(tmu->clk); + /* Map the memory resource. */ ret = sh_tmu_map_memory(tmu); if (ret < 0) { -- cgit v1.2.3 From 3814ae092d36da04d5fbaf777c1564dc4ee68559 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Mon, 6 Feb 2017 22:12:01 +0100 Subject: clocksource: em_sti: Split clock prepare and enable steps Currently, the em_sti driver prepares and enables the needed clock in em_sti_enable(), potentially called through its clockevent device's ->set_state_oneshot(). However, the clk_prepare() step may sleep whereas tick_program_event() and thus, ->set_state_oneshot(), can be called in atomic context. Split the clk_prepare_enable() in em_sti_enable() into two steps: - prepare the clock at device probing via clk_prepare() - and enable it in em_sti_enable() via clk_enable(). Slightly reorder resource initialization in em_sti_probe() in order to facilitate error handling in later patches. Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- drivers/clocksource/em_sti.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/em_sti.c b/drivers/clocksource/em_sti.c index aff87df07449..6c0955a92f24 100644 --- a/drivers/clocksource/em_sti.c +++ b/drivers/clocksource/em_sti.c @@ -78,7 +78,7 @@ static int em_sti_enable(struct em_sti_priv *p) int ret; /* enable clock */ - ret = clk_prepare_enable(p->clk); + ret = clk_enable(p->clk); if (ret) { dev_err(&p->pdev->dev, "cannot enable clock\n"); return ret; @@ -107,7 +107,7 @@ static void em_sti_disable(struct em_sti_priv *p) em_sti_write(p, STI_INTENCLR, 3); /* stop clock */ - clk_disable_unprepare(p->clk); + clk_disable(p->clk); } static u64 em_sti_count(struct em_sti_priv *p) @@ -303,6 +303,7 @@ static int em_sti_probe(struct platform_device *pdev) struct em_sti_priv *p; struct resource *res; int irq; + int ret; p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); if (p == NULL) @@ -323,6 +324,13 @@ static int em_sti_probe(struct platform_device *pdev) if (IS_ERR(p->base)) return PTR_ERR(p->base); + if (devm_request_irq(&pdev->dev, irq, em_sti_interrupt, + IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING, + dev_name(&pdev->dev), p)) { + dev_err(&pdev->dev, "failed to request low IRQ\n"); + return -ENOENT; + } + /* get hold of clock */ p->clk = devm_clk_get(&pdev->dev, "sclk"); if (IS_ERR(p->clk)) { @@ -330,11 +338,10 @@ static int em_sti_probe(struct platform_device *pdev) return PTR_ERR(p->clk); } - if (devm_request_irq(&pdev->dev, irq, em_sti_interrupt, - IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING, - dev_name(&pdev->dev), p)) { - dev_err(&pdev->dev, "failed to request low IRQ\n"); - return -ENOENT; + ret = clk_prepare(p->clk); + if (ret < 0) { + dev_err(&pdev->dev, "cannot prepare clock\n"); + return ret; } raw_spin_lock_init(&p->lock); -- cgit v1.2.3 From 4e53aa2fde4124878fc6b2183d6e8ec46e12ceb0 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Mon, 6 Feb 2017 22:12:02 +0100 Subject: clocksource: em_sti: Compute rate before registration With the upcoming NTP correction related rate adjustments to be implemented in the clockevents core, the latter needs to get informed about every rate change of a clockevent device made after its registration. Currently, em_sti violates this requirement in that it registers its clockevent device with a dummy rate and sets its final rate through clockevents_config() called from its ->set_state_oneshot(). This patch moves the setting of the clockevent device's rate to its registration. I checked all current em_sti users in arch/arm/mach-shmobile and right now, none of them changes any rate in any clock tree relevant to em_sti after their respective time_init(). Since all em_sti instances are created after time_init(), none of them should ever observe any clock rate changes. - Determine the ->rate value in em_sti_probe() at device probing rather than at first usage. - Set the clockevent device's rate at its registration. - Although not strictly necessary for the upcoming clockevent core changes, set the clocksource's rate at its registration for consistency. Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- drivers/clocksource/em_sti.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/em_sti.c b/drivers/clocksource/em_sti.c index 6c0955a92f24..bc48cbf6a795 100644 --- a/drivers/clocksource/em_sti.c +++ b/drivers/clocksource/em_sti.c @@ -84,9 +84,6 @@ static int em_sti_enable(struct em_sti_priv *p) return ret; } - /* configure channel, periodic mode and maximum timeout */ - p->rate = clk_get_rate(p->clk); - /* reset the counter */ em_sti_write(p, STI_SET_H, 0x40000000); em_sti_write(p, STI_SET_L, 0x00000000); @@ -205,13 +202,9 @@ static u64 em_sti_clocksource_read(struct clocksource *cs) static int em_sti_clocksource_enable(struct clocksource *cs) { - int ret; struct em_sti_priv *p = cs_to_em_sti(cs); - ret = em_sti_start(p, USER_CLOCKSOURCE); - if (!ret) - __clocksource_update_freq_hz(cs, p->rate); - return ret; + return em_sti_start(p, USER_CLOCKSOURCE); } static void em_sti_clocksource_disable(struct clocksource *cs) @@ -240,8 +233,7 @@ static int em_sti_register_clocksource(struct em_sti_priv *p) dev_info(&p->pdev->dev, "used as clock source\n"); - /* Register with dummy 1 Hz value, gets updated in ->enable() */ - clocksource_register_hz(cs, 1); + clocksource_register_hz(cs, p->rate); return 0; } @@ -263,7 +255,6 @@ static int em_sti_clock_event_set_oneshot(struct clock_event_device *ced) dev_info(&p->pdev->dev, "used for oneshot clock events\n"); em_sti_start(p, USER_CLOCKEVENT); - clockevents_config(&p->ced, p->rate); return 0; } @@ -294,8 +285,7 @@ static void em_sti_register_clockevent(struct em_sti_priv *p) dev_info(&p->pdev->dev, "used for clock events\n"); - /* Register with dummy 1 Hz value, gets updated in ->set_state_oneshot() */ - clockevents_config_and_register(ced, 1, 2, 0xffffffff); + clockevents_config_and_register(ced, p->rate, 2, 0xffffffff); } static int em_sti_probe(struct platform_device *pdev) @@ -344,6 +334,15 @@ static int em_sti_probe(struct platform_device *pdev) return ret; } + ret = clk_enable(p->clk); + if (ret < 0) { + dev_err(&p->pdev->dev, "cannot enable clock\n"); + clk_unprepare(p->clk); + return ret; + } + p->rate = clk_get_rate(p->clk); + clk_disable(p->clk); + raw_spin_lock_init(&p->lock); em_sti_register_clockevent(p); em_sti_register_clocksource(p); -- cgit v1.2.3 From a17e0178fa2898bd8c4ccaaefa83c729759a361c Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Mon, 6 Feb 2017 22:12:03 +0100 Subject: clocksource: h8300_timer8: Don't reset rate in ->set_state_oneshot() With the upcoming NTP correction related rate adjustments to be implemented in the clockevents core, the latter needs to get informed about every rate change of a clockevent device made after its registration. Currently, h8300_timer8 violates this requirement in that it registers its clockevent device with the correct rate, but resets its ->mult and ->rate values in timer8_clock_event_start(), called from its ->set_state_oneshot() function. It seems like commit 4633f4cac85a ("clocksource/drivers/h8300: Cleanup startup and remove module code."), which introduced the rate initialization at registration, missed to remove the manual setting of ->mult and ->shift from timer8_clock_event_start(). Purge the setting of ->mult, ->shift, ->min_delta_ns and ->max_delta_ns from timer8_clock_event_start(). Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- drivers/clocksource/h8300_timer8.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c index 546bb180f5a4..804c489531d6 100644 --- a/drivers/clocksource/h8300_timer8.c +++ b/drivers/clocksource/h8300_timer8.c @@ -101,15 +101,7 @@ static inline struct timer8_priv *ced_to_priv(struct clock_event_device *ced) static void timer8_clock_event_start(struct timer8_priv *p, unsigned long delta) { - struct clock_event_device *ced = &p->ced; - timer8_start(p); - - ced->shift = 32; - ced->mult = div_sc(p->rate, NSEC_PER_SEC, ced->shift); - ced->max_delta_ns = clockevent_delta2ns(0xffff, ced); - ced->min_delta_ns = clockevent_delta2ns(0x0001, ced); - timer8_set_next(p, delta); } -- cgit v1.2.3 From 651bb2e9dca6e6dbad3fba5f6e6086a23575b8b5 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Thu, 19 Jan 2017 17:20:59 +0000 Subject: arm64: arch_timer: Add infrastructure for multiple erratum detection methods We're currently stuck with DT when it comes to handling errata, which is pretty restrictive. In order to make things more flexible, let's introduce an infrastructure that could support alternative discovery methods. No change in functionality. Acked-by: Thomas Gleixner Reviewed-by: Hanjun Guo Signed-off-by: Marc Zyngier --- drivers/clocksource/arm_arch_timer.c | 83 +++++++++++++++++++++++++++++++----- 1 file changed, 72 insertions(+), 11 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 7a8a4117f123..5c5c2af74ad9 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -182,7 +182,9 @@ EXPORT_SYMBOL_GPL(arch_timer_read_ool_enabled); static const struct arch_timer_erratum_workaround ool_workarounds[] = { #ifdef CONFIG_FSL_ERRATUM_A008585 { + .match_type = ate_match_dt, .id = "fsl,erratum-a008585", + .desc = "Freescale erratum a005858", .read_cntp_tval_el0 = fsl_a008585_read_cntp_tval_el0, .read_cntv_tval_el0 = fsl_a008585_read_cntv_tval_el0, .read_cntvct_el0 = fsl_a008585_read_cntvct_el0, @@ -190,13 +192,81 @@ static const struct arch_timer_erratum_workaround ool_workarounds[] = { #endif #ifdef CONFIG_HISILICON_ERRATUM_161010101 { + .match_type = ate_match_dt, .id = "hisilicon,erratum-161010101", + .desc = "HiSilicon erratum 161010101", .read_cntp_tval_el0 = hisi_161010101_read_cntp_tval_el0, .read_cntv_tval_el0 = hisi_161010101_read_cntv_tval_el0, .read_cntvct_el0 = hisi_161010101_read_cntvct_el0, }, #endif }; + +typedef bool (*ate_match_fn_t)(const struct arch_timer_erratum_workaround *, + const void *); + +static +bool arch_timer_check_dt_erratum(const struct arch_timer_erratum_workaround *wa, + const void *arg) +{ + const struct device_node *np = arg; + + return of_property_read_bool(np, wa->id); +} + +static const struct arch_timer_erratum_workaround * +arch_timer_iterate_errata(enum arch_timer_erratum_match_type type, + ate_match_fn_t match_fn, + void *arg) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ool_workarounds); i++) { + if (ool_workarounds[i].match_type != type) + continue; + + if (match_fn(&ool_workarounds[i], arg)) + return &ool_workarounds[i]; + } + + return NULL; +} + +static +void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa) +{ + timer_unstable_counter_workaround = wa; + static_branch_enable(&arch_timer_read_ool_enabled); +} + +static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type type, + void *arg) +{ + const struct arch_timer_erratum_workaround *wa; + ate_match_fn_t match_fn = NULL; + + if (static_branch_unlikely(&arch_timer_read_ool_enabled)) + return; + + switch (type) { + case ate_match_dt: + match_fn = arch_timer_check_dt_erratum; + break; + default: + WARN_ON(1); + return; + } + + wa = arch_timer_iterate_errata(type, match_fn, arg); + if (!wa) + return; + + arch_timer_enable_workaround(wa); + pr_info("Enabling global workaround for %s\n", wa->desc); +} + +#else +#define arch_timer_check_ool_workaround(t,a) do { } while(0) #endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */ static __always_inline @@ -960,17 +1030,8 @@ static int __init arch_timer_of_init(struct device_node *np) arch_timer_c3stop = !of_property_read_bool(np, "always-on"); -#ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND - for (i = 0; i < ARRAY_SIZE(ool_workarounds); i++) { - if (of_property_read_bool(np, ool_workarounds[i].id)) { - timer_unstable_counter_workaround = &ool_workarounds[i]; - static_branch_enable(&arch_timer_read_ool_enabled); - pr_info("arch_timer: Enabling workaround for %s\n", - timer_unstable_counter_workaround->id); - break; - } - } -#endif + /* Check for globally applicable workarounds */ + arch_timer_check_ool_workaround(ate_match_dt, np); /* * If we cannot rely on firmware initializing the timer registers then -- cgit v1.2.3 From 0064030c6fd4ca6cfab42de037b2a89445beeead Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Mon, 20 Mar 2017 16:47:59 +0000 Subject: arm64: arch_timer: Add erratum handler for CPU-specific capability Should we ever have a workaround for an erratum that is detected using a capability and affecting a particular CPU, it'd be nice to have a way to probe them directly. Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier --- drivers/clocksource/arm_arch_timer.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 5c5c2af74ad9..532e47fa43b3 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -214,6 +214,13 @@ bool arch_timer_check_dt_erratum(const struct arch_timer_erratum_workaround *wa, return of_property_read_bool(np, wa->id); } +static +bool arch_timer_check_local_cap_erratum(const struct arch_timer_erratum_workaround *wa, + const void *arg) +{ + return this_cpu_has_cap((uintptr_t)wa->id); +} + static const struct arch_timer_erratum_workaround * arch_timer_iterate_errata(enum arch_timer_erratum_match_type type, ate_match_fn_t match_fn, @@ -244,14 +251,16 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t { const struct arch_timer_erratum_workaround *wa; ate_match_fn_t match_fn = NULL; - - if (static_branch_unlikely(&arch_timer_read_ool_enabled)) - return; + bool local = false; switch (type) { case ate_match_dt: match_fn = arch_timer_check_dt_erratum; break; + case ate_match_local_cap_id: + match_fn = arch_timer_check_local_cap_erratum; + local = true; + break; default: WARN_ON(1); return; @@ -261,8 +270,17 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t if (!wa) return; + if (needs_unstable_timer_counter_workaround()) { + if (wa != timer_unstable_counter_workaround) + pr_warn("Can't enable workaround for %s (clashes with %s\n)", + wa->desc, + timer_unstable_counter_workaround->desc); + return; + } + arch_timer_enable_workaround(wa); - pr_info("Enabling global workaround for %s\n", wa->desc); + pr_info("Enabling %s workaround for %s\n", + local ? "local" : "global", wa->desc); } #else @@ -522,6 +540,8 @@ static void __arch_timer_setup(unsigned type, BUG(); } + arch_timer_check_ool_workaround(ate_match_local_cap_id, NULL); + erratum_workaround_set_sne(clk); } else { clk->features |= CLOCK_EVT_FEAT_DYNIRQ; -- cgit v1.2.3 From f4e00a1a55c7f9b08a48b57088ac5d044d5523d5 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 20 Jan 2017 18:28:32 +0000 Subject: arm64: arch_timer: Move arch_timer_reg_read/write around As we're about to move things around, let's start with the low level read/write functions. This allows us to use these functions in the errata handling code without having to use forward declaration of static functions. Acked-by: Thomas Gleixner Acked-by: Mark Rutland Acked-by: Daniel Lezcano Signed-off-by: Marc Zyngier --- drivers/clocksource/arm_arch_timer.c | 124 +++++++++++++++++------------------ 1 file changed, 62 insertions(+), 62 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 532e47fa43b3..b5c83cc2a67a 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -96,6 +96,68 @@ early_param("clocksource.arm_arch_timer.evtstrm", early_evtstrm_cfg); * Architected system timer support. */ +static __always_inline +void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val, + struct clock_event_device *clk) +{ + if (access == ARCH_TIMER_MEM_PHYS_ACCESS) { + struct arch_timer *timer = to_arch_timer(clk); + switch (reg) { + case ARCH_TIMER_REG_CTRL: + writel_relaxed(val, timer->base + CNTP_CTL); + break; + case ARCH_TIMER_REG_TVAL: + writel_relaxed(val, timer->base + CNTP_TVAL); + break; + } + } else if (access == ARCH_TIMER_MEM_VIRT_ACCESS) { + struct arch_timer *timer = to_arch_timer(clk); + switch (reg) { + case ARCH_TIMER_REG_CTRL: + writel_relaxed(val, timer->base + CNTV_CTL); + break; + case ARCH_TIMER_REG_TVAL: + writel_relaxed(val, timer->base + CNTV_TVAL); + break; + } + } else { + arch_timer_reg_write_cp15(access, reg, val); + } +} + +static __always_inline +u32 arch_timer_reg_read(int access, enum arch_timer_reg reg, + struct clock_event_device *clk) +{ + u32 val; + + if (access == ARCH_TIMER_MEM_PHYS_ACCESS) { + struct arch_timer *timer = to_arch_timer(clk); + switch (reg) { + case ARCH_TIMER_REG_CTRL: + val = readl_relaxed(timer->base + CNTP_CTL); + break; + case ARCH_TIMER_REG_TVAL: + val = readl_relaxed(timer->base + CNTP_TVAL); + break; + } + } else if (access == ARCH_TIMER_MEM_VIRT_ACCESS) { + struct arch_timer *timer = to_arch_timer(clk); + switch (reg) { + case ARCH_TIMER_REG_CTRL: + val = readl_relaxed(timer->base + CNTV_CTL); + break; + case ARCH_TIMER_REG_TVAL: + val = readl_relaxed(timer->base + CNTV_TVAL); + break; + } + } else { + val = arch_timer_reg_read_cp15(access, reg); + } + + return val; +} + #ifdef CONFIG_FSL_ERRATUM_A008585 /* * The number of retries is an arbitrary value well beyond the highest number @@ -287,68 +349,6 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t #define arch_timer_check_ool_workaround(t,a) do { } while(0) #endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */ -static __always_inline -void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val, - struct clock_event_device *clk) -{ - if (access == ARCH_TIMER_MEM_PHYS_ACCESS) { - struct arch_timer *timer = to_arch_timer(clk); - switch (reg) { - case ARCH_TIMER_REG_CTRL: - writel_relaxed(val, timer->base + CNTP_CTL); - break; - case ARCH_TIMER_REG_TVAL: - writel_relaxed(val, timer->base + CNTP_TVAL); - break; - } - } else if (access == ARCH_TIMER_MEM_VIRT_ACCESS) { - struct arch_timer *timer = to_arch_timer(clk); - switch (reg) { - case ARCH_TIMER_REG_CTRL: - writel_relaxed(val, timer->base + CNTV_CTL); - break; - case ARCH_TIMER_REG_TVAL: - writel_relaxed(val, timer->base + CNTV_TVAL); - break; - } - } else { - arch_timer_reg_write_cp15(access, reg, val); - } -} - -static __always_inline -u32 arch_timer_reg_read(int access, enum arch_timer_reg reg, - struct clock_event_device *clk) -{ - u32 val; - - if (access == ARCH_TIMER_MEM_PHYS_ACCESS) { - struct arch_timer *timer = to_arch_timer(clk); - switch (reg) { - case ARCH_TIMER_REG_CTRL: - val = readl_relaxed(timer->base + CNTP_CTL); - break; - case ARCH_TIMER_REG_TVAL: - val = readl_relaxed(timer->base + CNTP_TVAL); - break; - } - } else if (access == ARCH_TIMER_MEM_VIRT_ACCESS) { - struct arch_timer *timer = to_arch_timer(clk); - switch (reg) { - case ARCH_TIMER_REG_CTRL: - val = readl_relaxed(timer->base + CNTV_CTL); - break; - case ARCH_TIMER_REG_TVAL: - val = readl_relaxed(timer->base + CNTV_TVAL); - break; - } - } else { - val = arch_timer_reg_read_cp15(access, reg); - } - - return val; -} - static __always_inline irqreturn_t timer_handler(const int access, struct clock_event_device *evt) { -- cgit v1.2.3 From 8328089f0aeba39173eee3fc109b5c77efd64747 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 27 Jan 2017 10:27:09 +0000 Subject: arm64: arch_timer: Get rid of erratum_workaround_set_sne Let's move the handling of workarounds affecting set_next_event to the affected function, instead of overriding the pointers as an afterthough. Yes, this is an extra indirection on the erratum handling path, but the HW is busted anyway. This will allow for some more flexibility later. Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier --- drivers/clocksource/arm_arch_timer.c | 90 ++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 49 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index b5c83cc2a67a..2c02e25d1475 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -241,6 +241,38 @@ EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround); DEFINE_STATIC_KEY_FALSE(arch_timer_read_ool_enabled); EXPORT_SYMBOL_GPL(arch_timer_read_ool_enabled); +static void erratum_set_next_event_tval_generic(const int access, unsigned long evt, + struct clock_event_device *clk) +{ + unsigned long ctrl; + u64 cval = evt + arch_counter_get_cntvct(); + + ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk); + ctrl |= ARCH_TIMER_CTRL_ENABLE; + ctrl &= ~ARCH_TIMER_CTRL_IT_MASK; + + if (access == ARCH_TIMER_PHYS_ACCESS) + write_sysreg(cval, cntp_cval_el0); + else + write_sysreg(cval, cntv_cval_el0); + + arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk); +} + +static int erratum_set_next_event_tval_virt(unsigned long evt, + struct clock_event_device *clk) +{ + erratum_set_next_event_tval_generic(ARCH_TIMER_VIRT_ACCESS, evt, clk); + return 0; +} + +static int erratum_set_next_event_tval_phys(unsigned long evt, + struct clock_event_device *clk) +{ + erratum_set_next_event_tval_generic(ARCH_TIMER_PHYS_ACCESS, evt, clk); + return 0; +} + static const struct arch_timer_erratum_workaround ool_workarounds[] = { #ifdef CONFIG_FSL_ERRATUM_A008585 { @@ -347,6 +379,9 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t #else #define arch_timer_check_ool_workaround(t,a) do { } while(0) +#define erratum_set_next_event_tval_virt(...) ({BUG(); 0;}) +#define erratum_set_next_event_tval_phys(...) ({BUG(); 0;}) +#define needs_unstable_timer_counter_workaround() ({false;}) #endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */ static __always_inline irqreturn_t timer_handler(const int access, @@ -436,43 +471,12 @@ static __always_inline void set_next_event(const int access, unsigned long evt, arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk); } -#ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND -static __always_inline void erratum_set_next_event_generic(const int access, - unsigned long evt, struct clock_event_device *clk) -{ - unsigned long ctrl; - u64 cval = evt + arch_counter_get_cntvct(); - - ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk); - ctrl |= ARCH_TIMER_CTRL_ENABLE; - ctrl &= ~ARCH_TIMER_CTRL_IT_MASK; - - if (access == ARCH_TIMER_PHYS_ACCESS) - write_sysreg(cval, cntp_cval_el0); - else if (access == ARCH_TIMER_VIRT_ACCESS) - write_sysreg(cval, cntv_cval_el0); - - arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk); -} - -static int erratum_set_next_event_virt(unsigned long evt, - struct clock_event_device *clk) -{ - erratum_set_next_event_generic(ARCH_TIMER_VIRT_ACCESS, evt, clk); - return 0; -} - -static int erratum_set_next_event_phys(unsigned long evt, - struct clock_event_device *clk) -{ - erratum_set_next_event_generic(ARCH_TIMER_PHYS_ACCESS, evt, clk); - return 0; -} -#endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */ - static int arch_timer_set_next_event_virt(unsigned long evt, struct clock_event_device *clk) { + if (needs_unstable_timer_counter_workaround()) + return erratum_set_next_event_tval_virt(evt, clk); + set_next_event(ARCH_TIMER_VIRT_ACCESS, evt, clk); return 0; } @@ -480,6 +484,9 @@ static int arch_timer_set_next_event_virt(unsigned long evt, static int arch_timer_set_next_event_phys(unsigned long evt, struct clock_event_device *clk) { + if (needs_unstable_timer_counter_workaround()) + return erratum_set_next_event_tval_phys(evt, clk); + set_next_event(ARCH_TIMER_PHYS_ACCESS, evt, clk); return 0; } @@ -498,19 +505,6 @@ static int arch_timer_set_next_event_phys_mem(unsigned long evt, return 0; } -static void erratum_workaround_set_sne(struct clock_event_device *clk) -{ -#ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND - if (!static_branch_unlikely(&arch_timer_read_ool_enabled)) - return; - - if (arch_timer_uses_ppi == VIRT_PPI) - clk->set_next_event = erratum_set_next_event_virt; - else - clk->set_next_event = erratum_set_next_event_phys; -#endif -} - static void __arch_timer_setup(unsigned type, struct clock_event_device *clk) { @@ -541,8 +535,6 @@ static void __arch_timer_setup(unsigned type, } arch_timer_check_ool_workaround(ate_match_local_cap_id, NULL); - - erratum_workaround_set_sne(clk); } else { clk->features |= CLOCK_EVT_FEAT_DYNIRQ; clk->name = "arch_mem_timer"; -- cgit v1.2.3 From 01d3e3ff26080040cb02ec4989a0da36d069f1e9 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 27 Jan 2017 10:27:09 +0000 Subject: arm64: arch_timer: Rework the set_next_event workarounds The way we work around errata affecting set_next_event is not very nice, at it imposes this workaround on errata that do not need it. Add new workaround hooks and let the existing workarounds use them. Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier --- drivers/clocksource/arm_arch_timer.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 2c02e25d1475..a0c9ee80147e 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -282,6 +282,8 @@ static const struct arch_timer_erratum_workaround ool_workarounds[] = { .read_cntp_tval_el0 = fsl_a008585_read_cntp_tval_el0, .read_cntv_tval_el0 = fsl_a008585_read_cntv_tval_el0, .read_cntvct_el0 = fsl_a008585_read_cntvct_el0, + .set_next_event_phys = erratum_set_next_event_tval_phys, + .set_next_event_virt = erratum_set_next_event_tval_virt, }, #endif #ifdef CONFIG_HISILICON_ERRATUM_161010101 @@ -292,6 +294,8 @@ static const struct arch_timer_erratum_workaround ool_workarounds[] = { .read_cntp_tval_el0 = hisi_161010101_read_cntp_tval_el0, .read_cntv_tval_el0 = hisi_161010101_read_cntv_tval_el0, .read_cntvct_el0 = hisi_161010101_read_cntvct_el0, + .set_next_event_phys = erratum_set_next_event_tval_phys, + .set_next_event_virt = erratum_set_next_event_tval_virt, }, #endif }; @@ -377,11 +381,24 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t local ? "local" : "global", wa->desc); } +#define erratum_handler(fn, r, ...) \ +({ \ + bool __val; \ + if (needs_unstable_timer_counter_workaround() && \ + timer_unstable_counter_workaround->fn) { \ + r = timer_unstable_counter_workaround->fn(__VA_ARGS__); \ + __val = true; \ + } else { \ + __val = false; \ + } \ + __val; \ +}) + #else #define arch_timer_check_ool_workaround(t,a) do { } while(0) #define erratum_set_next_event_tval_virt(...) ({BUG(); 0;}) #define erratum_set_next_event_tval_phys(...) ({BUG(); 0;}) -#define needs_unstable_timer_counter_workaround() ({false;}) +#define erratum_handler(fn, r, ...) ({false;}) #endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */ static __always_inline irqreturn_t timer_handler(const int access, @@ -474,8 +491,10 @@ static __always_inline void set_next_event(const int access, unsigned long evt, static int arch_timer_set_next_event_virt(unsigned long evt, struct clock_event_device *clk) { - if (needs_unstable_timer_counter_workaround()) - return erratum_set_next_event_tval_virt(evt, clk); + int ret; + + if (erratum_handler(set_next_event_virt, ret, evt, clk)) + return ret; set_next_event(ARCH_TIMER_VIRT_ACCESS, evt, clk); return 0; @@ -484,8 +503,10 @@ static int arch_timer_set_next_event_virt(unsigned long evt, static int arch_timer_set_next_event_phys(unsigned long evt, struct clock_event_device *clk) { - if (needs_unstable_timer_counter_workaround()) - return erratum_set_next_event_tval_phys(evt, clk); + int ret; + + if (erratum_handler(set_next_event_phys, ret, evt, clk)) + return ret; set_next_event(ARCH_TIMER_PHYS_ACCESS, evt, clk); return 0; -- cgit v1.2.3 From 6acc71ccac7187fc0ef85f10bd09c2058f21fab5 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Mon, 20 Feb 2017 18:34:48 +0000 Subject: arm64: arch_timer: Allows a CPU-specific erratum to only affect a subset of CPUs Instead of applying a CPU-specific workaround to all CPUs in the system, allow it to only affect a subset of them (typical big-little case). This is done by turning the erratum pointer into a per-CPU variable. Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier --- drivers/clocksource/arm_arch_timer.c | 42 +++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 12 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index a0c9ee80147e..4551587bcb44 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -235,7 +235,8 @@ static u64 notrace hisi_161010101_read_cntvct_el0(void) #endif #ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND -const struct arch_timer_erratum_workaround *timer_unstable_counter_workaround = NULL; +DEFINE_PER_CPU(const struct arch_timer_erratum_workaround *, + timer_unstable_counter_workaround); EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround); DEFINE_STATIC_KEY_FALSE(arch_timer_read_ool_enabled); @@ -338,9 +339,18 @@ arch_timer_iterate_errata(enum arch_timer_erratum_match_type type, } static -void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa) +void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa, + bool local) { - timer_unstable_counter_workaround = wa; + int i; + + if (local) { + __this_cpu_write(timer_unstable_counter_workaround, wa); + } else { + for_each_possible_cpu(i) + per_cpu(timer_unstable_counter_workaround, i) = wa; + } + static_branch_enable(&arch_timer_read_ool_enabled); } @@ -369,14 +379,17 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t return; if (needs_unstable_timer_counter_workaround()) { - if (wa != timer_unstable_counter_workaround) + const struct arch_timer_erratum_workaround *__wa; + __wa = __this_cpu_read(timer_unstable_counter_workaround); + if (__wa && wa != __wa) pr_warn("Can't enable workaround for %s (clashes with %s\n)", - wa->desc, - timer_unstable_counter_workaround->desc); - return; + wa->desc, __wa->desc); + + if (__wa) + return; } - arch_timer_enable_workaround(wa); + arch_timer_enable_workaround(wa, local); pr_info("Enabling %s workaround for %s\n", local ? "local" : "global", wa->desc); } @@ -384,10 +397,15 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t #define erratum_handler(fn, r, ...) \ ({ \ bool __val; \ - if (needs_unstable_timer_counter_workaround() && \ - timer_unstable_counter_workaround->fn) { \ - r = timer_unstable_counter_workaround->fn(__VA_ARGS__); \ - __val = true; \ + if (needs_unstable_timer_counter_workaround()) { \ + const struct arch_timer_erratum_workaround *__wa; \ + __wa = __this_cpu_read(timer_unstable_counter_workaround); \ + if (__wa && __wa->fn) { \ + r = __wa->fn(__VA_ARGS__); \ + __val = true; \ + } else { \ + __val = false; \ + } \ } else { \ __val = false; \ } \ -- cgit v1.2.3 From 992dd16f6528bd3f378dbcda43688d374be02943 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 1 Feb 2017 11:53:46 +0000 Subject: arm64: arch_timer: Move clocksource_counter and co around In order to access clocksource_counter from the errata handling code, move it (together with the related structures and functions) towards the top of the file. Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier --- drivers/clocksource/arm_arch_timer.c | 62 ++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 31 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 4551587bcb44..395f5d95a737 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -158,6 +158,37 @@ u32 arch_timer_reg_read(int access, enum arch_timer_reg reg, return val; } +/* + * Default to cp15 based access because arm64 uses this function for + * sched_clock() before DT is probed and the cp15 method is guaranteed + * to exist on arm64. arm doesn't use this before DT is probed so even + * if we don't have the cp15 accessors we won't have a problem. + */ +u64 (*arch_timer_read_counter)(void) = arch_counter_get_cntvct; + +static u64 arch_counter_read(struct clocksource *cs) +{ + return arch_timer_read_counter(); +} + +static u64 arch_counter_read_cc(const struct cyclecounter *cc) +{ + return arch_timer_read_counter(); +} + +static struct clocksource clocksource_counter = { + .name = "arch_sys_counter", + .rating = 400, + .read = arch_counter_read, + .mask = CLOCKSOURCE_MASK(56), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static struct cyclecounter cyclecounter __ro_after_init = { + .read = arch_counter_read_cc, + .mask = CLOCKSOURCE_MASK(56), +}; + #ifdef CONFIG_FSL_ERRATUM_A008585 /* * The number of retries is an arbitrary value well beyond the highest number @@ -742,37 +773,6 @@ static u64 arch_counter_get_cntvct_mem(void) return ((u64) vct_hi << 32) | vct_lo; } -/* - * Default to cp15 based access because arm64 uses this function for - * sched_clock() before DT is probed and the cp15 method is guaranteed - * to exist on arm64. arm doesn't use this before DT is probed so even - * if we don't have the cp15 accessors we won't have a problem. - */ -u64 (*arch_timer_read_counter)(void) = arch_counter_get_cntvct; - -static u64 arch_counter_read(struct clocksource *cs) -{ - return arch_timer_read_counter(); -} - -static u64 arch_counter_read_cc(const struct cyclecounter *cc) -{ - return arch_timer_read_counter(); -} - -static struct clocksource clocksource_counter = { - .name = "arch_sys_counter", - .rating = 400, - .read = arch_counter_read, - .mask = CLOCKSOURCE_MASK(56), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static struct cyclecounter cyclecounter __ro_after_init = { - .read = arch_counter_read_cc, - .mask = CLOCKSOURCE_MASK(56), -}; - static struct arch_timer_kvm_info arch_timer_kvm_info; struct arch_timer_kvm_info *arch_timer_get_kvm_info(void) -- cgit v1.2.3 From bee67c53a990452c4f3c7a0e9cebfecb5acfbde3 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 4 Apr 2017 17:05:16 +0100 Subject: arm64: arch_timer: Save cntkctl_el1 as a per-cpu variable As we're about to allow per CPU cntkctl_el1 configuration, we cannot rely on the register value to be common when performing power management. Let's turn saved_cntkctl into a per-cpu variable. Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier --- drivers/clocksource/arm_arch_timer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 395f5d95a737..5c114da0ed71 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -839,14 +839,14 @@ static int arch_timer_dying_cpu(unsigned int cpu) } #ifdef CONFIG_CPU_PM -static unsigned int saved_cntkctl; +static DEFINE_PER_CPU(unsigned long, saved_cntkctl); static int arch_timer_cpu_pm_notify(struct notifier_block *self, unsigned long action, void *hcpu) { if (action == CPU_PM_ENTER) - saved_cntkctl = arch_timer_get_cntkctl(); + __this_cpu_write(saved_cntkctl, arch_timer_get_cntkctl()); else if (action == CPU_PM_ENTER_FAILED || action == CPU_PM_EXIT) - arch_timer_set_cntkctl(saved_cntkctl); + arch_timer_set_cntkctl(__this_cpu_read(saved_cntkctl)); return NOTIFY_OK; } -- cgit v1.2.3 From a86bd139f2ae02f960caeb0c1dd5f871d3e087cd Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 1 Feb 2017 12:07:15 +0000 Subject: arm64: arch_timer: Enable CNTVCT_EL0 trap if workaround is enabled Userspace being allowed to use read CNTVCT_EL0 anytime (and not only in the VDSO), we need to enable trapping whenever a cntvct workaround is enabled on a given CPU. Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier --- drivers/clocksource/arm_arch_timer.c | 45 +++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 13 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 5c114da0ed71..f8adea258cf0 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -83,6 +83,7 @@ static enum ppi_nr arch_timer_uses_ppi = VIRT_PPI; static bool arch_timer_c3stop; static bool arch_timer_mem_use_virtual; static bool arch_counter_suspend_stop; +static bool vdso_default = true; static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM); @@ -383,6 +384,17 @@ void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa } static_branch_enable(&arch_timer_read_ool_enabled); + + /* + * Don't use the vdso fastpath if errata require using the + * out-of-line counter accessor. We may change our mind pretty + * late in the game (with a per-CPU erratum, for example), so + * change both the default value and the vdso itself. + */ + if (wa->read_cntvct_el0) { + clocksource_counter.archdata.vdso_direct = false; + vdso_default = false; + } } static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type type, @@ -443,11 +455,19 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t __val; \ }) +static bool arch_timer_this_cpu_has_cntvct_wa(void) +{ + const struct arch_timer_erratum_workaround *wa; + + wa = __this_cpu_read(timer_unstable_counter_workaround); + return wa && wa->read_cntvct_el0; +} #else #define arch_timer_check_ool_workaround(t,a) do { } while(0) #define erratum_set_next_event_tval_virt(...) ({BUG(); 0;}) #define erratum_set_next_event_tval_phys(...) ({BUG(); 0;}) #define erratum_handler(fn, r, ...) ({false;}) +#define arch_timer_this_cpu_has_cntvct_wa() ({false;}) #endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */ static __always_inline irqreturn_t timer_handler(const int access, @@ -660,15 +680,23 @@ static void arch_counter_set_user_access(void) { u32 cntkctl = arch_timer_get_cntkctl(); - /* Disable user access to the timers and the physical counter */ + /* Disable user access to the timers and both counters */ /* Also disable virtual event stream */ cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN | ARCH_TIMER_USR_VT_ACCESS_EN + | ARCH_TIMER_USR_VCT_ACCESS_EN | ARCH_TIMER_VIRT_EVT_EN | ARCH_TIMER_USR_PCT_ACCESS_EN); - /* Enable user access to the virtual counter */ - cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; + /* + * Enable user access to the virtual counter if it doesn't + * need to be workaround. The vdso may have been already + * disabled though. + */ + if (arch_timer_this_cpu_has_cntvct_wa()) + pr_info("CPU%d: Trapping CNTVCT access\n", smp_processor_id()); + else + cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; arch_timer_set_cntkctl(cntkctl); } @@ -791,16 +819,7 @@ static void __init arch_counter_register(unsigned type) else arch_timer_read_counter = arch_counter_get_cntpct; - clocksource_counter.archdata.vdso_direct = true; - -#ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND - /* - * Don't use the vdso fastpath if errata require using - * the out-of-line counter accessor. - */ - if (static_branch_unlikely(&arch_timer_read_ool_enabled)) - clocksource_counter.archdata.vdso_direct = false; -#endif + clocksource_counter.archdata.vdso_direct = vdso_default; } else { arch_timer_read_counter = arch_counter_get_cntvct_mem; } -- cgit v1.2.3 From fa8d815fac96e7c9247783d5a1f8fa4685b3c543 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 27 Jan 2017 12:52:31 +0000 Subject: arm64: arch_timer: Workaround for Cortex-A73 erratum 858921 Cortex-A73 (all versions) counter read can return a wrong value when the counter crosses a 32bit boundary. The workaround involves performing the read twice, and to return one or the other depending on whether a transition has taken place. Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier --- drivers/clocksource/Kconfig | 11 +++++++++++ drivers/clocksource/arm_arch_timer.c | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 3356ab821624..af80a7c44faf 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -366,6 +366,17 @@ config HISILICON_ERRATUM_161010101 161010101. The workaround will be active if the hisilicon,erratum-161010101 property is found in the timer node. +config ARM64_ERRATUM_858921 + bool "Workaround for Cortex-A73 erratum 858921" + default y + select ARM_ARCH_TIMER_OOL_WORKAROUND + depends on ARM_ARCH_TIMER && ARM64 + help + This option enables a workaround applicable to Cortex-A73 + (all versions), whose counter may return incorrect values. + The workaround will be dynamically enabled when an affected + core is detected. + config ARM_GLOBAL_TIMER bool "Support for the ARM global timer" if COMPILE_TEST select CLKSRC_OF if OF diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index f8adea258cf0..8459d19a84f5 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -266,6 +266,17 @@ static u64 notrace hisi_161010101_read_cntvct_el0(void) } #endif +#ifdef CONFIG_ARM64_ERRATUM_858921 +static u64 notrace arm64_858921_read_cntvct_el0(void) +{ + u64 old, new; + + old = read_sysreg(cntvct_el0); + new = read_sysreg(cntvct_el0); + return (((old ^ new) >> 32) & 1) ? old : new; +} +#endif + #ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND DEFINE_PER_CPU(const struct arch_timer_erratum_workaround *, timer_unstable_counter_workaround); @@ -331,6 +342,14 @@ static const struct arch_timer_erratum_workaround ool_workarounds[] = { .set_next_event_virt = erratum_set_next_event_tval_virt, }, #endif +#ifdef CONFIG_ARM64_ERRATUM_858921 + { + .match_type = ate_match_local_cap_id, + .id = (void *)ARM64_WORKAROUND_858921, + .desc = "ARM erratum 858921", + .read_cntvct_el0 = arm64_858921_read_cntvct_el0, + }, +#endif }; typedef bool (*ate_match_fn_t)(const struct arch_timer_erratum_workaround *, -- cgit v1.2.3 From 5a38bcac1f2f0bd0d24700690e36a277ffd0396d Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 21 Feb 2017 14:37:30 +0000 Subject: arm64: arch_timer: Allow erratum matching with ACPI OEM information Just as we're able to identify a broken platform using some DT information, let's enable a way to spot the offenders with ACPI. The difference is that we can only match on some OEM info instead of implementation-specific properties. So in order to avoid the insane multiplication of errata structures, we allow an array of OEM descriptions to be attached to an erratum structure. Acked-by: Thomas Gleixner Tested-by: dann frazier Tested-by: Hanjun Guo Reviewed-by: Hanjun Guo Signed-off-by: Marc Zyngier --- drivers/clocksource/arm_arch_timer.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 8459d19a84f5..887f6d00a71d 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -190,6 +190,12 @@ static struct cyclecounter cyclecounter __ro_after_init = { .mask = CLOCKSOURCE_MASK(56), }; +struct ate_acpi_oem_info { + char oem_id[ACPI_OEM_ID_SIZE + 1]; + char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1]; + u32 oem_revision; +}; + #ifdef CONFIG_FSL_ERRATUM_A008585 /* * The number of retries is an arbitrary value well beyond the highest number @@ -371,6 +377,28 @@ bool arch_timer_check_local_cap_erratum(const struct arch_timer_erratum_workarou return this_cpu_has_cap((uintptr_t)wa->id); } + +static +bool arch_timer_check_acpi_oem_erratum(const struct arch_timer_erratum_workaround *wa, + const void *arg) +{ + static const struct ate_acpi_oem_info empty_oem_info = {}; + const struct ate_acpi_oem_info *info = wa->id; + const struct acpi_table_header *table = arg; + + /* Iterate over the ACPI OEM info array, looking for a match */ + while (memcmp(info, &empty_oem_info, sizeof(*info))) { + if (!memcmp(info->oem_id, table->oem_id, ACPI_OEM_ID_SIZE) && + !memcmp(info->oem_table_id, table->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) && + info->oem_revision == table->oem_revision) + return true; + + info++; + } + + return false; +} + static const struct arch_timer_erratum_workaround * arch_timer_iterate_errata(enum arch_timer_erratum_match_type type, ate_match_fn_t match_fn, @@ -431,6 +459,9 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t match_fn = arch_timer_check_local_cap_erratum; local = true; break; + case ate_match_acpi_oem_info: + match_fn = arch_timer_check_acpi_oem_erratum; + break; default: WARN_ON(1); return; @@ -1277,6 +1308,9 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table) /* Always-on capability */ arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON); + /* Check for globally applicable workarounds */ + arch_timer_check_ool_workaround(ate_match_acpi_oem_info, table); + arch_timer_init(); return 0; } -- cgit v1.2.3 From d003d029cea8a28139b4f9b88a36b8fac864f45b Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 21 Feb 2017 15:04:27 +0000 Subject: arm64: arch_timer: Add HISILICON_ERRATUM_161010101 ACPI matching data In order to deal with ACPI enabled platforms suffering from the HISILICON_ERRATUM_161010101, let's add the required OEM data that allow the workaround to be enabled. Acked-by: Thomas Gleixner Tested-by: dann frazier Tested-by: Hanjun Guo Reviewed-by: Hanjun Guo Signed-off-by: Marc Zyngier --- drivers/clocksource/arm_arch_timer.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 887f6d00a71d..bf9e9d76375e 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -270,6 +270,29 @@ static u64 notrace hisi_161010101_read_cntvct_el0(void) { return __hisi_161010101_read_reg(cntvct_el0); } + +static struct ate_acpi_oem_info hisi_161010101_oem_info[] = { + /* + * Note that trailing spaces are required to properly match + * the OEM table information. + */ + { + .oem_id = "HISI ", + .oem_table_id = "HIP05 ", + .oem_revision = 0, + }, + { + .oem_id = "HISI ", + .oem_table_id = "HIP06 ", + .oem_revision = 0, + }, + { + .oem_id = "HISI ", + .oem_table_id = "HIP07 ", + .oem_revision = 0, + }, + { /* Sentinel indicating the end of the OEM array */ }, +}; #endif #ifdef CONFIG_ARM64_ERRATUM_858921 @@ -347,6 +370,16 @@ static const struct arch_timer_erratum_workaround ool_workarounds[] = { .set_next_event_phys = erratum_set_next_event_tval_phys, .set_next_event_virt = erratum_set_next_event_tval_virt, }, + { + .match_type = ate_match_acpi_oem_info, + .id = hisi_161010101_oem_info, + .desc = "HiSilicon erratum 161010101", + .read_cntp_tval_el0 = hisi_161010101_read_cntp_tval_el0, + .read_cntv_tval_el0 = hisi_161010101_read_cntv_tval_el0, + .read_cntvct_el0 = hisi_161010101_read_cntvct_el0, + .set_next_event_phys = erratum_set_next_event_tval_phys, + .set_next_event_virt = erratum_set_next_event_tval_virt, + }, #endif #ifdef CONFIG_ARM64_ERRATUM_858921 { -- cgit v1.2.3 From 0d9298ea37b5f590f3d10ccc2d8d34d26af3fa84 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 11 Mar 2017 17:42:29 +0000 Subject: clocksource/drivers/orion: Read clock rate once Rather than reading the clock rate three times, read it once - we are about to add a fourth usage. Signed-off-by: Russell King Signed-off-by: Daniel Lezcano --- drivers/clocksource/time-orion.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c index a28f496e97cf..c4818a5dc8e5 100644 --- a/drivers/clocksource/time-orion.c +++ b/drivers/clocksource/time-orion.c @@ -106,6 +106,7 @@ static struct irqaction orion_clkevt_irq = { static int __init orion_timer_init(struct device_node *np) { + unsigned long rate; struct clk *clk; int irq, ret; @@ -135,6 +136,8 @@ static int __init orion_timer_init(struct device_node *np) return -EINVAL; } + rate = clk_get_rate(clk); + /* setup timer0 as free-running clocksource */ writel(~0, timer_base + TIMER0_VAL); writel(~0, timer_base + TIMER0_RELOAD); @@ -142,15 +145,15 @@ static int __init orion_timer_init(struct device_node *np) TIMER0_RELOAD_EN | TIMER0_EN, TIMER0_RELOAD_EN | TIMER0_EN); - ret = clocksource_mmio_init(timer_base + TIMER0_VAL, "orion_clocksource", - clk_get_rate(clk), 300, 32, + ret = clocksource_mmio_init(timer_base + TIMER0_VAL, + "orion_clocksource", rate, 300, 32, clocksource_mmio_readl_down); if (ret) { pr_err("Failed to initialize mmio timer"); return ret; } - sched_clock_register(orion_read_sched_clock, 32, clk_get_rate(clk)); + sched_clock_register(orion_read_sched_clock, 32, rate); /* setup timer1 as clockevent timer */ ret = setup_irq(irq, &orion_clkevt_irq); @@ -162,7 +165,7 @@ static int __init orion_timer_init(struct device_node *np) ticks_per_jiffy = (clk_get_rate(clk) + HZ/2) / HZ; orion_clkevt.cpumask = cpumask_of(0); orion_clkevt.irq = irq; - clockevents_config_and_register(&orion_clkevt, clk_get_rate(clk), + clockevents_config_and_register(&orion_clkevt, rate, ORION_ONESHOT_MIN, ORION_ONESHOT_MAX); return 0; -- cgit v1.2.3 From 9a4914ce0dff47b53df9ffbf9f48120b86ccb4a3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 11 Mar 2017 17:42:34 +0000 Subject: clocksource/drivers/orion: Add delay_timer implementation Add an implementation for the ARM delay timer, which is used for udelay(). This provides less CPU dependent and more accurate delays - the CPU loop on Marvell Dove appears to calibrate to around 6% too short. Signed-off-by: Russell King Signed-off-by: Daniel Lezcano --- drivers/clocksource/time-orion.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c index c4818a5dc8e5..7eb2ab0bd114 100644 --- a/drivers/clocksource/time-orion.c +++ b/drivers/clocksource/time-orion.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,21 @@ static void __iomem *timer_base; +static unsigned long notrace orion_read_timer(void) +{ + return ~readl(timer_base + TIMER0_VAL); +} + +static struct delay_timer orion_delay_timer = { + .read_current_timer = orion_read_timer, +}; + +static void orion_delay_timer_init(unsigned long rate) +{ + orion_delay_timer.freq = rate; + register_current_timer_delay(&orion_delay_timer); +} + /* * Free-running clocksource handling. */ @@ -168,6 +184,9 @@ static int __init orion_timer_init(struct device_node *np) clockevents_config_and_register(&orion_clkevt, rate, ORION_ONESHOT_MIN, ORION_ONESHOT_MAX); + + orion_delay_timer_init(rate); + return 0; } CLOCKSOURCE_OF_DECLARE(orion_timer, "marvell,orion-timer", orion_timer_init); -- cgit v1.2.3 From ac9ce6d1a0cc29767932d9f2fcb8ebc97c5106c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 9 Mar 2017 10:47:10 +0100 Subject: clocksource: Add missing line break to error messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Printing with pr_* functions requires adding line break manually. Signed-off-by: Rafał Miłecki Acked-by: Thierry Reding Signed-off-by: Daniel Lezcano --- drivers/clocksource/arc_timer.c | 14 +++++++------- drivers/clocksource/arm_arch_timer.c | 2 +- drivers/clocksource/asm9260_timer.c | 2 +- drivers/clocksource/bcm2835_timer.c | 6 +++--- drivers/clocksource/bcm_kona_timer.c | 2 +- drivers/clocksource/clksrc-probe.c | 2 +- drivers/clocksource/dw_apb_timer.c | 2 +- drivers/clocksource/meson6_timer.c | 4 ++-- drivers/clocksource/mips-gic-timer.c | 2 +- drivers/clocksource/nomadik-mtu.c | 8 ++++---- drivers/clocksource/pxa_timer.c | 6 +++--- drivers/clocksource/samsung_pwm_timer.c | 6 +++--- drivers/clocksource/sun4i_timer.c | 10 +++++----- drivers/clocksource/tegra20_timer.c | 2 +- drivers/clocksource/time-armada-370-xp.c | 16 ++++++++-------- drivers/clocksource/time-efm32.c | 2 +- drivers/clocksource/time-orion.c | 4 ++-- drivers/clocksource/timer-atmel-pit.c | 2 +- drivers/clocksource/timer-digicolor.c | 6 +++--- drivers/clocksource/timer-integrator-ap.c | 4 ++-- drivers/clocksource/timer-nps.c | 6 +++--- drivers/clocksource/timer-prima2.c | 10 +++++----- drivers/clocksource/timer-sp804.c | 4 ++-- drivers/clocksource/timer-sun5i.c | 6 +++--- drivers/clocksource/vf_pit_timer.c | 2 +- 25 files changed, 65 insertions(+), 65 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arc_timer.c b/drivers/clocksource/arc_timer.c index 7517f959cba7..21649733827d 100644 --- a/drivers/clocksource/arc_timer.c +++ b/drivers/clocksource/arc_timer.c @@ -37,7 +37,7 @@ static int noinline arc_get_timer_clk(struct device_node *node) clk = of_clk_get(node, 0); if (IS_ERR(clk)) { - pr_err("timer missing clk"); + pr_err("timer missing clk\n"); return PTR_ERR(clk); } @@ -89,7 +89,7 @@ static int __init arc_cs_setup_gfrc(struct device_node *node) READ_BCR(ARC_REG_MCIP_BCR, mp); if (!mp.gfrc) { - pr_warn("Global-64-bit-Ctr clocksource not detected"); + pr_warn("Global-64-bit-Ctr clocksource not detected\n"); return -ENXIO; } @@ -140,13 +140,13 @@ static int __init arc_cs_setup_rtc(struct device_node *node) READ_BCR(ARC_REG_TIMERS_BCR, timer); if (!timer.rtc) { - pr_warn("Local-64-bit-Ctr clocksource not detected"); + pr_warn("Local-64-bit-Ctr clocksource not detected\n"); return -ENXIO; } /* Local to CPU hence not usable in SMP */ if (IS_ENABLED(CONFIG_SMP)) { - pr_warn("Local-64-bit-Ctr not usable in SMP"); + pr_warn("Local-64-bit-Ctr not usable in SMP\n"); return -EINVAL; } @@ -290,13 +290,13 @@ static int __init arc_clockevent_setup(struct device_node *node) arc_timer_irq = irq_of_parse_and_map(node, 0); if (arc_timer_irq <= 0) { - pr_err("clockevent: missing irq"); + pr_err("clockevent: missing irq\n"); return -EINVAL; } ret = arc_get_timer_clk(node); if (ret) { - pr_err("clockevent: missing clk"); + pr_err("clockevent: missing clk\n"); return ret; } @@ -313,7 +313,7 @@ static int __init arc_clockevent_setup(struct device_node *node) arc_timer_starting_cpu, arc_timer_dying_cpu); if (ret) { - pr_err("Failed to setup hotplug state"); + pr_err("Failed to setup hotplug state\n"); return ret; } return 0; diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 7a8a4117f123..56c3e25f4e1a 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -1055,7 +1055,7 @@ static int __init arch_timer_mem_init(struct device_node *np) ret = -EINVAL; if (!irq) { - pr_err("arch_timer: Frame missing %s irq", + pr_err("arch_timer: Frame missing %s irq\n", arch_timer_mem_use_virtual ? "virt" : "phys"); goto out; } diff --git a/drivers/clocksource/asm9260_timer.c b/drivers/clocksource/asm9260_timer.c index 1ba871b7fe11..c6780830b8ac 100644 --- a/drivers/clocksource/asm9260_timer.c +++ b/drivers/clocksource/asm9260_timer.c @@ -193,7 +193,7 @@ static int __init asm9260_timer_init(struct device_node *np) priv.base = of_io_request_and_map(np, 0, np->name); if (IS_ERR(priv.base)) { - pr_err("%s: unable to map resource", np->name); + pr_err("%s: unable to map resource\n", np->name); return PTR_ERR(priv.base); } diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c index f2f29d2be1cf..dce44307469e 100644 --- a/drivers/clocksource/bcm2835_timer.c +++ b/drivers/clocksource/bcm2835_timer.c @@ -89,13 +89,13 @@ static int __init bcm2835_timer_init(struct device_node *node) base = of_iomap(node, 0); if (!base) { - pr_err("Can't remap registers"); + pr_err("Can't remap registers\n"); return -ENXIO; } ret = of_property_read_u32(node, "clock-frequency", &freq); if (ret) { - pr_err("Can't read clock-frequency"); + pr_err("Can't read clock-frequency\n"); goto err_iounmap; } @@ -107,7 +107,7 @@ static int __init bcm2835_timer_init(struct device_node *node) irq = irq_of_parse_and_map(node, DEFAULT_TIMER); if (irq <= 0) { - pr_err("Can't parse IRQ"); + pr_err("Can't parse IRQ\n"); ret = -EINVAL; goto err_iounmap; } diff --git a/drivers/clocksource/bcm_kona_timer.c b/drivers/clocksource/bcm_kona_timer.c index 92f6e4deee74..fda5e1476638 100644 --- a/drivers/clocksource/bcm_kona_timer.c +++ b/drivers/clocksource/bcm_kona_timer.c @@ -179,7 +179,7 @@ static int __init kona_timer_init(struct device_node *node) } else if (!of_property_read_u32(node, "clock-frequency", &freq)) { arch_timer_rate = freq; } else { - pr_err("Kona Timer v1 unable to determine clock-frequency"); + pr_err("Kona Timer v1 unable to determine clock-frequency\n"); return -EINVAL; } diff --git a/drivers/clocksource/clksrc-probe.c b/drivers/clocksource/clksrc-probe.c index bc62be97f0a8..ac701ffb8d59 100644 --- a/drivers/clocksource/clksrc-probe.c +++ b/drivers/clocksource/clksrc-probe.c @@ -40,7 +40,7 @@ void __init clocksource_probe(void) ret = init_func_ret(np); if (ret) { - pr_err("Failed to initialize '%s': %d", + pr_err("Failed to initialize '%s': %d\n", of_node_full_name(np), ret); continue; } diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c index 63e4f5519577..9e937e23b63e 100644 --- a/drivers/clocksource/dw_apb_timer.c +++ b/drivers/clocksource/dw_apb_timer.c @@ -101,7 +101,7 @@ static irqreturn_t dw_apb_clockevent_irq(int irq, void *data) struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); if (!evt->event_handler) { - pr_info("Spurious APBT timer interrupt %d", irq); + pr_info("Spurious APBT timer interrupt %d\n", irq); return IRQ_NONE; } diff --git a/drivers/clocksource/meson6_timer.c b/drivers/clocksource/meson6_timer.c index 52af591a9fc7..39d21f693a33 100644 --- a/drivers/clocksource/meson6_timer.c +++ b/drivers/clocksource/meson6_timer.c @@ -133,13 +133,13 @@ static int __init meson6_timer_init(struct device_node *node) timer_base = of_io_request_and_map(node, 0, "meson6-timer"); if (IS_ERR(timer_base)) { - pr_err("Can't map registers"); + pr_err("Can't map registers\n"); return -ENXIO; } irq = irq_of_parse_and_map(node, 0); if (irq <= 0) { - pr_err("Can't parse IRQ"); + pr_err("Can't parse IRQ\n"); return -EINVAL; } diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c index d9ef7a61e093..b6ad9c0a7c55 100644 --- a/drivers/clocksource/mips-gic-timer.c +++ b/drivers/clocksource/mips-gic-timer.c @@ -174,7 +174,7 @@ static int __init gic_clocksource_of_init(struct device_node *node) if (!gic_present || !node->parent || !of_device_is_compatible(node->parent, "mti,gic")) { - pr_warn("No DT definition for the mips gic driver"); + pr_warn("No DT definition for the mips gic driver\n"); return -ENXIO; } diff --git a/drivers/clocksource/nomadik-mtu.c b/drivers/clocksource/nomadik-mtu.c index 3c124d1ca600..7d44de304f37 100644 --- a/drivers/clocksource/nomadik-mtu.c +++ b/drivers/clocksource/nomadik-mtu.c @@ -260,25 +260,25 @@ static int __init nmdk_timer_of_init(struct device_node *node) base = of_iomap(node, 0); if (!base) { - pr_err("Can't remap registers"); + pr_err("Can't remap registers\n"); return -ENXIO; } pclk = of_clk_get_by_name(node, "apb_pclk"); if (IS_ERR(pclk)) { - pr_err("could not get apb_pclk"); + pr_err("could not get apb_pclk\n"); return PTR_ERR(pclk); } clk = of_clk_get_by_name(node, "timclk"); if (IS_ERR(clk)) { - pr_err("could not get timclk"); + pr_err("could not get timclk\n"); return PTR_ERR(clk); } irq = irq_of_parse_and_map(node, 0); if (irq <= 0) { - pr_err("Can't parse IRQ"); + pr_err("Can't parse IRQ\n"); return -EINVAL; } diff --git a/drivers/clocksource/pxa_timer.c b/drivers/clocksource/pxa_timer.c index 1c24de215c14..a10fa667325f 100644 --- a/drivers/clocksource/pxa_timer.c +++ b/drivers/clocksource/pxa_timer.c @@ -166,14 +166,14 @@ static int __init pxa_timer_common_init(int irq, unsigned long clock_tick_rate) ret = setup_irq(irq, &pxa_ost0_irq); if (ret) { - pr_err("Failed to setup irq"); + pr_err("Failed to setup irq\n"); return ret; } ret = clocksource_mmio_init(timer_base + OSCR, "oscr0", clock_tick_rate, 200, 32, clocksource_mmio_readl_up); if (ret) { - pr_err("Failed to init clocksource"); + pr_err("Failed to init clocksource\n"); return ret; } @@ -203,7 +203,7 @@ static int __init pxa_timer_dt_init(struct device_node *np) ret = clk_prepare_enable(clk); if (ret) { - pr_crit("Failed to prepare clock"); + pr_crit("Failed to prepare clock\n"); return ret; } diff --git a/drivers/clocksource/samsung_pwm_timer.c b/drivers/clocksource/samsung_pwm_timer.c index 0093ece661fe..a68e6538c809 100644 --- a/drivers/clocksource/samsung_pwm_timer.c +++ b/drivers/clocksource/samsung_pwm_timer.c @@ -385,7 +385,7 @@ static int __init _samsung_pwm_clocksource_init(void) mask = ~pwm.variant.output_mask & ((1 << SAMSUNG_PWM_NUM) - 1); channel = fls(mask) - 1; if (channel < 0) { - pr_crit("failed to find PWM channel for clocksource"); + pr_crit("failed to find PWM channel for clocksource\n"); return -EINVAL; } pwm.source_id = channel; @@ -393,7 +393,7 @@ static int __init _samsung_pwm_clocksource_init(void) mask &= ~(1 << channel); channel = fls(mask) - 1; if (channel < 0) { - pr_crit("failed to find PWM channel for clock event"); + pr_crit("failed to find PWM channel for clock event\n"); return -EINVAL; } pwm.event_id = channel; @@ -448,7 +448,7 @@ static int __init samsung_pwm_alloc(struct device_node *np, pwm.timerclk = of_clk_get_by_name(np, "timers"); if (IS_ERR(pwm.timerclk)) { - pr_crit("failed to get timers clock for timer"); + pr_crit("failed to get timers clock for timer\n"); return PTR_ERR(pwm.timerclk); } diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index c83452cacb41..4452d5c8f304 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -159,25 +159,25 @@ static int __init sun4i_timer_init(struct device_node *node) timer_base = of_iomap(node, 0); if (!timer_base) { - pr_crit("Can't map registers"); + pr_crit("Can't map registers\n"); return -ENXIO; } irq = irq_of_parse_and_map(node, 0); if (irq <= 0) { - pr_crit("Can't parse IRQ"); + pr_crit("Can't parse IRQ\n"); return -EINVAL; } clk = of_clk_get(node, 0); if (IS_ERR(clk)) { - pr_crit("Can't get timer clock"); + pr_crit("Can't get timer clock\n"); return PTR_ERR(clk); } ret = clk_prepare_enable(clk); if (ret) { - pr_err("Failed to prepare clock"); + pr_err("Failed to prepare clock\n"); return ret; } @@ -200,7 +200,7 @@ static int __init sun4i_timer_init(struct device_node *node) ret = clocksource_mmio_init(timer_base + TIMER_CNTVAL_REG(1), node->name, rate, 350, 32, clocksource_mmio_readl_down); if (ret) { - pr_err("Failed to register clocksource"); + pr_err("Failed to register clocksource\n"); return ret; } diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c index f960891aa04e..b9990b9c98c5 100644 --- a/drivers/clocksource/tegra20_timer.c +++ b/drivers/clocksource/tegra20_timer.c @@ -245,7 +245,7 @@ static int __init tegra20_init_rtc(struct device_node *np) rtc_base = of_iomap(np, 0); if (!rtc_base) { - pr_err("Can't map RTC registers"); + pr_err("Can't map RTC registers\n"); return -ENXIO; } diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c index 4440aefc59cd..aea4380129ea 100644 --- a/drivers/clocksource/time-armada-370-xp.c +++ b/drivers/clocksource/time-armada-370-xp.c @@ -247,13 +247,13 @@ static int __init armada_370_xp_timer_common_init(struct device_node *np) timer_base = of_iomap(np, 0); if (!timer_base) { - pr_err("Failed to iomap"); + pr_err("Failed to iomap\n"); return -ENXIO; } local_base = of_iomap(np, 1); if (!local_base) { - pr_err("Failed to iomap"); + pr_err("Failed to iomap\n"); return -ENXIO; } @@ -298,7 +298,7 @@ static int __init armada_370_xp_timer_common_init(struct device_node *np) "armada_370_xp_clocksource", timer_clk, 300, 32, clocksource_mmio_readl_down); if (res) { - pr_err("Failed to initialize clocksource mmio"); + pr_err("Failed to initialize clocksource mmio\n"); return res; } @@ -315,7 +315,7 @@ static int __init armada_370_xp_timer_common_init(struct device_node *np) armada_370_xp_evt); /* Immediately configure the timer on the boot CPU */ if (res) { - pr_err("Failed to request percpu irq"); + pr_err("Failed to request percpu irq\n"); return res; } @@ -324,7 +324,7 @@ static int __init armada_370_xp_timer_common_init(struct device_node *np) armada_370_xp_timer_starting_cpu, armada_370_xp_timer_dying_cpu); if (res) { - pr_err("Failed to setup hotplug state and timer"); + pr_err("Failed to setup hotplug state and timer\n"); return res; } @@ -339,7 +339,7 @@ static int __init armada_xp_timer_init(struct device_node *np) int ret; if (IS_ERR(clk)) { - pr_err("Failed to get clock"); + pr_err("Failed to get clock\n"); return PTR_ERR(clk); } @@ -375,7 +375,7 @@ static int __init armada_375_timer_init(struct device_node *np) /* Must have at least a clock */ if (IS_ERR(clk)) { - pr_err("Failed to get clock"); + pr_err("Failed to get clock\n"); return PTR_ERR(clk); } @@ -399,7 +399,7 @@ static int __init armada_370_timer_init(struct device_node *np) clk = of_clk_get(np, 0); if (IS_ERR(clk)) { - pr_err("Failed to get clock"); + pr_err("Failed to get clock\n"); return PTR_ERR(clk); } diff --git a/drivers/clocksource/time-efm32.c b/drivers/clocksource/time-efm32.c index 5ac344b383e1..ce0f97b4e5db 100644 --- a/drivers/clocksource/time-efm32.c +++ b/drivers/clocksource/time-efm32.c @@ -235,7 +235,7 @@ static int __init efm32_clockevent_init(struct device_node *np) ret = setup_irq(irq, &efm32_clock_event_irq); if (ret) { - pr_err("Failed setup irq"); + pr_err("Failed setup irq\n"); goto err_setup_irq; } diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c index 7eb2ab0bd114..b9b97f630c4d 100644 --- a/drivers/clocksource/time-orion.c +++ b/drivers/clocksource/time-orion.c @@ -141,7 +141,7 @@ static int __init orion_timer_init(struct device_node *np) ret = clk_prepare_enable(clk); if (ret) { - pr_err("Failed to prepare clock"); + pr_err("Failed to prepare clock\n"); return ret; } @@ -165,7 +165,7 @@ static int __init orion_timer_init(struct device_node *np) "orion_clocksource", rate, 300, 32, clocksource_mmio_readl_down); if (ret) { - pr_err("Failed to initialize mmio timer"); + pr_err("Failed to initialize mmio timer\n"); return ret; } diff --git a/drivers/clocksource/timer-atmel-pit.c b/drivers/clocksource/timer-atmel-pit.c index c0b5df3167a0..cc112351dc70 100644 --- a/drivers/clocksource/timer-atmel-pit.c +++ b/drivers/clocksource/timer-atmel-pit.c @@ -226,7 +226,7 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node) ret = clocksource_register_hz(&data->clksrc, pit_rate); if (ret) { - pr_err("Failed to register clocksource"); + pr_err("Failed to register clocksource\n"); return ret; } diff --git a/drivers/clocksource/timer-digicolor.c b/drivers/clocksource/timer-digicolor.c index e9f50d289362..94a161eb9cce 100644 --- a/drivers/clocksource/timer-digicolor.c +++ b/drivers/clocksource/timer-digicolor.c @@ -161,19 +161,19 @@ static int __init digicolor_timer_init(struct device_node *node) */ dc_timer_dev.base = of_iomap(node, 0); if (!dc_timer_dev.base) { - pr_err("Can't map registers"); + pr_err("Can't map registers\n"); return -ENXIO; } irq = irq_of_parse_and_map(node, dc_timer_dev.timer_id); if (irq <= 0) { - pr_err("Can't parse IRQ"); + pr_err("Can't parse IRQ\n"); return -EINVAL; } clk = of_clk_get(node, 0); if (IS_ERR(clk)) { - pr_err("Can't get timer clock"); + pr_err("Can't get timer clock\n"); return PTR_ERR(clk); } clk_prepare_enable(clk); diff --git a/drivers/clocksource/timer-integrator-ap.c b/drivers/clocksource/timer-integrator-ap.c index df6e672afc04..04ad3066e190 100644 --- a/drivers/clocksource/timer-integrator-ap.c +++ b/drivers/clocksource/timer-integrator-ap.c @@ -200,7 +200,7 @@ static int __init integrator_ap_timer_init_of(struct device_node *node) err = of_property_read_string(of_aliases, "arm,timer-primary", &path); if (err) { - pr_warn("Failed to read property"); + pr_warn("Failed to read property\n"); return err; } @@ -209,7 +209,7 @@ static int __init integrator_ap_timer_init_of(struct device_node *node) err = of_property_read_string(of_aliases, "arm,timer-secondary", &path); if (err) { - pr_warn("Failed to read property"); + pr_warn("Failed to read property\n"); return err; } diff --git a/drivers/clocksource/timer-nps.c b/drivers/clocksource/timer-nps.c index da1f7986e477..e74ea1722ad3 100644 --- a/drivers/clocksource/timer-nps.c +++ b/drivers/clocksource/timer-nps.c @@ -55,7 +55,7 @@ static int __init nps_get_timer_clk(struct device_node *node, *clk = of_clk_get(node, 0); ret = PTR_ERR_OR_ZERO(*clk); if (ret) { - pr_err("timer missing clk"); + pr_err("timer missing clk\n"); return ret; } @@ -247,7 +247,7 @@ static int __init nps_setup_clockevent(struct device_node *node) nps_timer0_irq = irq_of_parse_and_map(node, 0); if (nps_timer0_irq <= 0) { - pr_err("clockevent: missing irq"); + pr_err("clockevent: missing irq\n"); return -EINVAL; } @@ -270,7 +270,7 @@ static int __init nps_setup_clockevent(struct device_node *node) nps_timer_starting_cpu, nps_timer_dying_cpu); if (ret) { - pr_err("Failed to setup hotplug state"); + pr_err("Failed to setup hotplug state\n"); clk_disable_unprepare(clk); free_percpu_irq(nps_timer0_irq, &nps_clockevent_device); return ret; diff --git a/drivers/clocksource/timer-prima2.c b/drivers/clocksource/timer-prima2.c index bfa981ac1eaf..b4122ed1accb 100644 --- a/drivers/clocksource/timer-prima2.c +++ b/drivers/clocksource/timer-prima2.c @@ -196,20 +196,20 @@ static int __init sirfsoc_prima2_timer_init(struct device_node *np) clk = of_clk_get(np, 0); if (IS_ERR(clk)) { - pr_err("Failed to get clock"); + pr_err("Failed to get clock\n"); return PTR_ERR(clk); } ret = clk_prepare_enable(clk); if (ret) { - pr_err("Failed to enable clock"); + pr_err("Failed to enable clock\n"); return ret; } rate = clk_get_rate(clk); if (rate < PRIMA2_CLOCK_FREQ || rate % PRIMA2_CLOCK_FREQ) { - pr_err("Invalid clock rate"); + pr_err("Invalid clock rate\n"); return -EINVAL; } @@ -229,7 +229,7 @@ static int __init sirfsoc_prima2_timer_init(struct device_node *np) ret = clocksource_register_hz(&sirfsoc_clocksource, PRIMA2_CLOCK_FREQ); if (ret) { - pr_err("Failed to register clocksource"); + pr_err("Failed to register clocksource\n"); return ret; } @@ -237,7 +237,7 @@ static int __init sirfsoc_prima2_timer_init(struct device_node *np) ret = setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq); if (ret) { - pr_err("Failed to setup irq"); + pr_err("Failed to setup irq\n"); return ret; } diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c index d07863388e05..2d575a8c0939 100644 --- a/drivers/clocksource/timer-sp804.c +++ b/drivers/clocksource/timer-sp804.c @@ -299,13 +299,13 @@ static int __init integrator_cp_of_init(struct device_node *np) base = of_iomap(np, 0); if (!base) { - pr_err("Failed to iomap"); + pr_err("Failed to iomap\n"); return -ENXIO; } clk = of_clk_get(np, 0); if (IS_ERR(clk)) { - pr_err("Failed to get clock"); + pr_err("Failed to get clock\n"); return PTR_ERR(clk); } diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c index a3e662b15964..2e9c830ae1cd 100644 --- a/drivers/clocksource/timer-sun5i.c +++ b/drivers/clocksource/timer-sun5i.c @@ -332,19 +332,19 @@ static int __init sun5i_timer_init(struct device_node *node) timer_base = of_io_request_and_map(node, 0, of_node_full_name(node)); if (IS_ERR(timer_base)) { - pr_err("Can't map registers"); + pr_err("Can't map registers\n"); return PTR_ERR(timer_base);; } irq = irq_of_parse_and_map(node, 0); if (irq <= 0) { - pr_err("Can't parse IRQ"); + pr_err("Can't parse IRQ\n"); return -EINVAL; } clk = of_clk_get(node, 0); if (IS_ERR(clk)) { - pr_err("Can't get timer clock"); + pr_err("Can't get timer clock\n"); return PTR_ERR(clk); } diff --git a/drivers/clocksource/vf_pit_timer.c b/drivers/clocksource/vf_pit_timer.c index 55d8d8402d90..e0849e20a307 100644 --- a/drivers/clocksource/vf_pit_timer.c +++ b/drivers/clocksource/vf_pit_timer.c @@ -165,7 +165,7 @@ static int __init pit_timer_init(struct device_node *np) timer_base = of_iomap(np, 0); if (!timer_base) { - pr_err("Failed to iomap"); + pr_err("Failed to iomap\n"); return -ENXIO; } -- cgit v1.2.3 From 5e0a39d0f727b35c8b7ef56ba0724c8ceb006297 Mon Sep 17 00:00:00 2001 From: Alexander Kochetkov Date: Tue, 31 Jan 2017 15:43:14 +0300 Subject: clocksource/drivers/rockchip_timer: Implement clocksource timer The clock supplying the arm-global-timer on the rk3188 is coming from the the cpu clock itself and thus changes its rate everytime cpufreq adjusts the cpu frequency making this timer unsuitable as a stable clocksource and sched clock. The rk3188, rk3288 and following socs share a separate timer block already handled by the rockchip-timer driver. Therefore adapt this driver to also be able to act as clocksource and sched clock on rk3188. In order to test clocksource you can run following commands and check how much time it take in real. On rk3188 it take about ~45 seconds. cpufreq-set -f 1.6GHZ date; sleep 60; date In order to use the patch you need to declare two timers in the dts file. The first timer will be initialized as clockevent provider and the second one as clocksource. The clockevent must be from alive subsystem as it used as backup for the local timers at sleep time. The patch does not break compatibility with older device tree files. The older device tree files contain only one timer. The timer will be initialized as clockevent, as expected. rk3288 (and probably anything newer) is irrelevant to this patch, as it has the arch timer interface. This patch may be useful for Cortex-A9/A5 based parts. Signed-off-by: Alexander Kochetkov Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 1 + drivers/clocksource/rockchip_timer.c | 218 +++++++++++++++++++++++++---------- 2 files changed, 158 insertions(+), 61 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 3356ab821624..483f3b1af4fd 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -81,6 +81,7 @@ config ROCKCHIP_TIMER bool "Rockchip timer driver" if COMPILE_TEST depends on ARM || ARM64 select CLKSRC_OF + select CLKSRC_MMIO help Enables the support for the rockchip timer driver. diff --git a/drivers/clocksource/rockchip_timer.c b/drivers/clocksource/rockchip_timer.c index 23e267acba25..49c02be50eca 100644 --- a/drivers/clocksource/rockchip_timer.c +++ b/drivers/clocksource/rockchip_timer.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include #include @@ -19,6 +21,8 @@ #define TIMER_LOAD_COUNT0 0x00 #define TIMER_LOAD_COUNT1 0x04 +#define TIMER_CURRENT_VALUE0 0x08 +#define TIMER_CURRENT_VALUE1 0x0C #define TIMER_CONTROL_REG3288 0x10 #define TIMER_CONTROL_REG3399 0x1c #define TIMER_INT_STATUS 0x18 @@ -29,103 +33,118 @@ #define TIMER_MODE_USER_DEFINED_COUNT (1 << 1) #define TIMER_INT_UNMASK (1 << 2) -struct bc_timer { - struct clock_event_device ce; +struct rk_timer { void __iomem *base; void __iomem *ctrl; + struct clk *clk; + struct clk *pclk; u32 freq; + int irq; }; -static struct bc_timer bc_timer; - -static inline struct bc_timer *rk_timer(struct clock_event_device *ce) -{ - return container_of(ce, struct bc_timer, ce); -} +struct rk_clkevt { + struct clock_event_device ce; + struct rk_timer timer; +}; -static inline void __iomem *rk_base(struct clock_event_device *ce) -{ - return rk_timer(ce)->base; -} +static struct rk_clkevt *rk_clkevt; +static struct rk_timer *rk_clksrc; -static inline void __iomem *rk_ctrl(struct clock_event_device *ce) +static inline struct rk_timer *rk_timer(struct clock_event_device *ce) { - return rk_timer(ce)->ctrl; + return &container_of(ce, struct rk_clkevt, ce)->timer; } -static inline void rk_timer_disable(struct clock_event_device *ce) +static inline void rk_timer_disable(struct rk_timer *timer) { - writel_relaxed(TIMER_DISABLE, rk_ctrl(ce)); + writel_relaxed(TIMER_DISABLE, timer->ctrl); } -static inline void rk_timer_enable(struct clock_event_device *ce, u32 flags) +static inline void rk_timer_enable(struct rk_timer *timer, u32 flags) { - writel_relaxed(TIMER_ENABLE | TIMER_INT_UNMASK | flags, - rk_ctrl(ce)); + writel_relaxed(TIMER_ENABLE | flags, timer->ctrl); } static void rk_timer_update_counter(unsigned long cycles, - struct clock_event_device *ce) + struct rk_timer *timer) { - writel_relaxed(cycles, rk_base(ce) + TIMER_LOAD_COUNT0); - writel_relaxed(0, rk_base(ce) + TIMER_LOAD_COUNT1); + writel_relaxed(cycles, timer->base + TIMER_LOAD_COUNT0); + writel_relaxed(0, timer->base + TIMER_LOAD_COUNT1); } -static void rk_timer_interrupt_clear(struct clock_event_device *ce) +static void rk_timer_interrupt_clear(struct rk_timer *timer) { - writel_relaxed(1, rk_base(ce) + TIMER_INT_STATUS); + writel_relaxed(1, timer->base + TIMER_INT_STATUS); } static inline int rk_timer_set_next_event(unsigned long cycles, struct clock_event_device *ce) { - rk_timer_disable(ce); - rk_timer_update_counter(cycles, ce); - rk_timer_enable(ce, TIMER_MODE_USER_DEFINED_COUNT); + struct rk_timer *timer = rk_timer(ce); + + rk_timer_disable(timer); + rk_timer_update_counter(cycles, timer); + rk_timer_enable(timer, TIMER_MODE_USER_DEFINED_COUNT | + TIMER_INT_UNMASK); return 0; } static int rk_timer_shutdown(struct clock_event_device *ce) { - rk_timer_disable(ce); + struct rk_timer *timer = rk_timer(ce); + + rk_timer_disable(timer); return 0; } static int rk_timer_set_periodic(struct clock_event_device *ce) { - rk_timer_disable(ce); - rk_timer_update_counter(rk_timer(ce)->freq / HZ - 1, ce); - rk_timer_enable(ce, TIMER_MODE_FREE_RUNNING); + struct rk_timer *timer = rk_timer(ce); + + rk_timer_disable(timer); + rk_timer_update_counter(timer->freq / HZ - 1, timer); + rk_timer_enable(timer, TIMER_MODE_FREE_RUNNING | TIMER_INT_UNMASK); return 0; } static irqreturn_t rk_timer_interrupt(int irq, void *dev_id) { struct clock_event_device *ce = dev_id; + struct rk_timer *timer = rk_timer(ce); - rk_timer_interrupt_clear(ce); + rk_timer_interrupt_clear(timer); if (clockevent_state_oneshot(ce)) - rk_timer_disable(ce); + rk_timer_disable(timer); ce->event_handler(ce); return IRQ_HANDLED; } -static int __init rk_timer_init(struct device_node *np, u32 ctrl_reg) +static u64 notrace rk_timer_sched_read(void) +{ + return ~readl_relaxed(rk_clksrc->base + TIMER_CURRENT_VALUE0); +} + +static int __init +rk_timer_probe(struct rk_timer *timer, struct device_node *np) { - struct clock_event_device *ce = &bc_timer.ce; struct clk *timer_clk; struct clk *pclk; int ret = -EINVAL, irq; + u32 ctrl_reg = TIMER_CONTROL_REG3288; - bc_timer.base = of_iomap(np, 0); - if (!bc_timer.base) { + timer->base = of_iomap(np, 0); + if (!timer->base) { pr_err("Failed to get base address for '%s'\n", TIMER_NAME); return -ENXIO; } - bc_timer.ctrl = bc_timer.base + ctrl_reg; + + if (of_device_is_compatible(np, "rockchip,rk3399-timer")) + ctrl_reg = TIMER_CONTROL_REG3399; + + timer->ctrl = timer->base + ctrl_reg; pclk = of_clk_get_by_name(np, "pclk"); if (IS_ERR(pclk)) { @@ -139,6 +158,7 @@ static int __init rk_timer_init(struct device_node *np, u32 ctrl_reg) pr_err("Failed to enable pclk for '%s'\n", TIMER_NAME); goto out_unmap; } + timer->pclk = pclk; timer_clk = of_clk_get_by_name(np, "timer"); if (IS_ERR(timer_clk)) { @@ -152,8 +172,9 @@ static int __init rk_timer_init(struct device_node *np, u32 ctrl_reg) pr_err("Failed to enable timer clock\n"); goto out_timer_clk; } + timer->clk = timer_clk; - bc_timer.freq = clk_get_rate(timer_clk); + timer->freq = clk_get_rate(timer_clk); irq = irq_of_parse_and_map(np, 0); if (!irq) { @@ -161,51 +182,126 @@ static int __init rk_timer_init(struct device_node *np, u32 ctrl_reg) pr_err("Failed to map interrupts for '%s'\n", TIMER_NAME); goto out_irq; } + timer->irq = irq; + + rk_timer_interrupt_clear(timer); + rk_timer_disable(timer); + return 0; + +out_irq: + clk_disable_unprepare(timer_clk); +out_timer_clk: + clk_disable_unprepare(pclk); +out_unmap: + iounmap(timer->base); + + return ret; +} + +static void __init rk_timer_cleanup(struct rk_timer *timer) +{ + clk_disable_unprepare(timer->clk); + clk_disable_unprepare(timer->pclk); + iounmap(timer->base); +} + +static int __init rk_clkevt_init(struct device_node *np) +{ + struct clock_event_device *ce; + int ret = -EINVAL; + + rk_clkevt = kzalloc(sizeof(struct rk_clkevt), GFP_KERNEL); + if (!rk_clkevt) { + ret = -ENOMEM; + goto out; + } + ret = rk_timer_probe(&rk_clkevt->timer, np); + if (ret) + goto out_probe; + + ce = &rk_clkevt->ce; ce->name = TIMER_NAME; ce->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_DYNIRQ; ce->set_next_event = rk_timer_set_next_event; ce->set_state_shutdown = rk_timer_shutdown; ce->set_state_periodic = rk_timer_set_periodic; - ce->irq = irq; + ce->irq = rk_clkevt->timer.irq; ce->cpumask = cpu_possible_mask; ce->rating = 250; - rk_timer_interrupt_clear(ce); - rk_timer_disable(ce); - - ret = request_irq(irq, rk_timer_interrupt, IRQF_TIMER, TIMER_NAME, ce); + ret = request_irq(rk_clkevt->timer.irq, rk_timer_interrupt, IRQF_TIMER, + TIMER_NAME, ce); if (ret) { - pr_err("Failed to initialize '%s': %d\n", TIMER_NAME, ret); + pr_err("Failed to initialize '%s': %d\n", + TIMER_NAME, ret); goto out_irq; } - clockevents_config_and_register(ce, bc_timer.freq, 1, UINT_MAX); - + clockevents_config_and_register(&rk_clkevt->ce, + rk_clkevt->timer.freq, 1, UINT_MAX); return 0; out_irq: - clk_disable_unprepare(timer_clk); -out_timer_clk: - clk_disable_unprepare(pclk); -out_unmap: - iounmap(bc_timer.base); - + rk_timer_cleanup(&rk_clkevt->timer); +out_probe: + kfree(rk_clkevt); +out: + /* Leave rk_clkevt not NULL to prevent future init */ + rk_clkevt = ERR_PTR(ret); return ret; } -static int __init rk3288_timer_init(struct device_node *np) +static int __init rk_clksrc_init(struct device_node *np) { - return rk_timer_init(np, TIMER_CONTROL_REG3288); + int ret = -EINVAL; + + rk_clksrc = kzalloc(sizeof(struct rk_timer), GFP_KERNEL); + if (!rk_clksrc) { + ret = -ENOMEM; + goto out; + } + + ret = rk_timer_probe(rk_clksrc, np); + if (ret) + goto out_probe; + + rk_timer_update_counter(UINT_MAX, rk_clksrc); + rk_timer_enable(rk_clksrc, 0); + + ret = clocksource_mmio_init(rk_clksrc->base + TIMER_CURRENT_VALUE0, + TIMER_NAME, rk_clksrc->freq, 250, 32, + clocksource_mmio_readl_down); + if (ret) { + pr_err("Failed to register clocksource"); + goto out_clocksource; + } + + sched_clock_register(rk_timer_sched_read, 32, rk_clksrc->freq); + return 0; + +out_clocksource: + rk_timer_cleanup(rk_clksrc); +out_probe: + kfree(rk_clksrc); +out: + /* Leave rk_clksrc not NULL to prevent future init */ + rk_clksrc = ERR_PTR(ret); + return ret; } -static int __init rk3399_timer_init(struct device_node *np) +static int __init rk_timer_init(struct device_node *np) { - return rk_timer_init(np, TIMER_CONTROL_REG3399); + if (!rk_clkevt) + return rk_clkevt_init(np); + + if (!rk_clksrc) + return rk_clksrc_init(np); + + pr_err("Too many timer definitions for '%s'\n", TIMER_NAME); + return -EINVAL; } -CLOCKSOURCE_OF_DECLARE(rk3288_timer, "rockchip,rk3288-timer", - rk3288_timer_init); -CLOCKSOURCE_OF_DECLARE(rk3399_timer, "rockchip,rk3399-timer", - rk3399_timer_init); +CLOCKSOURCE_OF_DECLARE(rk3288_timer, "rockchip,rk3288-timer", rk_timer_init); +CLOCKSOURCE_OF_DECLARE(rk3399_timer, "rockchip,rk3399-timer", rk_timer_init); -- cgit v1.2.3 From f5bf0ee4ebf779e256bb710f638b4452d94e97fb Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 24 Mar 2017 22:32:34 +0100 Subject: clocksource/drivers/gemini: Rename Gemini timer to Faraday After some research it turns out that the "Gemini" timer is actually a generic IP block from Faraday Technology named FTTMR010, so as to not make things too confusing we need to rename the driver and its symbols to make sense. The implementation remains the same in this patch but we fix the copy-paste error in the timer name "nomadik_mtu" as we're at it. Signed-off-by: Linus Walleij Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 7 +- drivers/clocksource/Makefile | 2 +- drivers/clocksource/timer-fttmr010.c | 276 ++++++++++++++++++++++++++++++++++ drivers/clocksource/timer-gemini.c | 277 ----------------------------------- 4 files changed, 281 insertions(+), 281 deletions(-) create mode 100644 drivers/clocksource/timer-fttmr010.c delete mode 100644 drivers/clocksource/timer-gemini.c (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 483f3b1af4fd..7ca2c2461c9c 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -67,15 +67,16 @@ config DW_APB_TIMER_OF select DW_APB_TIMER select CLKSRC_OF -config GEMINI_TIMER - bool "Cortina Gemini timer driver" if COMPILE_TEST +config FTTMR010_TIMER + bool "Faraday Technology timer driver" if COMPILE_TEST depends on GENERIC_CLOCKEVENTS depends on HAS_IOMEM select CLKSRC_MMIO select CLKSRC_OF select MFD_SYSCON help - Enables support for the Gemini timer + Enables support for the Faraday Technology timer block + FTTMR010. config ROCKCHIP_TIMER bool "Rockchip timer driver" if COMPILE_TEST diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index d227d1314f14..2b5b56a6f00f 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -17,7 +17,7 @@ obj-$(CONFIG_CLKSRC_MMIO) += mmio.o obj-$(CONFIG_DIGICOLOR_TIMER) += timer-digicolor.o obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_timer_of.o -obj-$(CONFIG_GEMINI_TIMER) += timer-gemini.o +obj-$(CONFIG_FTTMR010_TIMER) += timer-fttmr010.o obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.o obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o diff --git a/drivers/clocksource/timer-fttmr010.c b/drivers/clocksource/timer-fttmr010.c new file mode 100644 index 000000000000..e37ec3d69a7e --- /dev/null +++ b/drivers/clocksource/timer-fttmr010.c @@ -0,0 +1,276 @@ +/* + * Faraday Technology FTTMR010 timer driver + * Copyright (C) 2017 Linus Walleij + * + * Based on a rewrite of arch/arm/mach-gemini/timer.c: + * Copyright (C) 2001-2006 Storlink, Corp. + * Copyright (C) 2008-2009 Paulius Zaleckas + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Relevant registers in the global syscon + */ +#define GLOBAL_STATUS 0x04 +#define CPU_AHB_RATIO_MASK (0x3 << 18) +#define CPU_AHB_1_1 (0x0 << 18) +#define CPU_AHB_3_2 (0x1 << 18) +#define CPU_AHB_24_13 (0x2 << 18) +#define CPU_AHB_2_1 (0x3 << 18) +#define REG_TO_AHB_SPEED(reg) ((((reg) >> 15) & 0x7) * 10 + 130) + +/* + * Register definitions for the timers + */ +#define TIMER1_COUNT (0x00) +#define TIMER1_LOAD (0x04) +#define TIMER1_MATCH1 (0x08) +#define TIMER1_MATCH2 (0x0c) +#define TIMER2_COUNT (0x10) +#define TIMER2_LOAD (0x14) +#define TIMER2_MATCH1 (0x18) +#define TIMER2_MATCH2 (0x1c) +#define TIMER3_COUNT (0x20) +#define TIMER3_LOAD (0x24) +#define TIMER3_MATCH1 (0x28) +#define TIMER3_MATCH2 (0x2c) +#define TIMER_CR (0x30) +#define TIMER_INTR_STATE (0x34) +#define TIMER_INTR_MASK (0x38) + +#define TIMER_1_CR_ENABLE (1 << 0) +#define TIMER_1_CR_CLOCK (1 << 1) +#define TIMER_1_CR_INT (1 << 2) +#define TIMER_2_CR_ENABLE (1 << 3) +#define TIMER_2_CR_CLOCK (1 << 4) +#define TIMER_2_CR_INT (1 << 5) +#define TIMER_3_CR_ENABLE (1 << 6) +#define TIMER_3_CR_CLOCK (1 << 7) +#define TIMER_3_CR_INT (1 << 8) +#define TIMER_1_CR_UPDOWN (1 << 9) +#define TIMER_2_CR_UPDOWN (1 << 10) +#define TIMER_3_CR_UPDOWN (1 << 11) +#define TIMER_DEFAULT_FLAGS (TIMER_1_CR_UPDOWN | \ + TIMER_3_CR_ENABLE | \ + TIMER_3_CR_UPDOWN) + +#define TIMER_1_INT_MATCH1 (1 << 0) +#define TIMER_1_INT_MATCH2 (1 << 1) +#define TIMER_1_INT_OVERFLOW (1 << 2) +#define TIMER_2_INT_MATCH1 (1 << 3) +#define TIMER_2_INT_MATCH2 (1 << 4) +#define TIMER_2_INT_OVERFLOW (1 << 5) +#define TIMER_3_INT_MATCH1 (1 << 6) +#define TIMER_3_INT_MATCH2 (1 << 7) +#define TIMER_3_INT_OVERFLOW (1 << 8) +#define TIMER_INT_ALL_MASK 0x1ff + +static unsigned int tick_rate; +static void __iomem *base; + +static u64 notrace fttmr010_read_sched_clock(void) +{ + return readl(base + TIMER3_COUNT); +} + +static int fttmr010_timer_set_next_event(unsigned long cycles, + struct clock_event_device *evt) +{ + u32 cr; + + /* Setup the match register */ + cr = readl(base + TIMER1_COUNT); + writel(cr + cycles, base + TIMER1_MATCH1); + if (readl(base + TIMER1_COUNT) - cr > cycles) + return -ETIME; + + return 0; +} + +static int fttmr010_timer_shutdown(struct clock_event_device *evt) +{ + u32 cr; + + /* + * Disable also for oneshot: the set_next() call will arm the timer + * instead. + */ + /* Stop timer and interrupt. */ + cr = readl(base + TIMER_CR); + cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT); + writel(cr, base + TIMER_CR); + + /* Setup counter start from 0 */ + writel(0, base + TIMER1_COUNT); + writel(0, base + TIMER1_LOAD); + + /* enable interrupt */ + cr = readl(base + TIMER_INTR_MASK); + cr &= ~(TIMER_1_INT_OVERFLOW | TIMER_1_INT_MATCH2); + cr |= TIMER_1_INT_MATCH1; + writel(cr, base + TIMER_INTR_MASK); + + /* start the timer */ + cr = readl(base + TIMER_CR); + cr |= TIMER_1_CR_ENABLE; + writel(cr, base + TIMER_CR); + + return 0; +} + +static int fttmr010_timer_set_periodic(struct clock_event_device *evt) +{ + u32 period = DIV_ROUND_CLOSEST(tick_rate, HZ); + u32 cr; + + /* Stop timer and interrupt */ + cr = readl(base + TIMER_CR); + cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT); + writel(cr, base + TIMER_CR); + + /* Setup timer to fire at 1/HT intervals. */ + cr = 0xffffffff - (period - 1); + writel(cr, base + TIMER1_COUNT); + writel(cr, base + TIMER1_LOAD); + + /* enable interrupt on overflow */ + cr = readl(base + TIMER_INTR_MASK); + cr &= ~(TIMER_1_INT_MATCH1 | TIMER_1_INT_MATCH2); + cr |= TIMER_1_INT_OVERFLOW; + writel(cr, base + TIMER_INTR_MASK); + + /* Start the timer */ + cr = readl(base + TIMER_CR); + cr |= TIMER_1_CR_ENABLE; + cr |= TIMER_1_CR_INT; + writel(cr, base + TIMER_CR); + + return 0; +} + +/* Use TIMER1 as clock event */ +static struct clock_event_device fttmr010_clockevent = { + .name = "TIMER1", + /* Reasonably fast and accurate clock event */ + .rating = 300, + .shift = 32, + .features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT, + .set_next_event = fttmr010_timer_set_next_event, + .set_state_shutdown = fttmr010_timer_shutdown, + .set_state_periodic = fttmr010_timer_set_periodic, + .set_state_oneshot = fttmr010_timer_shutdown, + .tick_resume = fttmr010_timer_shutdown, +}; + +/* + * IRQ handler for the timer + */ +static irqreturn_t fttmr010_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = &fttmr010_clockevent; + + evt->event_handler(evt); + return IRQ_HANDLED; +} + +static struct irqaction fttmr010_timer_irq = { + .name = "Faraday FTTMR010 Timer Tick", + .flags = IRQF_TIMER, + .handler = fttmr010_timer_interrupt, +}; + +static int __init gemini_timer_of_init(struct device_node *np) +{ + static struct regmap *map; + int irq; + int ret; + u32 val; + + map = syscon_regmap_lookup_by_phandle(np, "syscon"); + if (IS_ERR(map)) { + pr_err("Can't get regmap for syscon handle"); + return -ENODEV; + } + ret = regmap_read(map, GLOBAL_STATUS, &val); + if (ret) { + pr_err("Can't read syscon status register"); + return -ENXIO; + } + + base = of_iomap(np, 0); + if (!base) { + pr_err("Can't remap registers"); + return -ENXIO; + } + /* IRQ for timer 1 */ + irq = irq_of_parse_and_map(np, 0); + if (irq <= 0) { + pr_err("Can't parse IRQ"); + return -EINVAL; + } + + tick_rate = REG_TO_AHB_SPEED(val) * 1000000; + printk(KERN_INFO "Bus: %dMHz", tick_rate / 1000000); + + tick_rate /= 6; /* APB bus run AHB*(1/6) */ + + switch (val & CPU_AHB_RATIO_MASK) { + case CPU_AHB_1_1: + printk(KERN_CONT "(1/1)\n"); + break; + case CPU_AHB_3_2: + printk(KERN_CONT "(3/2)\n"); + break; + case CPU_AHB_24_13: + printk(KERN_CONT "(24/13)\n"); + break; + case CPU_AHB_2_1: + printk(KERN_CONT "(2/1)\n"); + break; + } + + /* + * Reset the interrupt mask and status + */ + writel(TIMER_INT_ALL_MASK, base + TIMER_INTR_MASK); + writel(0, base + TIMER_INTR_STATE); + writel(TIMER_DEFAULT_FLAGS, base + TIMER_CR); + + /* + * Setup free-running clocksource timer (interrupts + * disabled.) + */ + writel(0, base + TIMER3_COUNT); + writel(0, base + TIMER3_LOAD); + writel(0, base + TIMER3_MATCH1); + writel(0, base + TIMER3_MATCH2); + clocksource_mmio_init(base + TIMER3_COUNT, + "fttmr010_clocksource", tick_rate, + 300, 32, clocksource_mmio_readl_up); + sched_clock_register(fttmr010_read_sched_clock, 32, tick_rate); + + /* + * Setup clockevent timer (interrupt-driven.) + */ + writel(0, base + TIMER1_COUNT); + writel(0, base + TIMER1_LOAD); + writel(0, base + TIMER1_MATCH1); + writel(0, base + TIMER1_MATCH2); + setup_irq(irq, &fttmr010_timer_irq); + fttmr010_clockevent.cpumask = cpumask_of(0); + clockevents_config_and_register(&fttmr010_clockevent, tick_rate, + 1, 0xffffffff); + + return 0; +} +CLOCKSOURCE_OF_DECLARE(gemini, "cortina,gemini-timer", gemini_timer_of_init); diff --git a/drivers/clocksource/timer-gemini.c b/drivers/clocksource/timer-gemini.c deleted file mode 100644 index dda27b7bf1a1..000000000000 --- a/drivers/clocksource/timer-gemini.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Gemini timer driver - * Copyright (C) 2017 Linus Walleij - * - * Based on a rewrite of arch/arm/mach-gemini/timer.c: - * Copyright (C) 2001-2006 Storlink, Corp. - * Copyright (C) 2008-2009 Paulius Zaleckas - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Relevant registers in the global syscon - */ -#define GLOBAL_STATUS 0x04 -#define CPU_AHB_RATIO_MASK (0x3 << 18) -#define CPU_AHB_1_1 (0x0 << 18) -#define CPU_AHB_3_2 (0x1 << 18) -#define CPU_AHB_24_13 (0x2 << 18) -#define CPU_AHB_2_1 (0x3 << 18) -#define REG_TO_AHB_SPEED(reg) ((((reg) >> 15) & 0x7) * 10 + 130) - -/* - * Register definitions for the timers - */ -#define TIMER1_COUNT (0x00) -#define TIMER1_LOAD (0x04) -#define TIMER1_MATCH1 (0x08) -#define TIMER1_MATCH2 (0x0c) -#define TIMER2_COUNT (0x10) -#define TIMER2_LOAD (0x14) -#define TIMER2_MATCH1 (0x18) -#define TIMER2_MATCH2 (0x1c) -#define TIMER3_COUNT (0x20) -#define TIMER3_LOAD (0x24) -#define TIMER3_MATCH1 (0x28) -#define TIMER3_MATCH2 (0x2c) -#define TIMER_CR (0x30) -#define TIMER_INTR_STATE (0x34) -#define TIMER_INTR_MASK (0x38) - -#define TIMER_1_CR_ENABLE (1 << 0) -#define TIMER_1_CR_CLOCK (1 << 1) -#define TIMER_1_CR_INT (1 << 2) -#define TIMER_2_CR_ENABLE (1 << 3) -#define TIMER_2_CR_CLOCK (1 << 4) -#define TIMER_2_CR_INT (1 << 5) -#define TIMER_3_CR_ENABLE (1 << 6) -#define TIMER_3_CR_CLOCK (1 << 7) -#define TIMER_3_CR_INT (1 << 8) -#define TIMER_1_CR_UPDOWN (1 << 9) -#define TIMER_2_CR_UPDOWN (1 << 10) -#define TIMER_3_CR_UPDOWN (1 << 11) -#define TIMER_DEFAULT_FLAGS (TIMER_1_CR_UPDOWN | \ - TIMER_3_CR_ENABLE | \ - TIMER_3_CR_UPDOWN) - -#define TIMER_1_INT_MATCH1 (1 << 0) -#define TIMER_1_INT_MATCH2 (1 << 1) -#define TIMER_1_INT_OVERFLOW (1 << 2) -#define TIMER_2_INT_MATCH1 (1 << 3) -#define TIMER_2_INT_MATCH2 (1 << 4) -#define TIMER_2_INT_OVERFLOW (1 << 5) -#define TIMER_3_INT_MATCH1 (1 << 6) -#define TIMER_3_INT_MATCH2 (1 << 7) -#define TIMER_3_INT_OVERFLOW (1 << 8) -#define TIMER_INT_ALL_MASK 0x1ff - -static unsigned int tick_rate; -static void __iomem *base; - -static u64 notrace gemini_read_sched_clock(void) -{ - return readl(base + TIMER3_COUNT); -} - -static int gemini_timer_set_next_event(unsigned long cycles, - struct clock_event_device *evt) -{ - u32 cr; - - /* Setup the match register */ - cr = readl(base + TIMER1_COUNT); - writel(cr + cycles, base + TIMER1_MATCH1); - if (readl(base + TIMER1_COUNT) - cr > cycles) - return -ETIME; - - return 0; -} - -static int gemini_timer_shutdown(struct clock_event_device *evt) -{ - u32 cr; - - /* - * Disable also for oneshot: the set_next() call will arm the timer - * instead. - */ - /* Stop timer and interrupt. */ - cr = readl(base + TIMER_CR); - cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT); - writel(cr, base + TIMER_CR); - - /* Setup counter start from 0 */ - writel(0, base + TIMER1_COUNT); - writel(0, base + TIMER1_LOAD); - - /* enable interrupt */ - cr = readl(base + TIMER_INTR_MASK); - cr &= ~(TIMER_1_INT_OVERFLOW | TIMER_1_INT_MATCH2); - cr |= TIMER_1_INT_MATCH1; - writel(cr, base + TIMER_INTR_MASK); - - /* start the timer */ - cr = readl(base + TIMER_CR); - cr |= TIMER_1_CR_ENABLE; - writel(cr, base + TIMER_CR); - - return 0; -} - -static int gemini_timer_set_periodic(struct clock_event_device *evt) -{ - u32 period = DIV_ROUND_CLOSEST(tick_rate, HZ); - u32 cr; - - /* Stop timer and interrupt */ - cr = readl(base + TIMER_CR); - cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT); - writel(cr, base + TIMER_CR); - - /* Setup timer to fire at 1/HT intervals. */ - cr = 0xffffffff - (period - 1); - writel(cr, base + TIMER1_COUNT); - writel(cr, base + TIMER1_LOAD); - - /* enable interrupt on overflow */ - cr = readl(base + TIMER_INTR_MASK); - cr &= ~(TIMER_1_INT_MATCH1 | TIMER_1_INT_MATCH2); - cr |= TIMER_1_INT_OVERFLOW; - writel(cr, base + TIMER_INTR_MASK); - - /* Start the timer */ - cr = readl(base + TIMER_CR); - cr |= TIMER_1_CR_ENABLE; - cr |= TIMER_1_CR_INT; - writel(cr, base + TIMER_CR); - - return 0; -} - -/* Use TIMER1 as clock event */ -static struct clock_event_device gemini_clockevent = { - .name = "TIMER1", - /* Reasonably fast and accurate clock event */ - .rating = 300, - .shift = 32, - .features = CLOCK_EVT_FEAT_PERIODIC | - CLOCK_EVT_FEAT_ONESHOT, - .set_next_event = gemini_timer_set_next_event, - .set_state_shutdown = gemini_timer_shutdown, - .set_state_periodic = gemini_timer_set_periodic, - .set_state_oneshot = gemini_timer_shutdown, - .tick_resume = gemini_timer_shutdown, -}; - -/* - * IRQ handler for the timer - */ -static irqreturn_t gemini_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = &gemini_clockevent; - - evt->event_handler(evt); - return IRQ_HANDLED; -} - -static struct irqaction gemini_timer_irq = { - .name = "Gemini Timer Tick", - .flags = IRQF_TIMER, - .handler = gemini_timer_interrupt, -}; - -static int __init gemini_timer_of_init(struct device_node *np) -{ - static struct regmap *map; - int irq; - int ret; - u32 val; - - map = syscon_regmap_lookup_by_phandle(np, "syscon"); - if (IS_ERR(map)) { - pr_err("Can't get regmap for syscon handle"); - return -ENODEV; - } - ret = regmap_read(map, GLOBAL_STATUS, &val); - if (ret) { - pr_err("Can't read syscon status register"); - return -ENXIO; - } - - base = of_iomap(np, 0); - if (!base) { - pr_err("Can't remap registers"); - return -ENXIO; - } - /* IRQ for timer 1 */ - irq = irq_of_parse_and_map(np, 0); - if (irq <= 0) { - pr_err("Can't parse IRQ"); - return -EINVAL; - } - - tick_rate = REG_TO_AHB_SPEED(val) * 1000000; - printk(KERN_INFO "Bus: %dMHz", tick_rate / 1000000); - - tick_rate /= 6; /* APB bus run AHB*(1/6) */ - - switch (val & CPU_AHB_RATIO_MASK) { - case CPU_AHB_1_1: - printk(KERN_CONT "(1/1)\n"); - break; - case CPU_AHB_3_2: - printk(KERN_CONT "(3/2)\n"); - break; - case CPU_AHB_24_13: - printk(KERN_CONT "(24/13)\n"); - break; - case CPU_AHB_2_1: - printk(KERN_CONT "(2/1)\n"); - break; - } - - /* - * Reset the interrupt mask and status - */ - writel(TIMER_INT_ALL_MASK, base + TIMER_INTR_MASK); - writel(0, base + TIMER_INTR_STATE); - writel(TIMER_DEFAULT_FLAGS, base + TIMER_CR); - - /* - * Setup free-running clocksource timer (interrupts - * disabled.) - */ - writel(0, base + TIMER3_COUNT); - writel(0, base + TIMER3_LOAD); - writel(0, base + TIMER3_MATCH1); - writel(0, base + TIMER3_MATCH2); - clocksource_mmio_init(base + TIMER3_COUNT, - "gemini_clocksource", tick_rate, - 300, 32, clocksource_mmio_readl_up); - sched_clock_register(gemini_read_sched_clock, 32, tick_rate); - - /* - * Setup clockevent timer (interrupt-driven.) - */ - writel(0, base + TIMER1_COUNT); - writel(0, base + TIMER1_LOAD); - writel(0, base + TIMER1_MATCH1); - writel(0, base + TIMER1_MATCH2); - setup_irq(irq, &gemini_timer_irq); - gemini_clockevent.cpumask = cpumask_of(0); - clockevents_config_and_register(&gemini_clockevent, tick_rate, - 1, 0xffffffff); - - return 0; -} -CLOCKSOURCE_OF_DECLARE(nomadik_mtu, "cortina,gemini-timer", - gemini_timer_of_init); -- cgit v1.2.3 From 28e71e2fe8fe6cdbd1bdc61601ea50d6423d3cf0 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 24 Mar 2017 22:32:35 +0100 Subject: clocksource/drivers/fttmr010: Refactor to handle clock The plain Faraday FTTMR010 timer needs a clock to figure out its tick rate, and the gemini reads it directly from the system controller set-up. Split the init function and add two paths for the two compatible-strings. We only support clocking using PCLK because of lack of documentation on how EXTCLK works. The Gemini still works like before, but we can also support a generic, clock-based version. Signed-off-by: Linus Walleij Signed-off-by: Daniel Lezcano --- drivers/clocksource/timer-fttmr010.c | 119 +++++++++++++++++++++-------------- 1 file changed, 73 insertions(+), 46 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-fttmr010.c b/drivers/clocksource/timer-fttmr010.c index e37ec3d69a7e..b4a6f1e4bc54 100644 --- a/drivers/clocksource/timer-fttmr010.c +++ b/drivers/clocksource/timer-fttmr010.c @@ -16,17 +16,7 @@ #include #include #include - -/* - * Relevant registers in the global syscon - */ -#define GLOBAL_STATUS 0x04 -#define CPU_AHB_RATIO_MASK (0x3 << 18) -#define CPU_AHB_1_1 (0x0 << 18) -#define CPU_AHB_3_2 (0x1 << 18) -#define CPU_AHB_24_13 (0x2 << 18) -#define CPU_AHB_2_1 (0x3 << 18) -#define REG_TO_AHB_SPEED(reg) ((((reg) >> 15) & 0x7) * 10 + 130) +#include /* * Register definitions for the timers @@ -189,23 +179,9 @@ static struct irqaction fttmr010_timer_irq = { .handler = fttmr010_timer_interrupt, }; -static int __init gemini_timer_of_init(struct device_node *np) +static int __init fttmr010_timer_common_init(struct device_node *np) { - static struct regmap *map; int irq; - int ret; - u32 val; - - map = syscon_regmap_lookup_by_phandle(np, "syscon"); - if (IS_ERR(map)) { - pr_err("Can't get regmap for syscon handle"); - return -ENODEV; - } - ret = regmap_read(map, GLOBAL_STATUS, &val); - if (ret) { - pr_err("Can't read syscon status register"); - return -ENXIO; - } base = of_iomap(np, 0); if (!base) { @@ -219,26 +195,6 @@ static int __init gemini_timer_of_init(struct device_node *np) return -EINVAL; } - tick_rate = REG_TO_AHB_SPEED(val) * 1000000; - printk(KERN_INFO "Bus: %dMHz", tick_rate / 1000000); - - tick_rate /= 6; /* APB bus run AHB*(1/6) */ - - switch (val & CPU_AHB_RATIO_MASK) { - case CPU_AHB_1_1: - printk(KERN_CONT "(1/1)\n"); - break; - case CPU_AHB_3_2: - printk(KERN_CONT "(3/2)\n"); - break; - case CPU_AHB_24_13: - printk(KERN_CONT "(24/13)\n"); - break; - case CPU_AHB_2_1: - printk(KERN_CONT "(2/1)\n"); - break; - } - /* * Reset the interrupt mask and status */ @@ -273,4 +229,75 @@ static int __init gemini_timer_of_init(struct device_node *np) return 0; } + +static int __init fttmr010_timer_of_init(struct device_node *np) +{ + /* + * These implementations require a clock reference. + * FIXME: we currently only support clocking using PCLK + * and using EXTCLK is not supported in the driver. + */ + struct clk *clk; + + clk = of_clk_get_by_name(np, "PCLK"); + if (IS_ERR(clk)) { + pr_err("could not get PCLK"); + return PTR_ERR(clk); + } + tick_rate = clk_get_rate(clk); + + return fttmr010_timer_common_init(np); +} +CLOCKSOURCE_OF_DECLARE(fttmr010, "faraday,fttmr010", fttmr010_timer_of_init); + +/* + * Gemini-specific: relevant registers in the global syscon + */ +#define GLOBAL_STATUS 0x04 +#define CPU_AHB_RATIO_MASK (0x3 << 18) +#define CPU_AHB_1_1 (0x0 << 18) +#define CPU_AHB_3_2 (0x1 << 18) +#define CPU_AHB_24_13 (0x2 << 18) +#define CPU_AHB_2_1 (0x3 << 18) +#define REG_TO_AHB_SPEED(reg) ((((reg) >> 15) & 0x7) * 10 + 130) + +static int __init gemini_timer_of_init(struct device_node *np) +{ + static struct regmap *map; + int ret; + u32 val; + + map = syscon_regmap_lookup_by_phandle(np, "syscon"); + if (IS_ERR(map)) { + pr_err("Can't get regmap for syscon handle\n"); + return -ENODEV; + } + ret = regmap_read(map, GLOBAL_STATUS, &val); + if (ret) { + pr_err("Can't read syscon status register\n"); + return -ENXIO; + } + + tick_rate = REG_TO_AHB_SPEED(val) * 1000000; + pr_info("Bus: %dMHz ", tick_rate / 1000000); + + tick_rate /= 6; /* APB bus run AHB*(1/6) */ + + switch (val & CPU_AHB_RATIO_MASK) { + case CPU_AHB_1_1: + pr_cont("(1/1)\n"); + break; + case CPU_AHB_3_2: + pr_cont("(3/2)\n"); + break; + case CPU_AHB_24_13: + pr_cont("(24/13)\n"); + break; + case CPU_AHB_2_1: + pr_cont("(2/1)\n"); + break; + } + + return fttmr010_timer_common_init(np); +} CLOCKSOURCE_OF_DECLARE(gemini, "cortina,gemini-timer", gemini_timer_of_init); -- cgit v1.2.3 From ded24019b6b6f18ed079bbabc89832cd68959748 Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Wed, 18 Jan 2017 21:25:25 +0800 Subject: clocksource: arm_arch_timer: clean up printk usage Almost all string in the arm_arch_timer driver duplicate an common prefix (though a few do not). For consistency, it would be better to use pr_fmt(), and always use this prefix. At the same time, we may as well clean up some whitespace issues in arch_timer_banner and arch_timer_init. No functional change. Signed-off-by: Fu Wei Acked-by: Mark Rutland Tested-by: Xiongfeng Wang [Mark: reword commit message] Signed-off-by: Mark Rutland --- drivers/clocksource/arm_arch_timer.c | 49 ++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 24 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index bf9e9d76375e..467ee6197c3f 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -33,6 +33,9 @@ #include +#undef pr_fmt +#define pr_fmt(fmt) "arch_timer: " fmt + #define CNTTIDR 0x08 #define CNTTIDR_VIRT(n) (BIT(1) << ((n) * 4)) @@ -846,22 +849,22 @@ arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np) /* Check the timer frequency. */ if (arch_timer_rate == 0) - pr_warn("Architected timer frequency not available\n"); + pr_warn("frequency not available\n"); } static void arch_timer_banner(unsigned type) { - pr_info("Architected %s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n", - type & ARCH_CP15_TIMER ? "cp15" : "", - type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ? " and " : "", - type & ARCH_MEM_TIMER ? "mmio" : "", - (unsigned long)arch_timer_rate / 1000000, - (unsigned long)(arch_timer_rate / 10000) % 100, - type & ARCH_CP15_TIMER ? - (arch_timer_uses_ppi == VIRT_PPI) ? "virt" : "phys" : + pr_info("%s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n", + type & ARCH_CP15_TIMER ? "cp15" : "", + type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ? " and " : "", + type & ARCH_MEM_TIMER ? "mmio" : "", + (unsigned long)arch_timer_rate / 1000000, + (unsigned long)(arch_timer_rate / 10000) % 100, + type & ARCH_CP15_TIMER ? + (arch_timer_uses_ppi == VIRT_PPI) ? "virt" : "phys" : "", - type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ? "/" : "", - type & ARCH_MEM_TIMER ? + type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ? "/" : "", + type & ARCH_MEM_TIMER ? arch_timer_mem_use_virtual ? "virt" : "phys" : ""); } @@ -922,8 +925,7 @@ static void __init arch_counter_register(unsigned type) static void arch_timer_stop(struct clock_event_device *clk) { - pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n", - clk->irq, smp_processor_id()); + pr_debug("disable IRQ%d cpu #%d\n", clk->irq, smp_processor_id()); disable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi]); if (arch_timer_has_nonsecure_ppi()) @@ -1016,8 +1018,7 @@ static int __init arch_timer_register(void) } if (err) { - pr_err("arch_timer: can't register interrupt %d (%d)\n", - ppi, err); + pr_err("can't register interrupt %d (%d)\n", ppi, err); goto out_free; } @@ -1070,7 +1071,7 @@ static int __init arch_timer_mem_register(void __iomem *base, unsigned int irq) ret = request_irq(irq, func, IRQF_TIMER, "arch_mem_timer", &t->evt); if (ret) { - pr_err("arch_timer: Failed to request mem timer irq\n"); + pr_err("Failed to request mem timer irq\n"); kfree(t); } @@ -1148,7 +1149,7 @@ static int __init arch_timer_init(void) } if (!has_ppi) { - pr_warn("arch_timer: No interrupt available, giving up\n"); + pr_warn("No interrupt available, giving up\n"); return -EINVAL; } } @@ -1162,7 +1163,7 @@ static int __init arch_timer_init(void) return ret; arch_timer_kvm_info.virtual_irq = arch_timer_ppi[VIRT_PPI]; - + return 0; } @@ -1171,7 +1172,7 @@ static int __init arch_timer_of_init(struct device_node *np) int i; if (arch_timers_present & ARCH_CP15_TIMER) { - pr_warn("arch_timer: multiple nodes in dt, skipping\n"); + pr_warn("multiple nodes in dt, skipping\n"); return 0; } @@ -1213,7 +1214,7 @@ static int __init arch_timer_mem_init(struct device_node *np) arch_timers_present |= ARCH_MEM_TIMER; cntctlbase = of_iomap(np, 0); if (!cntctlbase) { - pr_err("arch_timer: Can't find CNTCTLBase\n"); + pr_err("Can't find CNTCTLBase\n"); return -ENXIO; } @@ -1228,7 +1229,7 @@ static int __init arch_timer_mem_init(struct device_node *np) u32 cntacr; if (of_property_read_u32(frame, "frame-number", &n)) { - pr_err("arch_timer: Missing frame-number\n"); + pr_err("Missing frame-number\n"); of_node_put(frame); goto out; } @@ -1258,7 +1259,7 @@ static int __init arch_timer_mem_init(struct device_node *np) base = arch_counter_base = of_io_request_and_map(best_frame, 0, "arch_mem_timer"); if (IS_ERR(base)) { - pr_err("arch_timer: Can't map frame's registers\n"); + pr_err("Can't map frame's registers\n"); goto out; } @@ -1269,7 +1270,7 @@ static int __init arch_timer_mem_init(struct device_node *np) ret = -EINVAL; if (!irq) { - pr_err("arch_timer: Frame missing %s irq", + pr_err("Frame missing %s irq.\n", arch_timer_mem_use_virtual ? "virt" : "phys"); goto out; } @@ -1311,7 +1312,7 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table) struct acpi_table_gtdt *gtdt; if (arch_timers_present & ARCH_CP15_TIMER) { - pr_warn("arch_timer: already initialized, skipping\n"); + pr_warn("already initialized, skipping\n"); return -EINVAL; } -- cgit v1.2.3 From 8a5c21dc05ea44d0e7255c88f8f56af0971bbc68 Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Wed, 18 Jan 2017 21:25:26 +0800 Subject: clocksource: arm_arch_timer: rename type macros In preparation for moving the type macros out into a header, rename these so they are namespaced w.r.t. the arch timer. We'll apply the same prefix to other definitions in subsequent patches. This will aid consistency and avoid potential name clahses when this move occurs. No functional change. Signed-off-by: Fu Wei Tested-by: Xiongfeng Wang [Mark: reword commit message] Signed-off-by: Mark Rutland --- drivers/clocksource/arm_arch_timer.c | 43 +++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 20 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 467ee6197c3f..38bddb9a2076 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -55,8 +55,8 @@ #define CNTV_TVAL 0x38 #define CNTV_CTL 0x3c -#define ARCH_CP15_TIMER BIT(0) -#define ARCH_MEM_TIMER BIT(1) +#define ARCH_TIMER_TYPE_CP15 BIT(0) +#define ARCH_TIMER_TYPE_MEM BIT(1) static unsigned arch_timers_present __initdata; static void __iomem *arch_counter_base; @@ -686,7 +686,7 @@ static void __arch_timer_setup(unsigned type, { clk->features = CLOCK_EVT_FEAT_ONESHOT; - if (type == ARCH_CP15_TIMER) { + if (type == ARCH_TIMER_TYPE_CP15) { if (arch_timer_c3stop) clk->features |= CLOCK_EVT_FEAT_C3STOP; clk->name = "arch_sys_timer"; @@ -811,7 +811,7 @@ static int arch_timer_starting_cpu(unsigned int cpu) struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt); u32 flags; - __arch_timer_setup(ARCH_CP15_TIMER, clk); + __arch_timer_setup(ARCH_TIMER_TYPE_CP15, clk); flags = check_ppi_trigger(arch_timer_ppi[arch_timer_uses_ppi]); enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], flags); @@ -855,16 +855,17 @@ arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np) static void arch_timer_banner(unsigned type) { pr_info("%s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n", - type & ARCH_CP15_TIMER ? "cp15" : "", - type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ? " and " : "", - type & ARCH_MEM_TIMER ? "mmio" : "", + type & ARCH_TIMER_TYPE_CP15 ? "cp15" : "", + type == (ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM) ? + " and " : "", + type & ARCH_TIMER_TYPE_MEM ? "mmio" : "", (unsigned long)arch_timer_rate / 1000000, (unsigned long)(arch_timer_rate / 10000) % 100, - type & ARCH_CP15_TIMER ? + type & ARCH_TIMER_TYPE_CP15 ? (arch_timer_uses_ppi == VIRT_PPI) ? "virt" : "phys" : "", - type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ? "/" : "", - type & ARCH_MEM_TIMER ? + type == (ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM) ? "/" : "", + type & ARCH_TIMER_TYPE_MEM ? arch_timer_mem_use_virtual ? "virt" : "phys" : ""); } @@ -899,7 +900,7 @@ static void __init arch_counter_register(unsigned type) u64 start_count; /* Register the CP15 based counter if we have one */ - if (type & ARCH_CP15_TIMER) { + if (type & ARCH_TIMER_TYPE_CP15) { if (IS_ENABLED(CONFIG_ARM64) || arch_timer_uses_ppi == VIRT_PPI) arch_timer_read_counter = arch_counter_get_cntvct; else @@ -1062,7 +1063,7 @@ static int __init arch_timer_mem_register(void __iomem *base, unsigned int irq) t->base = base; t->evt.irq = irq; - __arch_timer_setup(ARCH_MEM_TIMER, &t->evt); + __arch_timer_setup(ARCH_TIMER_TYPE_MEM, &t->evt); if (arch_timer_mem_use_virtual) func = arch_timer_handler_virt_mem; @@ -1105,13 +1106,15 @@ arch_timer_needs_probing(int type, const struct of_device_id *matches) static int __init arch_timer_common_init(void) { - unsigned mask = ARCH_CP15_TIMER | ARCH_MEM_TIMER; + unsigned mask = ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM; /* Wait until both nodes are probed if we have two timers */ if ((arch_timers_present & mask) != mask) { - if (arch_timer_needs_probing(ARCH_MEM_TIMER, arch_timer_mem_of_match)) + if (arch_timer_needs_probing(ARCH_TIMER_TYPE_MEM, + arch_timer_mem_of_match)) return 0; - if (arch_timer_needs_probing(ARCH_CP15_TIMER, arch_timer_of_match)) + if (arch_timer_needs_probing(ARCH_TIMER_TYPE_CP15, + arch_timer_of_match)) return 0; } @@ -1171,12 +1174,12 @@ static int __init arch_timer_of_init(struct device_node *np) { int i; - if (arch_timers_present & ARCH_CP15_TIMER) { + if (arch_timers_present & ARCH_TIMER_TYPE_CP15) { pr_warn("multiple nodes in dt, skipping\n"); return 0; } - arch_timers_present |= ARCH_CP15_TIMER; + arch_timers_present |= ARCH_TIMER_TYPE_CP15; for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++) arch_timer_ppi[i] = irq_of_parse_and_map(np, i); @@ -1211,7 +1214,7 @@ static int __init arch_timer_mem_init(struct device_node *np) unsigned int irq, ret = -EINVAL; u32 cnttidr; - arch_timers_present |= ARCH_MEM_TIMER; + arch_timers_present |= ARCH_TIMER_TYPE_MEM; cntctlbase = of_iomap(np, 0); if (!cntctlbase) { pr_err("Can't find CNTCTLBase\n"); @@ -1311,14 +1314,14 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table) { struct acpi_table_gtdt *gtdt; - if (arch_timers_present & ARCH_CP15_TIMER) { + if (arch_timers_present & ARCH_TIMER_TYPE_CP15) { pr_warn("already initialized, skipping\n"); return -EINVAL; } gtdt = container_of(table, struct acpi_table_gtdt, header); - arch_timers_present |= ARCH_CP15_TIMER; + arch_timers_present |= ARCH_TIMER_TYPE_CP15; arch_timer_ppi[PHYS_SECURE_PPI] = map_generic_timer_interrupt(gtdt->secure_el1_interrupt, -- cgit v1.2.3 From ee34f1e63d3d2b8df8607847eafbc859ec6818dc Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Wed, 18 Jan 2017 21:25:27 +0800 Subject: clocksource: arm_arch_timer: rename the PPI enum In preparation for moving the PPI enum out into a header, rename the enum and its constituent values these so they are namespaced w.r.t. the arch timer. This will aid consistency and avoid potential name clashes when this move occurs. No functional change. Signed-off-by: Fu Wei Tested-by: Xiongfeng Wang [Mark: reword commit message] Signed-off-by: Mark Rutland --- drivers/clocksource/arm_arch_timer.c | 82 ++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 40 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 38bddb9a2076..94e355bb0d38 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -70,19 +70,19 @@ struct arch_timer { static u32 arch_timer_rate; -enum ppi_nr { - PHYS_SECURE_PPI, - PHYS_NONSECURE_PPI, - VIRT_PPI, - HYP_PPI, - MAX_TIMER_PPI +enum arch_timer_ppi_nr { + ARCH_TIMER_PHYS_SECURE_PPI, + ARCH_TIMER_PHYS_NONSECURE_PPI, + ARCH_TIMER_VIRT_PPI, + ARCH_TIMER_HYP_PPI, + ARCH_TIMER_MAX_TIMER_PPI }; -static int arch_timer_ppi[MAX_TIMER_PPI]; +static int arch_timer_ppi[ARCH_TIMER_MAX_TIMER_PPI]; static struct clock_event_device __percpu *arch_timer_evt; -static enum ppi_nr arch_timer_uses_ppi = VIRT_PPI; +static enum arch_timer_ppi_nr arch_timer_uses_ppi = ARCH_TIMER_VIRT_PPI; static bool arch_timer_c3stop; static bool arch_timer_mem_use_virtual; static bool arch_counter_suspend_stop; @@ -694,14 +694,14 @@ static void __arch_timer_setup(unsigned type, clk->cpumask = cpumask_of(smp_processor_id()); clk->irq = arch_timer_ppi[arch_timer_uses_ppi]; switch (arch_timer_uses_ppi) { - case VIRT_PPI: + case ARCH_TIMER_VIRT_PPI: clk->set_state_shutdown = arch_timer_shutdown_virt; clk->set_state_oneshot_stopped = arch_timer_shutdown_virt; clk->set_next_event = arch_timer_set_next_event_virt; break; - case PHYS_SECURE_PPI: - case PHYS_NONSECURE_PPI: - case HYP_PPI: + case ARCH_TIMER_PHYS_SECURE_PPI: + case ARCH_TIMER_PHYS_NONSECURE_PPI: + case ARCH_TIMER_HYP_PPI: clk->set_state_shutdown = arch_timer_shutdown_phys; clk->set_state_oneshot_stopped = arch_timer_shutdown_phys; clk->set_next_event = arch_timer_set_next_event_phys; @@ -789,8 +789,8 @@ static void arch_counter_set_user_access(void) static bool arch_timer_has_nonsecure_ppi(void) { - return (arch_timer_uses_ppi == PHYS_SECURE_PPI && - arch_timer_ppi[PHYS_NONSECURE_PPI]); + return (arch_timer_uses_ppi == ARCH_TIMER_PHYS_SECURE_PPI && + arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]); } static u32 check_ppi_trigger(int irq) @@ -817,8 +817,9 @@ static int arch_timer_starting_cpu(unsigned int cpu) enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], flags); if (arch_timer_has_nonsecure_ppi()) { - flags = check_ppi_trigger(arch_timer_ppi[PHYS_NONSECURE_PPI]); - enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], flags); + flags = check_ppi_trigger(arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]); + enable_percpu_irq(arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI], + flags); } arch_counter_set_user_access(); @@ -862,7 +863,7 @@ static void arch_timer_banner(unsigned type) (unsigned long)arch_timer_rate / 1000000, (unsigned long)(arch_timer_rate / 10000) % 100, type & ARCH_TIMER_TYPE_CP15 ? - (arch_timer_uses_ppi == VIRT_PPI) ? "virt" : "phys" : + (arch_timer_uses_ppi == ARCH_TIMER_VIRT_PPI) ? "virt" : "phys" : "", type == (ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM) ? "/" : "", type & ARCH_TIMER_TYPE_MEM ? @@ -901,7 +902,8 @@ static void __init arch_counter_register(unsigned type) /* Register the CP15 based counter if we have one */ if (type & ARCH_TIMER_TYPE_CP15) { - if (IS_ENABLED(CONFIG_ARM64) || arch_timer_uses_ppi == VIRT_PPI) + if (IS_ENABLED(CONFIG_ARM64) || + arch_timer_uses_ppi == ARCH_TIMER_VIRT_PPI) arch_timer_read_counter = arch_counter_get_cntvct; else arch_timer_read_counter = arch_counter_get_cntpct; @@ -930,7 +932,7 @@ static void arch_timer_stop(struct clock_event_device *clk) disable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi]); if (arch_timer_has_nonsecure_ppi()) - disable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI]); + disable_percpu_irq(arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]); clk->set_state_shutdown(clk); } @@ -993,24 +995,24 @@ static int __init arch_timer_register(void) ppi = arch_timer_ppi[arch_timer_uses_ppi]; switch (arch_timer_uses_ppi) { - case VIRT_PPI: + case ARCH_TIMER_VIRT_PPI: err = request_percpu_irq(ppi, arch_timer_handler_virt, "arch_timer", arch_timer_evt); break; - case PHYS_SECURE_PPI: - case PHYS_NONSECURE_PPI: + case ARCH_TIMER_PHYS_SECURE_PPI: + case ARCH_TIMER_PHYS_NONSECURE_PPI: err = request_percpu_irq(ppi, arch_timer_handler_phys, "arch_timer", arch_timer_evt); - if (!err && arch_timer_ppi[PHYS_NONSECURE_PPI]) { - ppi = arch_timer_ppi[PHYS_NONSECURE_PPI]; + if (!err && arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]) { + ppi = arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]; err = request_percpu_irq(ppi, arch_timer_handler_phys, "arch_timer", arch_timer_evt); if (err) - free_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI], + free_percpu_irq(arch_timer_ppi[ARCH_TIMER_PHYS_SECURE_PPI], arch_timer_evt); } break; - case HYP_PPI: + case ARCH_TIMER_HYP_PPI: err = request_percpu_irq(ppi, arch_timer_handler_phys, "arch_timer", arch_timer_evt); break; @@ -1042,7 +1044,7 @@ out_unreg_cpupm: out_unreg_notify: free_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], arch_timer_evt); if (arch_timer_has_nonsecure_ppi()) - free_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], + free_percpu_irq(arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI], arch_timer_evt); out_free: @@ -1139,16 +1141,16 @@ static int __init arch_timer_init(void) * their CNTHP_*_EL2 counterparts, and use a different PPI * number. */ - if (is_hyp_mode_available() || !arch_timer_ppi[VIRT_PPI]) { + if (is_hyp_mode_available() || !arch_timer_ppi[ARCH_TIMER_VIRT_PPI]) { bool has_ppi; if (is_kernel_in_hyp_mode()) { - arch_timer_uses_ppi = HYP_PPI; - has_ppi = !!arch_timer_ppi[HYP_PPI]; + arch_timer_uses_ppi = ARCH_TIMER_HYP_PPI; + has_ppi = !!arch_timer_ppi[ARCH_TIMER_HYP_PPI]; } else { - arch_timer_uses_ppi = PHYS_SECURE_PPI; - has_ppi = (!!arch_timer_ppi[PHYS_SECURE_PPI] || - !!arch_timer_ppi[PHYS_NONSECURE_PPI]); + arch_timer_uses_ppi = ARCH_TIMER_PHYS_SECURE_PPI; + has_ppi = (!!arch_timer_ppi[ARCH_TIMER_PHYS_SECURE_PPI] || + !!arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]); } if (!has_ppi) { @@ -1165,7 +1167,7 @@ static int __init arch_timer_init(void) if (ret) return ret; - arch_timer_kvm_info.virtual_irq = arch_timer_ppi[VIRT_PPI]; + arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI]; return 0; } @@ -1180,7 +1182,7 @@ static int __init arch_timer_of_init(struct device_node *np) } arch_timers_present |= ARCH_TIMER_TYPE_CP15; - for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++) + for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; i++) arch_timer_ppi[i] = irq_of_parse_and_map(np, i); arch_timer_detect_rate(NULL, np); @@ -1196,7 +1198,7 @@ static int __init arch_timer_of_init(struct device_node *np) */ if (IS_ENABLED(CONFIG_ARM) && of_property_read_bool(np, "arm,cpu-registers-not-fw-configured")) - arch_timer_uses_ppi = PHYS_SECURE_PPI; + arch_timer_uses_ppi = ARCH_TIMER_PHYS_SECURE_PPI; /* On some systems, the counter stops ticking when in suspend. */ arch_counter_suspend_stop = of_property_read_bool(np, @@ -1323,19 +1325,19 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table) arch_timers_present |= ARCH_TIMER_TYPE_CP15; - arch_timer_ppi[PHYS_SECURE_PPI] = + arch_timer_ppi[ARCH_TIMER_PHYS_SECURE_PPI] = map_generic_timer_interrupt(gtdt->secure_el1_interrupt, gtdt->secure_el1_flags); - arch_timer_ppi[PHYS_NONSECURE_PPI] = + arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI] = map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt, gtdt->non_secure_el1_flags); - arch_timer_ppi[VIRT_PPI] = + arch_timer_ppi[ARCH_TIMER_VIRT_PPI] = map_generic_timer_interrupt(gtdt->virtual_timer_interrupt, gtdt->virtual_timer_flags); - arch_timer_ppi[HYP_PPI] = + arch_timer_ppi[ARCH_TIMER_HYP_PPI] = map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt, gtdt->non_secure_el2_flags); -- cgit v1.2.3 From 831610c08e63b69b141c446c78eb9e9315660a5d Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Wed, 18 Jan 2017 21:25:28 +0800 Subject: clocksource: arm_arch_timer: move enums and defines to header file To support the arm_arch_timer via ACPI we need to share defines and enums between the driver and the ACPI parser code. So we split out the relevant defines and enums into arm_arch_timer.h. No functional change. Signed-off-by: Fu Wei Acked-by: Mark Rutland Tested-by: Xiongfeng Wang Signed-off-by: Mark Rutland --- drivers/clocksource/arm_arch_timer.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 94e355bb0d38..04218c1043e1 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -55,8 +55,6 @@ #define CNTV_TVAL 0x38 #define CNTV_CTL 0x3c -#define ARCH_TIMER_TYPE_CP15 BIT(0) -#define ARCH_TIMER_TYPE_MEM BIT(1) static unsigned arch_timers_present __initdata; static void __iomem *arch_counter_base; @@ -69,15 +67,6 @@ struct arch_timer { #define to_arch_timer(e) container_of(e, struct arch_timer, evt) static u32 arch_timer_rate; - -enum arch_timer_ppi_nr { - ARCH_TIMER_PHYS_SECURE_PPI, - ARCH_TIMER_PHYS_NONSECURE_PPI, - ARCH_TIMER_VIRT_PPI, - ARCH_TIMER_HYP_PPI, - ARCH_TIMER_MAX_TIMER_PPI -}; - static int arch_timer_ppi[ARCH_TIMER_MAX_TIMER_PPI]; static struct clock_event_device __percpu *arch_timer_evt; -- cgit v1.2.3 From 097cd143dd871bfceacf4ed252b177cf515a1888 Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Wed, 18 Jan 2017 21:25:29 +0800 Subject: clocksource: arm_arch_timer: add a new enum for spi type This patch add a new enum "arch_timer_spi_nr" and use it in the driver. Just for code's readability, no functional change. Signed-off-by: Fu Wei Acked-by: Mark Rutland Signed-off-by: Mark Rutland --- drivers/clocksource/arm_arch_timer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 04218c1043e1..15059c958be7 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -1258,9 +1258,9 @@ static int __init arch_timer_mem_init(struct device_node *np) } if (arch_timer_mem_use_virtual) - irq = irq_of_parse_and_map(best_frame, 1); + irq = irq_of_parse_and_map(best_frame, ARCH_TIMER_VIRT_SPI); else - irq = irq_of_parse_and_map(best_frame, 0); + irq = irq_of_parse_and_map(best_frame, ARCH_TIMER_PHYS_SPI); ret = -EINVAL; if (!irq) { -- cgit v1.2.3 From 4502b6bb720d7a519c4cea76cf68a2425b481a45 Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Wed, 18 Jan 2017 21:25:30 +0800 Subject: clocksource: arm_arch_timer: rework PPI selection Currently, the arch timer driver uses ARCH_TIMER_PHYS_SECURE_PPI to mean the driver will use the secure PPI *and* potentially also use the non-secure PPI. This is somewhat confusing. For arm64 it never makes sense to use the secure PPI, but we do anyway, inheriting this behaviour from 32-bit arm. For ACPI, we may not even have a valid secure PPI, so we need to be able to only request the non-secure PPI. To that end, this patch reworks the timer driver so that we can request the non-secure PPI alone. The PPI selection is split out into a new function, arch_timer_select_ppi(), and verification of the selected PPI is shifted out to callers (as DT may select the PPI by other means and must handle this anyway). We now consistently use arch_timer_has_nonsecure_ppi() to determine whether we must manage a non-secure PPI *in addition* to a secure PPI. When we only have a non-secure PPI, this returns false. Signed-off-by: Fu Wei Tested-by: Xiongfeng Wang [Mark: reword commit message] Signed-off-by: Mark Rutland --- drivers/clocksource/arm_arch_timer.c | 77 +++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 31 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 15059c958be7..94de018c65d0 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -992,7 +992,7 @@ static int __init arch_timer_register(void) case ARCH_TIMER_PHYS_NONSECURE_PPI: err = request_percpu_irq(ppi, arch_timer_handler_phys, "arch_timer", arch_timer_evt); - if (!err && arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]) { + if (!err && arch_timer_has_nonsecure_ppi()) { ppi = arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]; err = request_percpu_irq(ppi, arch_timer_handler_phys, "arch_timer", arch_timer_evt); @@ -1114,39 +1114,41 @@ static int __init arch_timer_common_init(void) return arch_timer_arch_init(); } -static int __init arch_timer_init(void) +/** + * arch_timer_select_ppi() - Select suitable PPI for the current system. + * + * If HYP mode is available, we know that the physical timer + * has been configured to be accessible from PL1. Use it, so + * that a guest can use the virtual timer instead. + * + * On ARMv8.1 with VH extensions, the kernel runs in HYP. VHE + * accesses to CNTP_*_EL1 registers are silently redirected to + * their CNTHP_*_EL2 counterparts, and use a different PPI + * number. + * + * If no interrupt provided for virtual timer, we'll have to + * stick to the physical timer. It'd better be accessible... + * For arm64 we never use the secure interrupt. + * + * Return: a suitable PPI type for the current system. + */ +static enum arch_timer_ppi_nr __init arch_timer_select_ppi(void) { - int ret; - /* - * If HYP mode is available, we know that the physical timer - * has been configured to be accessible from PL1. Use it, so - * that a guest can use the virtual timer instead. - * - * If no interrupt provided for virtual timer, we'll have to - * stick to the physical timer. It'd better be accessible... - * - * On ARMv8.1 with VH extensions, the kernel runs in HYP. VHE - * accesses to CNTP_*_EL1 registers are silently redirected to - * their CNTHP_*_EL2 counterparts, and use a different PPI - * number. - */ - if (is_hyp_mode_available() || !arch_timer_ppi[ARCH_TIMER_VIRT_PPI]) { - bool has_ppi; + if (is_kernel_in_hyp_mode()) + return ARCH_TIMER_HYP_PPI; - if (is_kernel_in_hyp_mode()) { - arch_timer_uses_ppi = ARCH_TIMER_HYP_PPI; - has_ppi = !!arch_timer_ppi[ARCH_TIMER_HYP_PPI]; - } else { - arch_timer_uses_ppi = ARCH_TIMER_PHYS_SECURE_PPI; - has_ppi = (!!arch_timer_ppi[ARCH_TIMER_PHYS_SECURE_PPI] || - !!arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]); - } + if (!is_hyp_mode_available() && arch_timer_ppi[ARCH_TIMER_VIRT_PPI]) + return ARCH_TIMER_VIRT_PPI; - if (!has_ppi) { - pr_warn("No interrupt available, giving up\n"); - return -EINVAL; - } - } + if (IS_ENABLED(CONFIG_ARM64)) + return ARCH_TIMER_PHYS_NONSECURE_PPI; + + return ARCH_TIMER_PHYS_SECURE_PPI; +} + +static int __init arch_timer_init(void) +{ + int ret; ret = arch_timer_register(); if (ret) @@ -1188,6 +1190,13 @@ static int __init arch_timer_of_init(struct device_node *np) if (IS_ENABLED(CONFIG_ARM) && of_property_read_bool(np, "arm,cpu-registers-not-fw-configured")) arch_timer_uses_ppi = ARCH_TIMER_PHYS_SECURE_PPI; + else + arch_timer_uses_ppi = arch_timer_select_ppi(); + + if (!arch_timer_ppi[arch_timer_uses_ppi]) { + pr_err("No interrupt available, giving up\n"); + return -EINVAL; + } /* On some systems, the counter stops ticking when in suspend. */ arch_counter_suspend_stop = of_property_read_bool(np, @@ -1333,6 +1342,12 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table) /* Get the frequency from CNTFRQ */ arch_timer_detect_rate(NULL, NULL); + arch_timer_uses_ppi = arch_timer_select_ppi(); + if (!arch_timer_ppi[arch_timer_uses_ppi]) { + pr_err("No interrupt available, giving up\n"); + return -EINVAL; + } + /* Always-on capability */ arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON); -- cgit v1.2.3 From 8317b53fbe32439c56ba83ad4435b641799b2ce8 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 22:07:49 +0200 Subject: clockevents/drivers/dw_apb: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Make the dw_apb clockevent driver initialize these fields properly. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from this driver. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Acked-by: Daniel Lezcano Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- drivers/clocksource/dw_apb_timer.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c index 63e4f5519577..880f37e8278f 100644 --- a/drivers/clocksource/dw_apb_timer.c +++ b/drivers/clocksource/dw_apb_timer.c @@ -257,7 +257,9 @@ dw_apb_clockevent_init(int cpu, const char *name, unsigned rating, clockevents_calc_mult_shift(&dw_ced->ced, freq, APBT_MIN_PERIOD); dw_ced->ced.max_delta_ns = clockevent_delta2ns(0x7fffffff, &dw_ced->ced); + dw_ced->ced.max_delta_ticks = 0x7fffffff; dw_ced->ced.min_delta_ns = clockevent_delta2ns(5000, &dw_ced->ced); + dw_ced->ced.min_delta_ticks = 5000; dw_ced->ced.cpumask = cpumask_of(cpu); dw_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_DYNIRQ; -- cgit v1.2.3 From c7438ba1133f9cccf230d63e7f978b5a71d468ff Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 22:08:20 +0200 Subject: clockevents/drivers/metag: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Make the metag_generic clockevent driver initialize these fields properly. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from this driver. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: James Hogan Acked-by: Daniel Lezcano Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- drivers/clocksource/metag_generic.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/metag_generic.c b/drivers/clocksource/metag_generic.c index 6fcf96540631..3e5fa2f62d5f 100644 --- a/drivers/clocksource/metag_generic.c +++ b/drivers/clocksource/metag_generic.c @@ -114,7 +114,9 @@ static int arch_timer_starting_cpu(unsigned int cpu) clk->mult = div_sc(hwtimer_freq, NSEC_PER_SEC, clk->shift); clk->max_delta_ns = clockevent_delta2ns(0x7fffffff, clk); + clk->max_delta_ticks = 0x7fffffff; clk->min_delta_ns = clockevent_delta2ns(0xf, clk); + clk->min_delta_ticks = 0xf; clk->cpumask = cpumask_of(cpu); clockevents_register_device(clk); -- cgit v1.2.3 From 6cf57ae8cd9916efa889dc030b1010571b4567ab Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 22:08:49 +0200 Subject: x86/numachip timer: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Make the numachip clockevent driver initialize these fields properly. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from this driver. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Acked-by: Daniel Lezcano Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- drivers/clocksource/numachip.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/numachip.c b/drivers/clocksource/numachip.c index 4e0f11fd2617..6a20dc8b253f 100644 --- a/drivers/clocksource/numachip.c +++ b/drivers/clocksource/numachip.c @@ -51,7 +51,9 @@ static struct clock_event_device numachip2_clockevent = { .mult = 1, .shift = 0, .min_delta_ns = 1250, + .min_delta_ticks = 1250, .max_delta_ns = LONG_MAX, + .max_delta_ticks = LONG_MAX, }; static void numachip_timer_interrupt(void) -- cgit v1.2.3 From bb2e94ac0cf4628f5e5f778c8de4a376dac43558 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 22:09:12 +0200 Subject: clockevents/drivers/sh_cmt: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Make the sh_cmt clockevent driver initialize these fields properly. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from this driver. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Acked-by: Daniel Lezcano Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- drivers/clocksource/sh_cmt.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index e3bf3baa12cc..e09e8bf0bb9b 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -815,7 +815,9 @@ static int sh_cmt_register_clockevent(struct sh_cmt_channel *ch, ced->shift = 32; ced->mult = div_sc(ch->cmt->rate, NSEC_PER_SEC, ced->shift); ced->max_delta_ns = clockevent_delta2ns(ch->max_match_value, ced); + ced->max_delta_ticks = ch->max_match_value; ced->min_delta_ns = clockevent_delta2ns(0x1f, ced); + ced->min_delta_ticks = 0x1f; dev_info(&ch->cmt->pdev->dev, "ch%u: used for clock events\n", ch->index); -- cgit v1.2.3 From 547733c58dc3d2a50af762d4fdaf1d552e6b31cd Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 22:10:21 +0200 Subject: clockevents/drivers/atlas7: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Make the timer-atlas7 clockevent driver initialize these fields properly. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from this driver. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: Barry Song Cc: linux-arm-kernel@lists.infradead.org Acked-by: Daniel Lezcano Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- drivers/clocksource/timer-atlas7.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-atlas7.c b/drivers/clocksource/timer-atlas7.c index 3d8a181f0252..50300eec4a39 100644 --- a/drivers/clocksource/timer-atlas7.c +++ b/drivers/clocksource/timer-atlas7.c @@ -192,7 +192,9 @@ static int sirfsoc_local_timer_starting_cpu(unsigned int cpu) ce->set_next_event = sirfsoc_timer_set_next_event; clockevents_calc_mult_shift(ce, atlas7_timer_rate, 60); ce->max_delta_ns = clockevent_delta2ns(-2, ce); + ce->max_delta_ticks = (unsigned long)-2; ce->min_delta_ns = clockevent_delta2ns(2, ce); + ce->min_delta_ticks = 2; ce->cpumask = cpumask_of(cpu); action->dev_id = ce; -- cgit v1.2.3 From 5d3dfa96c7a202f3a70ebeb6f8bb5005c1547250 Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Wed, 22 Mar 2017 00:31:13 +0800 Subject: clocksource: arm_arch_timer: split dt-only rate handling For historical reasons, rate detection when probing via DT is somewhat convoluted. We tried to package this up in arch_timer_detect_rate(), but with the addition of ACPI worse, and gets in the way of stringent rate checking when ACPI is used. This patch makes arch_timer_detect_rate() specific to DT, ripping out ACPI logic. In preparation for rework of the MMIO timer probing, the reading of the relevant CNTFRQ register is factored out to callers. The function is then renamed to arch_timer_of_configure_rate(), which better represents its new place in the world. Comments are added in the DT and ACPI probe paths to explain this. Signed-off-by: Fu Wei [Mark: reword commit message] Signed-off-by: Mark Rutland --- drivers/clocksource/arm_arch_timer.c | 41 ++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 18 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 94de018c65d0..02c5cb86ca83 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -818,24 +818,19 @@ static int arch_timer_starting_cpu(unsigned int cpu) return 0; } -static void -arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np) +/* + * For historical reasons, when probing with DT we use whichever (non-zero) + * rate was probed first, and don't verify that others match. If the first node + * probed has a clock-frequency property, this overrides the HW register. + */ +static void arch_timer_of_configure_rate(u32 rate, struct device_node *np) { /* Who has more than one independent system counter? */ if (arch_timer_rate) return; - /* - * Try to determine the frequency from the device tree or CNTFRQ, - * if ACPI is enabled, get the frequency from CNTFRQ ONLY. - */ - if (!acpi_disabled || - of_property_read_u32(np, "clock-frequency", &arch_timer_rate)) { - if (cntbase) - arch_timer_rate = readl_relaxed(cntbase + CNTFRQ); - else - arch_timer_rate = arch_timer_get_cntfrq(); - } + if (of_property_read_u32(np, "clock-frequency", &arch_timer_rate)) + arch_timer_rate = rate; /* Check the timer frequency. */ if (arch_timer_rate == 0) @@ -1166,6 +1161,7 @@ static int __init arch_timer_init(void) static int __init arch_timer_of_init(struct device_node *np) { int i; + u32 rate; if (arch_timers_present & ARCH_TIMER_TYPE_CP15) { pr_warn("multiple nodes in dt, skipping\n"); @@ -1176,7 +1172,8 @@ static int __init arch_timer_of_init(struct device_node *np) for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; i++) arch_timer_ppi[i] = irq_of_parse_and_map(np, i); - arch_timer_detect_rate(NULL, np); + rate = arch_timer_get_cntfrq; + arch_timer_of_configure_rate(rate, np); arch_timer_c3stop = !of_property_read_bool(np, "always-on"); @@ -1212,7 +1209,7 @@ static int __init arch_timer_mem_init(struct device_node *np) struct device_node *frame, *best_frame = NULL; void __iomem *cntctlbase, *base; unsigned int irq, ret = -EINVAL; - u32 cnttidr; + u32 cnttidr, rate; arch_timers_present |= ARCH_TIMER_TYPE_MEM; cntctlbase = of_iomap(np, 0); @@ -1278,7 +1275,8 @@ static int __init arch_timer_mem_init(struct device_node *np) goto out; } - arch_timer_detect_rate(base, np); + rate = readl(base + CNTFRQ); + arch_timer_of_configure_rate(rate, np); ret = arch_timer_mem_register(base, irq); if (ret) goto out; @@ -1339,8 +1337,15 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table) map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt, gtdt->non_secure_el2_flags); - /* Get the frequency from CNTFRQ */ - arch_timer_detect_rate(NULL, NULL); + /* + * When probing via ACPI, we have no mechanism to override the sysreg + * CNTFRQ value. This *must* be correct. + */ + arch_timer_rate = arch_timer_get_cntfrq(); + if (!arch_timer_rate) { + pr_err(FW_BUG "frequency not available.\n"); + return -EINVAL; + } arch_timer_uses_ppi = arch_timer_select_ppi(); if (!arch_timer_ppi[arch_timer_uses_ppi]) { -- cgit v1.2.3 From 13bf6992fe5496d56101b5d57fbdae2ee91184f2 Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Wed, 22 Mar 2017 00:31:14 +0800 Subject: clocksource: arm_arch_timer: refactor arch_timer_needs_probing When booting with DT, it's possible for timer nodes to be probed in any order. Some common initialisation needs to occur after all nodes have been probed, and arch_timer_common_init() has code to detect when this has happened. This logic is DT-specific, and it would be best to factor it out of the common code that will be shared with ACPI. This patch folds this into the existing arch_timer_needs_probing(), which is renamed to arch_timer_needs_of_probing(), and no longer takes any arguments. This is only called when using DT, and not when using ACPI, which will have a deterministic probe order. Signed-off-by: Fu Wei Reviewed-by: Hanjun Guo [Mark: reword commit message] Signed-off-by: Mark Rutland --- drivers/clocksource/arm_arch_timer.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 02c5cb86ca83..e38f4d4290ad 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -1076,15 +1076,28 @@ static const struct of_device_id arch_timer_mem_of_match[] __initconst = { {}, }; -static bool __init -arch_timer_needs_probing(int type, const struct of_device_id *matches) +static bool __init arch_timer_needs_of_probing(void) { struct device_node *dn; bool needs_probing = false; + unsigned int mask = ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM; - dn = of_find_matching_node(NULL, matches); - if (dn && of_device_is_available(dn) && !(arch_timers_present & type)) + /* We have two timers, and both device-tree nodes are probed. */ + if ((arch_timers_present & mask) == mask) + return false; + + /* + * Only one type of timer is probed, + * check if we have another type of timer node in device-tree. + */ + if (arch_timers_present & ARCH_TIMER_TYPE_CP15) + dn = of_find_matching_node(NULL, arch_timer_mem_of_match); + else + dn = of_find_matching_node(NULL, arch_timer_of_match); + + if (dn && of_device_is_available(dn)) needs_probing = true; + of_node_put(dn); return needs_probing; @@ -1092,17 +1105,8 @@ arch_timer_needs_probing(int type, const struct of_device_id *matches) static int __init arch_timer_common_init(void) { - unsigned mask = ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM; - - /* Wait until both nodes are probed if we have two timers */ - if ((arch_timers_present & mask) != mask) { - if (arch_timer_needs_probing(ARCH_TIMER_TYPE_MEM, - arch_timer_mem_of_match)) - return 0; - if (arch_timer_needs_probing(ARCH_TIMER_TYPE_CP15, - arch_timer_of_match)) - return 0; - } + if (acpi_disabled && arch_timer_needs_of_probing()) + return 0; arch_timer_banner(arch_timers_present); arch_counter_register(arch_timers_present); -- cgit v1.2.3 From ca0e1b5214eee56a7fc4c7a5399323ab0bad73ef Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Wed, 22 Mar 2017 00:31:15 +0800 Subject: clocksource: arm_arch_timer: move arch_timer_needs_of_probing into DT init call To cleanly split code paths specific to ACPI or DT at a higher level, this patch removes arch_timer_init(), folding the relevant parts of its logic into existing callers. This pathes the way for further rework, and saves a few lines. Signed-off-by: Fu Wei Reviewed-by: Hanjun Guo [Mark: reword commit message] Signed-off-by: Mark Rutland --- drivers/clocksource/arm_arch_timer.c | 46 ++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 25 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index e38f4d4290ad..ac6fd00c98ba 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -1105,9 +1105,6 @@ static bool __init arch_timer_needs_of_probing(void) static int __init arch_timer_common_init(void) { - if (acpi_disabled && arch_timer_needs_of_probing()) - return 0; - arch_timer_banner(arch_timers_present); arch_counter_register(arch_timers_present); return arch_timer_arch_init(); @@ -1145,26 +1142,9 @@ static enum arch_timer_ppi_nr __init arch_timer_select_ppi(void) return ARCH_TIMER_PHYS_SECURE_PPI; } -static int __init arch_timer_init(void) -{ - int ret; - - ret = arch_timer_register(); - if (ret) - return ret; - - ret = arch_timer_common_init(); - if (ret) - return ret; - - arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI]; - - return 0; -} - static int __init arch_timer_of_init(struct device_node *np) { - int i; + int i, ret; u32 rate; if (arch_timers_present & ARCH_TIMER_TYPE_CP15) { @@ -1176,6 +1156,8 @@ static int __init arch_timer_of_init(struct device_node *np) for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; i++) arch_timer_ppi[i] = irq_of_parse_and_map(np, i); + arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI]; + rate = arch_timer_get_cntfrq; arch_timer_of_configure_rate(rate, np); @@ -1203,7 +1185,14 @@ static int __init arch_timer_of_init(struct device_node *np) arch_counter_suspend_stop = of_property_read_bool(np, "arm,no-tick-in-suspend"); - return arch_timer_init(); + ret = arch_timer_register(); + if (ret) + return ret; + + if (arch_timer_needs_of_probing()) + return 0; + + return arch_timer_common_init(); } CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init); CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_of_init); @@ -1285,7 +1274,8 @@ static int __init arch_timer_mem_init(struct device_node *np) if (ret) goto out; - return arch_timer_common_init(); + if (!arch_timer_needs_of_probing()) + ret = arch_timer_common_init(); out: iounmap(cntctlbase); of_node_put(best_frame); @@ -1314,6 +1304,7 @@ static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags) /* Initialize per-processor generic timer */ static int __init arch_timer_acpi_init(struct acpi_table_header *table) { + int ret; struct acpi_table_gtdt *gtdt; if (arch_timers_present & ARCH_TIMER_TYPE_CP15) { @@ -1341,6 +1332,8 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table) map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt, gtdt->non_secure_el2_flags); + arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI]; + /* * When probing via ACPI, we have no mechanism to override the sysreg * CNTFRQ value. This *must* be correct. @@ -1363,8 +1356,11 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table) /* Check for globally applicable workarounds */ arch_timer_check_ool_workaround(ate_match_acpi_oem_info, table); - arch_timer_init(); - return 0; + ret = arch_timer_register(); + if (ret) + return ret; + + return arch_timer_common_init(); } CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init); #endif -- cgit v1.2.3 From c389d701dfb70154edf896f0f9c40d2857ca2d90 Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Sat, 1 Apr 2017 01:51:00 +0800 Subject: clocksource: arm_arch_timer: split MMIO timer probing. Currently the code to probe MMIO architected timers mixes DT parsing with actual poking of hardware. This makes the code harder than necessary to understand, and makes it difficult to add support for probing via ACPI. This patch splits the DT parsing from HW probing. The DT parsing now lives in arch_timer_mem_of_init(), which fills in an arch_timer_mem structure that it hands to probing functions that can be reused for ACPI support. Since the rate detection logic will be slight different when using ACPI, the probing is performed as a number of steps. This results in more code for the moment, and some arguably redundant work, but simplifies matters considerably when ACPI support is added. Signed-off-by: Fu Wei [Mark: refactor the probing split] Signed-off-by: Mark Rutland --- drivers/clocksource/arm_arch_timer.c | 189 +++++++++++++++++++++++++++-------- 1 file changed, 145 insertions(+), 44 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index ac6fd00c98ba..d87c4035a505 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -1158,7 +1158,7 @@ static int __init arch_timer_of_init(struct device_node *np) arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI]; - rate = arch_timer_get_cntfrq; + rate = arch_timer_get_cntfrq(); arch_timer_of_configure_rate(rate, np); arch_timer_c3stop = !of_property_read_bool(np, "always-on"); @@ -1197,18 +1197,38 @@ static int __init arch_timer_of_init(struct device_node *np) CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init); CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_of_init); -static int __init arch_timer_mem_init(struct device_node *np) +static u32 __init +arch_timer_mem_frame_get_cntfrq(struct arch_timer_mem_frame *frame) { - struct device_node *frame, *best_frame = NULL; - void __iomem *cntctlbase, *base; - unsigned int irq, ret = -EINVAL; - u32 cnttidr, rate; + void __iomem *base; + u32 rate; - arch_timers_present |= ARCH_TIMER_TYPE_MEM; - cntctlbase = of_iomap(np, 0); + base = ioremap(frame->cntbase, frame->size); + if (!base) { + pr_err("Unable to map frame @ %pa\n", &frame->cntbase); + return 0; + } + + rate = readl_relaxed(frame + CNTFRQ); + + iounmap(frame); + + return rate; +} + +static struct arch_timer_mem_frame * __init +arch_timer_mem_find_best_frame(struct arch_timer_mem *timer_mem) +{ + struct arch_timer_mem_frame *frame, *best_frame = NULL; + void __iomem *cntctlbase; + u32 cnttidr; + int i; + + cntctlbase = ioremap(timer_mem->cntctlbase, timer_mem->size); if (!cntctlbase) { - pr_err("Can't find CNTCTLBase\n"); - return -ENXIO; + pr_err("Can't map CNTCTLBase @ %pa\n", + &timer_mem->cntctlbase); + return NULL; } cnttidr = readl_relaxed(cntctlbase + CNTTIDR); @@ -1217,25 +1237,20 @@ static int __init arch_timer_mem_init(struct device_node *np) * Try to find a virtual capable frame. Otherwise fall back to a * physical capable frame. */ - for_each_available_child_of_node(np, frame) { - int n; - u32 cntacr; + for (i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) { + u32 cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT | + CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT; - if (of_property_read_u32(frame, "frame-number", &n)) { - pr_err("Missing frame-number\n"); - of_node_put(frame); - goto out; - } + frame = &timer_mem->frame[i]; + if (!frame->valid) + continue; /* Try enabling everything, and see what sticks */ - cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT | - CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT; - writel_relaxed(cntacr, cntctlbase + CNTACR(n)); - cntacr = readl_relaxed(cntctlbase + CNTACR(n)); + writel_relaxed(cntacr, cntctlbase + CNTACR(i)); + cntacr = readl_relaxed(cntctlbase + CNTACR(i)); - if ((cnttidr & CNTTIDR_VIRT(n)) && + if ((cnttidr & CNTTIDR_VIRT(i)) && !(~cntacr & (CNTACR_RWVT | CNTACR_RVCT))) { - of_node_put(best_frame); best_frame = frame; arch_timer_mem_use_virtual = true; break; @@ -1244,45 +1259,131 @@ static int __init arch_timer_mem_init(struct device_node *np) if (~cntacr & (CNTACR_RWPT | CNTACR_RPCT)) continue; - of_node_put(best_frame); - best_frame = of_node_get(frame); + best_frame = frame; } - ret= -ENXIO; - base = arch_counter_base = of_io_request_and_map(best_frame, 0, - "arch_mem_timer"); - if (IS_ERR(base)) { - pr_err("Can't map frame's registers\n"); - goto out; - } + iounmap(cntctlbase); + + if (!best_frame) + pr_err("Unable to find a suitable frame in timer @ %pa\n", + &timer_mem->cntctlbase); + + return frame; +} + +static int __init +arch_timer_mem_frame_register(struct arch_timer_mem_frame *frame) +{ + void __iomem *base; + int ret, irq = 0; if (arch_timer_mem_use_virtual) - irq = irq_of_parse_and_map(best_frame, ARCH_TIMER_VIRT_SPI); + irq = frame->virt_irq; else - irq = irq_of_parse_and_map(best_frame, ARCH_TIMER_PHYS_SPI); + irq = frame->phys_irq; - ret = -EINVAL; if (!irq) { pr_err("Frame missing %s irq.\n", arch_timer_mem_use_virtual ? "virt" : "phys"); - goto out; + return -EINVAL; + } + + if (!request_mem_region(frame->cntbase, frame->size, + "arch_mem_timer")) + return -EBUSY; + + base = ioremap(frame->cntbase, frame->size); + if (!base) { + pr_err("Can't map frame's registers\n"); + return -ENXIO; } - rate = readl(base + CNTFRQ); - arch_timer_of_configure_rate(rate, np); ret = arch_timer_mem_register(base, irq); - if (ret) + if (ret) { + iounmap(base); + return ret; + } + + arch_counter_base = base; + arch_timers_present |= ARCH_TIMER_TYPE_MEM; + + return 0; +} + +static int __init arch_timer_mem_of_init(struct device_node *np) +{ + struct arch_timer_mem *timer_mem; + struct arch_timer_mem_frame *frame; + struct device_node *frame_node; + struct resource res; + int ret = -EINVAL; + u32 rate; + + timer_mem = kzalloc(sizeof(*timer_mem), GFP_KERNEL); + if (!timer_mem) + return -ENOMEM; + + if (of_address_to_resource(np, 0, &res)) goto out; + timer_mem->cntctlbase = res.start; + timer_mem->size = resource_size(&res); - if (!arch_timer_needs_of_probing()) + for_each_available_child_of_node(np, frame_node) { + u32 n; + struct arch_timer_mem_frame *frame; + + if (of_property_read_u32(frame_node, "frame-number", &n)) { + pr_err(FW_BUG "Missing frame-number.\n"); + of_node_put(frame_node); + goto out; + } + if (n >= ARCH_TIMER_MEM_MAX_FRAMES) { + pr_err(FW_BUG "Wrong frame-number, only 0-%u are permitted.\n", + ARCH_TIMER_MEM_MAX_FRAMES - 1); + of_node_put(frame_node); + goto out; + } + frame = &timer_mem->frame[n]; + + if (frame->valid) { + pr_err(FW_BUG "Duplicated frame-number.\n"); + of_node_put(frame_node); + goto out; + } + + if (of_address_to_resource(frame_node, 0, &res)) { + of_node_put(frame_node); + goto out; + } + frame->cntbase = res.start; + frame->size = resource_size(&res); + + frame->virt_irq = irq_of_parse_and_map(frame_node, + ARCH_TIMER_VIRT_SPI); + frame->phys_irq = irq_of_parse_and_map(frame_node, + ARCH_TIMER_PHYS_SPI); + + frame->valid = true; + } + + frame = arch_timer_mem_find_best_frame(timer_mem); + if (!frame) { + ret = -EINVAL; + goto out; + } + + rate = arch_timer_mem_frame_get_cntfrq(frame); + arch_timer_of_configure_rate(rate, np); + + ret = arch_timer_mem_frame_register(frame); + if (!ret && !arch_timer_needs_of_probing()) ret = arch_timer_common_init(); out: - iounmap(cntctlbase); - of_node_put(best_frame); + kfree(timer_mem); return ret; } CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem", - arch_timer_mem_init); + arch_timer_mem_of_init); #ifdef CONFIG_ACPI static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags) -- cgit v1.2.3 From f79d209405fada700047245ed1a152bab8d6535e Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Sat, 1 Apr 2017 01:51:02 +0800 Subject: clocksource: arm_arch_timer: simplify ACPI support code. The patch update arm_arch_timer driver to use the function provided by the new GTDT driver of ACPI. By this way, arm_arch_timer.c can be simplified, and separate all the ACPI GTDT knowledge from this timer driver. Signed-off-by: Fu Wei Signed-off-by: Hanjun Guo Tested-by: Xiongfeng Wang Reviewed-by: Hanjun Guo Tested-by: Hanjun Guo Signed-off-by: Mark Rutland --- drivers/clocksource/arm_arch_timer.c | 40 +++++++++--------------------------- 1 file changed, 10 insertions(+), 30 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index d87c4035a505..e398228d60b2 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -1385,53 +1385,33 @@ out: CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem", arch_timer_mem_of_init); -#ifdef CONFIG_ACPI -static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags) -{ - int trigger, polarity; - - if (!interrupt) - return 0; - - trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE - : ACPI_LEVEL_SENSITIVE; - - polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW - : ACPI_ACTIVE_HIGH; - - return acpi_register_gsi(NULL, interrupt, trigger, polarity); -} - +#ifdef CONFIG_ACPI_GTDT /* Initialize per-processor generic timer */ static int __init arch_timer_acpi_init(struct acpi_table_header *table) { int ret; - struct acpi_table_gtdt *gtdt; if (arch_timers_present & ARCH_TIMER_TYPE_CP15) { pr_warn("already initialized, skipping\n"); return -EINVAL; } - gtdt = container_of(table, struct acpi_table_gtdt, header); - arch_timers_present |= ARCH_TIMER_TYPE_CP15; - arch_timer_ppi[ARCH_TIMER_PHYS_SECURE_PPI] = - map_generic_timer_interrupt(gtdt->secure_el1_interrupt, - gtdt->secure_el1_flags); + ret = acpi_gtdt_init(table, NULL); + if (ret) { + pr_err("Failed to init GTDT table.\n"); + return ret; + } arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI] = - map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt, - gtdt->non_secure_el1_flags); + acpi_gtdt_map_ppi(ARCH_TIMER_PHYS_NONSECURE_PPI); arch_timer_ppi[ARCH_TIMER_VIRT_PPI] = - map_generic_timer_interrupt(gtdt->virtual_timer_interrupt, - gtdt->virtual_timer_flags); + acpi_gtdt_map_ppi(ARCH_TIMER_VIRT_PPI); arch_timer_ppi[ARCH_TIMER_HYP_PPI] = - map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt, - gtdt->non_secure_el2_flags); + acpi_gtdt_map_ppi(ARCH_TIMER_HYP_PPI); arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI]; @@ -1452,7 +1432,7 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table) } /* Always-on capability */ - arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON); + arch_timer_c3stop = acpi_gtdt_c3stop(arch_timer_uses_ppi); /* Check for globally applicable workarounds */ arch_timer_check_ool_workaround(ate_match_acpi_oem_info, table); -- cgit v1.2.3 From c2743a36765d337fad589b5c30b47c297a207194 Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Sat, 1 Apr 2017 01:51:04 +0800 Subject: clocksource: arm_arch_timer: add GTDT support for memory-mapped timer The patch add memory-mapped timer register support by using the information provided by the new GTDT driver of ACPI. Signed-off-by: Fu Wei Reviewed-by: Hanjun Guo [Mark: verify CNTFRQ, only register the first frame] Signed-off-by: Mark Rutland --- drivers/clocksource/arm_arch_timer.c | 79 ++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 3 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index e398228d60b2..2208fa4eafee 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -1386,10 +1386,79 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem", arch_timer_mem_of_init); #ifdef CONFIG_ACPI_GTDT -/* Initialize per-processor generic timer */ +static int __init +arch_timer_mem_verify_cntfrq(struct arch_timer_mem *timer_mem) +{ + struct arch_timer_mem_frame *frame; + u32 rate; + int i; + + for (i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) { + frame = &timer_mem->frame[i]; + + if (!frame->valid) + continue; + + rate = arch_timer_mem_frame_get_cntfrq(frame); + if (rate == arch_timer_rate) + continue; + + pr_err(FW_BUG "CNTFRQ mismatch: frame @ %pa: (0x%08lx), CPU: (0x%08lx)\n", + &frame->cntbase, + (unsigned long)rate, (unsigned long)arch_timer_rate); + + return -EINVAL; + } + + return 0; +} + +static int __init arch_timer_mem_acpi_init(int platform_timer_count) +{ + struct arch_timer_mem *timers, *timer; + struct arch_timer_mem_frame *frame; + int timer_count, i, ret = 0; + + timers = kcalloc(platform_timer_count, sizeof(*timers), + GFP_KERNEL); + if (!timers) + return -ENOMEM; + + ret = acpi_arch_timer_mem_init(timers, &timer_count); + if (ret || !timer_count) + goto out; + + for (i = 0; i < timer_count; i++) { + ret = arch_timer_mem_verify_cntfrq(&timers[i]); + if (ret) { + pr_err("Disabling MMIO timers due to CNTFRQ mismatch\n"); + goto out; + } + } + + /* + * While unlikely, it's theoretically possible that none of the frames + * in a timer expose the combination of feature we want. + */ + for (i = i; i < timer_count; i++) { + timer = &timers[i]; + + frame = arch_timer_mem_find_best_frame(timer); + if (frame) + break; + } + + if (frame) + ret = arch_timer_mem_frame_register(frame); +out: + kfree(timers); + return ret; +} + +/* Initialize per-processor generic timer and memory-mapped timer(if present) */ static int __init arch_timer_acpi_init(struct acpi_table_header *table) { - int ret; + int ret, platform_timer_count; if (arch_timers_present & ARCH_TIMER_TYPE_CP15) { pr_warn("already initialized, skipping\n"); @@ -1398,7 +1467,7 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table) arch_timers_present |= ARCH_TIMER_TYPE_CP15; - ret = acpi_gtdt_init(table, NULL); + ret = acpi_gtdt_init(table, &platform_timer_count); if (ret) { pr_err("Failed to init GTDT table.\n"); return ret; @@ -1441,6 +1510,10 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table) if (ret) return ret; + if (platform_timer_count && + arch_timer_mem_acpi_init(platform_timer_count)) + pr_err("Failed to initialize memory-mapped timer.\n"); + return arch_timer_common_init(); } CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init); -- cgit v1.2.3 From 58bb100a9de10329ca0d63484e76f27c257e9a2e Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Wed, 19 Apr 2017 13:26:46 +0100 Subject: Clocksource/mips-gic: Remove redundant non devicetree init Malta was the only platform probing this driver from platform code without using device tree. With that code removed, gic_clocksource_init is redundant so remove it. Signed-off-by: Matt Redfearn Cc: linux-mips@linux-mips.org Cc: Jason Cooper Cc: Paul Burton Cc: Daniel Lezcano Cc: Ralf Baechle Link: http://lkml.kernel.org/r/1492604806-23420-2-git-send-email-matt.redfearn@imgtec.com Signed-off-by: Thomas Gleixner --- drivers/clocksource/mips-gic-timer.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c index b6ad9c0a7c55..3f52ee219923 100644 --- a/drivers/clocksource/mips-gic-timer.c +++ b/drivers/clocksource/mips-gic-timer.c @@ -154,19 +154,6 @@ static int __init __gic_clocksource_init(void) return ret; } -void __init gic_clocksource_init(unsigned int frequency) -{ - gic_frequency = frequency; - gic_timer_irq = MIPS_GIC_IRQ_BASE + - GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_COMPARE); - - __gic_clocksource_init(); - gic_clockevent_init(); - - /* And finally start the counter */ - gic_start_count(); -} - static int __init gic_clocksource_of_init(struct device_node *node) { struct clk *clk; -- cgit v1.2.3 From eb64522100a1d4adc89bce11b935a30c4401e234 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 19 Apr 2017 19:37:09 +0200 Subject: arm64/arch_timer: Mark errata handlers as __maybe_unused In some rare randconfig builds, we end up with two functions being entirely unused: drivers/clocksource/arm_arch_timer.c:342:12: error: 'erratum_set_next_event_tval_phys' defined but not used [-Werror=unused-function] static int erratum_set_next_event_tval_phys(unsigned long evt, drivers/clocksource/arm_arch_timer.c:335:12: error: 'erratum_set_next_event_tval_virt' defined but not used [-Werror=unused-function] static int erratum_set_next_event_tval_virt(unsigned long evt, We could add an #ifdef around them, but we would already have to check for several symbols there and there is a chance this would get more complicated over time, so marking them as __maybe_unused is the simplest way to avoid the harmless warnings. Fixes: 01d3e3ff2608 ("arm64: arch_timer: Rework the set_next_event workarounds") Signed-off-by: Arnd Bergmann Acked-by: Marc Zyngier Acked-by: Daniel Lezcano Cc: Mark Rutland Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Cc: Christoffer Dall Link: http://lkml.kernel.org/r/20170419173737.3846098-1-arnd@arndb.de Signed-off-by: Thomas Gleixner --- drivers/clocksource/arm_arch_timer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 2208fa4eafee..a1fb918b8021 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -324,14 +324,14 @@ static void erratum_set_next_event_tval_generic(const int access, unsigned long arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk); } -static int erratum_set_next_event_tval_virt(unsigned long evt, +static __maybe_unused int erratum_set_next_event_tval_virt(unsigned long evt, struct clock_event_device *clk) { erratum_set_next_event_tval_generic(ARCH_TIMER_VIRT_ACCESS, evt, clk); return 0; } -static int erratum_set_next_event_tval_phys(unsigned long evt, +static __maybe_unused int erratum_set_next_event_tval_phys(unsigned long evt, struct clock_event_device *clk) { erratum_set_next_event_tval_generic(ARCH_TIMER_PHYS_ACCESS, evt, clk); -- cgit v1.2.3