Commit 8dd2eee2 authored by Thomas Gleixner's avatar Thomas Gleixner

Merge branch 'clockevents/5.1' of...

Merge branch 'clockevents/5.1' of https://git.linaro.org/people/daniel.lezcano/linux into timers/core

Pull clockevents updates from Daniel Lezcano:

 - Update the binding documentation for the gpt timer (Anson Huang)

 - Improve checking and error handling at init time on risc timer (Atish
   Patra)

 - Update the binding documentation for r8a774c0 cmt and tmu (Biju Das)

 - Fail gracefully when clock rate is unavailable on sun5i (Chen-Yu Tsai)

 - Rename the tango-xtal, pxa and cs5535 to timer-*.c for consistency
   (Daniel Lezcano)

 - Add the support for the tegra210 timer and add the platform's Kconfig
   selection (Joseph Lo)

 - Do a cleanup in the header inclusions and remove the unused ones for the
   exynos_mct timer driver (Krzysztof Kozlowski)

 - Remove some non-of dead code and fix the error path when initializing
   the resources in the exynos_mct timer driver (Marek Szyprowski)

 - Update the DT bindings for the MT7629 (Ryder Lee)

 - Provide a workaround for the arm arch timer for Allwinner A64 timers
   (Samuel Holland)

 - Clear the timer interrupt at shutdown time on the exynos_mct timer
   driver (Stuart Menefy)
parents 75b710af f40f4fc9
...@@ -44,6 +44,8 @@ stable kernels. ...@@ -44,6 +44,8 @@ stable kernels.
| Implementor | Component | Erratum ID | Kconfig | | Implementor | Component | Erratum ID | Kconfig |
+----------------+-----------------+-----------------+-----------------------------+ +----------------+-----------------+-----------------+-----------------------------+
| Allwinner | A64/R18 | UNKNOWN1 | SUN50I_ERRATUM_UNKNOWN1 |
| | | | |
| ARM | Cortex-A53 | #826319 | ARM64_ERRATUM_826319 | | ARM | Cortex-A53 | #826319 | ARM64_ERRATUM_826319 |
| ARM | Cortex-A53 | #827319 | ARM64_ERRATUM_827319 | | ARM | Cortex-A53 | #827319 | ARM64_ERRATUM_827319 |
| ARM | Cortex-A53 | #824069 | ARM64_ERRATUM_824069 | | ARM | Cortex-A53 | #824069 | ARM64_ERRATUM_824069 |
......
...@@ -2,17 +2,44 @@ Freescale i.MX General Purpose Timer (GPT) ...@@ -2,17 +2,44 @@ Freescale i.MX General Purpose Timer (GPT)
Required properties: Required properties:
- compatible : should be "fsl,<soc>-gpt" - compatible : should be one of following:
- reg : Specifies base physical address and size of the registers. for i.MX1:
- interrupts : A list of 4 interrupts; one per timer channel. - "fsl,imx1-gpt";
- clocks : The clocks provided by the SoC to drive the timer. for i.MX21:
- "fsl,imx21-gpt";
for i.MX27:
- "fsl,imx27-gpt", "fsl,imx21-gpt";
for i.MX31:
- "fsl,imx31-gpt";
for i.MX25:
- "fsl,imx25-gpt", "fsl,imx31-gpt";
for i.MX50:
- "fsl,imx50-gpt", "fsl,imx31-gpt";
for i.MX51:
- "fsl,imx51-gpt", "fsl,imx31-gpt";
for i.MX53:
- "fsl,imx53-gpt", "fsl,imx31-gpt";
for i.MX6Q:
- "fsl,imx6q-gpt", "fsl,imx31-gpt";
for i.MX6DL:
- "fsl,imx6dl-gpt";
for i.MX6SL:
- "fsl,imx6sl-gpt", "fsl,imx6dl-gpt";
for i.MX6SX:
- "fsl,imx6sx-gpt", "fsl,imx6dl-gpt";
- reg : specifies base physical address and size of the registers.
- interrupts : should be the gpt interrupt.
- clocks : the clocks provided by the SoC to drive the timer, must contain
an entry for each entry in clock-names.
- clock-names : must include "ipg" entry first, then "per" entry.
Example: Example:
gpt1: timer@10003000 { gpt1: timer@10003000 {
compatible = "fsl,imx27-gpt", "fsl,imx1-gpt"; compatible = "fsl,imx27-gpt", "fsl,imx21-gpt";
reg = <0x10003000 0x1000>; reg = <0x10003000 0x1000>;
interrupts = <26>; interrupts = <26>;
clocks = <&clks 46>, <&clks 61>; clocks = <&clks IMX27_CLK_GPT1_IPG_GATE>,
<&clks IMX27_CLK_PER1_GATE>;
clock-names = "ipg", "per"; clock-names = "ipg", "per";
}; };
Mediatek Timers MediaTek Timers
--------------- ---------------
Mediatek SoCs have two different timers on different platforms, MediaTek SoCs have two different timers on different platforms,
- GPT (General Purpose Timer) - GPT (General Purpose Timer)
- SYST (System Timer) - SYST (System Timer)
...@@ -9,6 +9,7 @@ The proper timer will be selected automatically by driver. ...@@ -9,6 +9,7 @@ The proper timer will be selected automatically by driver.
Required properties: Required properties:
- compatible should contain: - compatible should contain:
For those SoCs that use GPT
* "mediatek,mt2701-timer" for MT2701 compatible timers (GPT) * "mediatek,mt2701-timer" for MT2701 compatible timers (GPT)
* "mediatek,mt6580-timer" for MT6580 compatible timers (GPT) * "mediatek,mt6580-timer" for MT6580 compatible timers (GPT)
* "mediatek,mt6589-timer" for MT6589 compatible timers (GPT) * "mediatek,mt6589-timer" for MT6589 compatible timers (GPT)
...@@ -17,7 +18,11 @@ Required properties: ...@@ -17,7 +18,11 @@ Required properties:
* "mediatek,mt8135-timer" for MT8135 compatible timers (GPT) * "mediatek,mt8135-timer" for MT8135 compatible timers (GPT)
* "mediatek,mt8173-timer" for MT8173 compatible timers (GPT) * "mediatek,mt8173-timer" for MT8173 compatible timers (GPT)
* "mediatek,mt6577-timer" for MT6577 and all above compatible timers (GPT) * "mediatek,mt6577-timer" for MT6577 and all above compatible timers (GPT)
* "mediatek,mt6765-timer" for MT6765 compatible timers (SYST)
For those SoCs that use SYST
* "mediatek,mt7629-timer" for MT7629 compatible timers (SYST)
* "mediatek,mt6765-timer" for MT6765 and all above compatible timers (SYST)
- reg: Should contain location and length for timer register. - reg: Should contain location and length for timer register.
- clocks: Should contain system clock. - clocks: Should contain system clock.
......
NVIDIA Tegra210 timer
The Tegra210 timer provides fourteen 29-bit timer counters and one 32-bit
timestamp counter. The TMRs run at either a fixed 1 MHz clock rate derived
from the oscillator clock (TMR0-TMR9) or directly at the oscillator clock
(TMR10-TMR13). Each TMR can be programmed to generate one-shot, periodic,
or watchdog interrupts.
Required properties:
- compatible : "nvidia,tegra210-timer".
- reg : Specifies base physical address and size of the registers.
- interrupts : A list of 14 interrupts; one per each timer channels 0 through
13.
- clocks : Must contain one entry, for the module clock.
See ../clocks/clock-bindings.txt for details.
timer@60005000 {
compatible = "nvidia,tegra210-timer";
reg = <0x0 0x60005000 0x0 0x400>;
interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&tegra_car TEGRA210_CLK_TIMER>;
clock-names = "timer";
};
...@@ -32,6 +32,8 @@ Required Properties: ...@@ -32,6 +32,8 @@ Required Properties:
- "renesas,r8a77470-cmt1" for the 48-bit CMT1 device included in r8a77470. - "renesas,r8a77470-cmt1" for the 48-bit CMT1 device included in r8a77470.
- "renesas,r8a774a1-cmt0" for the 32-bit CMT0 device included in r8a774a1. - "renesas,r8a774a1-cmt0" for the 32-bit CMT0 device included in r8a774a1.
- "renesas,r8a774a1-cmt1" for the 48-bit CMT1 device included in r8a774a1. - "renesas,r8a774a1-cmt1" for the 48-bit CMT1 device included in r8a774a1.
- "renesas,r8a774c0-cmt0" for the 32-bit CMT0 device included in r8a774c0.
- "renesas,r8a774c0-cmt1" for the 48-bit CMT1 device included in r8a774c0.
- "renesas,r8a7790-cmt0" for the 32-bit CMT0 device included in r8a7790. - "renesas,r8a7790-cmt0" for the 32-bit CMT0 device included in r8a7790.
- "renesas,r8a7790-cmt1" for the 48-bit CMT1 device included in r8a7790. - "renesas,r8a7790-cmt1" for the 48-bit CMT1 device included in r8a7790.
- "renesas,r8a7791-cmt0" for the 32-bit CMT0 device included in r8a7791. - "renesas,r8a7791-cmt0" for the 32-bit CMT0 device included in r8a7791.
......
...@@ -10,6 +10,7 @@ Required Properties: ...@@ -10,6 +10,7 @@ Required Properties:
- compatible: must contain one or more of the following: - compatible: must contain one or more of the following:
- "renesas,tmu-r8a7740" for the r8a7740 TMU - "renesas,tmu-r8a7740" for the r8a7740 TMU
- "renesas,tmu-r8a774c0" for the r8a774C0 TMU
- "renesas,tmu-r8a7778" for the r8a7778 TMU - "renesas,tmu-r8a7778" for the r8a7778 TMU
- "renesas,tmu-r8a7779" for the r8a7779 TMU - "renesas,tmu-r8a7779" for the r8a7779 TMU
- "renesas,tmu-r8a77970" for the r8a77970 TMU - "renesas,tmu-r8a77970" for the r8a77970 TMU
......
...@@ -131,7 +131,8 @@ config SUN5I_HSTIMER ...@@ -131,7 +131,8 @@ config SUN5I_HSTIMER
config TEGRA_TIMER config TEGRA_TIMER
bool "Tegra timer driver" if COMPILE_TEST bool "Tegra timer driver" if COMPILE_TEST
select CLKSRC_MMIO select CLKSRC_MMIO
depends on ARM select TIMER_OF
depends on ARM || ARM64
help help
Enables support for the Tegra driver. Enables support for the Tegra driver.
...@@ -360,6 +361,16 @@ config ARM64_ERRATUM_858921 ...@@ -360,6 +361,16 @@ config ARM64_ERRATUM_858921
The workaround will be dynamically enabled when an affected The workaround will be dynamically enabled when an affected
core is detected. core is detected.
config SUN50I_ERRATUM_UNKNOWN1
bool "Workaround for Allwinner A64 erratum UNKNOWN1"
default y
depends on ARM_ARCH_TIMER && ARM64 && ARCH_SUNXI
select ARM_ARCH_TIMER_OOL_WORKAROUND
help
This option enables a workaround for instability in the timer on
the Allwinner A64 SoC. The workaround will only be active if the
allwinner,erratum-unknown1 property is found in the timer node.
config ARM_GLOBAL_TIMER config ARM_GLOBAL_TIMER
bool "Support for the ARM global timer" if COMPILE_TEST bool "Support for the ARM global timer" if COMPILE_TEST
select TIMER_OF if OF select TIMER_OF if OF
......
...@@ -6,7 +6,7 @@ obj-$(CONFIG_ATMEL_ST) += timer-atmel-st.o ...@@ -6,7 +6,7 @@ obj-$(CONFIG_ATMEL_ST) += timer-atmel-st.o
obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o
obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o
obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o
obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC) += cs5535-clockevt.o obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC) += timer-cs5535.o
obj-$(CONFIG_CLKSRC_JCORE_PIT) += jcore-pit.o obj-$(CONFIG_CLKSRC_JCORE_PIT) += jcore-pit.o
obj-$(CONFIG_SH_TIMER_CMT) += sh_cmt.o obj-$(CONFIG_SH_TIMER_CMT) += sh_cmt.o
obj-$(CONFIG_SH_TIMER_MTU2) += sh_mtu2.o obj-$(CONFIG_SH_TIMER_MTU2) += sh_mtu2.o
...@@ -29,7 +29,7 @@ obj-$(CONFIG_BCM2835_TIMER) += bcm2835_timer.o ...@@ -29,7 +29,7 @@ obj-$(CONFIG_BCM2835_TIMER) += bcm2835_timer.o
obj-$(CONFIG_CLPS711X_TIMER) += clps711x-timer.o obj-$(CONFIG_CLPS711X_TIMER) += clps711x-timer.o
obj-$(CONFIG_ATLAS7_TIMER) += timer-atlas7.o obj-$(CONFIG_ATLAS7_TIMER) += timer-atlas7.o
obj-$(CONFIG_MXS_TIMER) += mxs_timer.o obj-$(CONFIG_MXS_TIMER) += mxs_timer.o
obj-$(CONFIG_CLKSRC_PXA) += pxa_timer.o obj-$(CONFIG_CLKSRC_PXA) += timer-pxa.o
obj-$(CONFIG_PRIMA2_TIMER) += timer-prima2.o obj-$(CONFIG_PRIMA2_TIMER) += timer-prima2.o
obj-$(CONFIG_U300_TIMER) += timer-u300.o obj-$(CONFIG_U300_TIMER) += timer-u300.o
obj-$(CONFIG_SUN4I_TIMER) += timer-sun4i.o obj-$(CONFIG_SUN4I_TIMER) += timer-sun4i.o
...@@ -69,7 +69,7 @@ obj-$(CONFIG_KEYSTONE_TIMER) += timer-keystone.o ...@@ -69,7 +69,7 @@ obj-$(CONFIG_KEYSTONE_TIMER) += timer-keystone.o
obj-$(CONFIG_INTEGRATOR_AP_TIMER) += timer-integrator-ap.o obj-$(CONFIG_INTEGRATOR_AP_TIMER) += timer-integrator-ap.o
obj-$(CONFIG_CLKSRC_VERSATILE) += timer-versatile.o obj-$(CONFIG_CLKSRC_VERSATILE) += timer-versatile.o
obj-$(CONFIG_CLKSRC_MIPS_GIC) += mips-gic-timer.o obj-$(CONFIG_CLKSRC_MIPS_GIC) += mips-gic-timer.o
obj-$(CONFIG_CLKSRC_TANGO_XTAL) += tango_xtal.o obj-$(CONFIG_CLKSRC_TANGO_XTAL) += timer-tango-xtal.o
obj-$(CONFIG_CLKSRC_IMX_GPT) += timer-imx-gpt.o obj-$(CONFIG_CLKSRC_IMX_GPT) += timer-imx-gpt.o
obj-$(CONFIG_CLKSRC_IMX_TPM) += timer-imx-tpm.o obj-$(CONFIG_CLKSRC_IMX_TPM) += timer-imx-tpm.o
obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o
......
...@@ -326,6 +326,48 @@ static u64 notrace arm64_1188873_read_cntvct_el0(void) ...@@ -326,6 +326,48 @@ static u64 notrace arm64_1188873_read_cntvct_el0(void)
} }
#endif #endif
#ifdef CONFIG_SUN50I_ERRATUM_UNKNOWN1
/*
* The low bits of the counter registers are indeterminate while bit 10 or
* greater is rolling over. Since the counter value can jump both backward
* (7ff -> 000 -> 800) and forward (7ff -> fff -> 800), ignore register values
* with all ones or all zeros in the low bits. Bound the loop by the maximum
* number of CPU cycles in 3 consecutive 24 MHz counter periods.
*/
#define __sun50i_a64_read_reg(reg) ({ \
u64 _val; \
int _retries = 150; \
\
do { \
_val = read_sysreg(reg); \
_retries--; \
} while (((_val + 1) & GENMASK(9, 0)) <= 1 && _retries); \
\
WARN_ON_ONCE(!_retries); \
_val; \
})
static u64 notrace sun50i_a64_read_cntpct_el0(void)
{
return __sun50i_a64_read_reg(cntpct_el0);
}
static u64 notrace sun50i_a64_read_cntvct_el0(void)
{
return __sun50i_a64_read_reg(cntvct_el0);
}
static u32 notrace sun50i_a64_read_cntp_tval_el0(void)
{
return read_sysreg(cntp_cval_el0) - sun50i_a64_read_cntpct_el0();
}
static u32 notrace sun50i_a64_read_cntv_tval_el0(void)
{
return read_sysreg(cntv_cval_el0) - sun50i_a64_read_cntvct_el0();
}
#endif
#ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND #ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND
DEFINE_PER_CPU(const struct arch_timer_erratum_workaround *, timer_unstable_counter_workaround); DEFINE_PER_CPU(const struct arch_timer_erratum_workaround *, timer_unstable_counter_workaround);
EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround); EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround);
...@@ -423,6 +465,19 @@ static const struct arch_timer_erratum_workaround ool_workarounds[] = { ...@@ -423,6 +465,19 @@ static const struct arch_timer_erratum_workaround ool_workarounds[] = {
.read_cntvct_el0 = arm64_1188873_read_cntvct_el0, .read_cntvct_el0 = arm64_1188873_read_cntvct_el0,
}, },
#endif #endif
#ifdef CONFIG_SUN50I_ERRATUM_UNKNOWN1
{
.match_type = ate_match_dt,
.id = "allwinner,erratum-unknown1",
.desc = "Allwinner erratum UNKNOWN1",
.read_cntp_tval_el0 = sun50i_a64_read_cntp_tval_el0,
.read_cntv_tval_el0 = sun50i_a64_read_cntv_tval_el0,
.read_cntpct_el0 = sun50i_a64_read_cntpct_el0,
.read_cntvct_el0 = sun50i_a64_read_cntvct_el0,
.set_next_event_phys = erratum_set_next_event_tval_phys,
.set_next_event_virt = erratum_set_next_event_tval_virt,
},
#endif
}; };
typedef bool (*ate_match_fn_t)(const struct arch_timer_erratum_workaround *, typedef bool (*ate_match_fn_t)(const struct arch_timer_erratum_workaround *,
......
...@@ -10,14 +10,12 @@ ...@@ -10,14 +10,12 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <linux/sched.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clockchips.h> #include <linux/clockchips.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/platform_device.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/percpu.h> #include <linux/percpu.h>
#include <linux/of.h> #include <linux/of.h>
...@@ -388,6 +386,13 @@ static void exynos4_mct_tick_start(unsigned long cycles, ...@@ -388,6 +386,13 @@ static void exynos4_mct_tick_start(unsigned long cycles,
exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET); exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET);
} }
static void exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
{
/* Clear the MCT tick interrupt */
if (readl_relaxed(reg_base + mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1)
exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
}
static int exynos4_tick_set_next_event(unsigned long cycles, static int exynos4_tick_set_next_event(unsigned long cycles,
struct clock_event_device *evt) struct clock_event_device *evt)
{ {
...@@ -404,6 +409,7 @@ static int set_state_shutdown(struct clock_event_device *evt) ...@@ -404,6 +409,7 @@ static int set_state_shutdown(struct clock_event_device *evt)
mevt = container_of(evt, struct mct_clock_event_device, evt); mevt = container_of(evt, struct mct_clock_event_device, evt);
exynos4_mct_tick_stop(mevt); exynos4_mct_tick_stop(mevt);
exynos4_mct_tick_clear(mevt);
return 0; return 0;
} }
...@@ -420,8 +426,11 @@ static int set_state_periodic(struct clock_event_device *evt) ...@@ -420,8 +426,11 @@ static int set_state_periodic(struct clock_event_device *evt)
return 0; return 0;
} }
static void exynos4_mct_tick_clear(struct mct_clock_event_device *mevt) static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
{ {
struct mct_clock_event_device *mevt = dev_id;
struct clock_event_device *evt = &mevt->evt;
/* /*
* This is for supporting oneshot mode. * This is for supporting oneshot mode.
* Mct would generate interrupt periodically * Mct would generate interrupt periodically
...@@ -430,16 +439,6 @@ static void exynos4_mct_tick_clear(struct mct_clock_event_device *mevt) ...@@ -430,16 +439,6 @@ static void exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
if (!clockevent_state_periodic(&mevt->evt)) if (!clockevent_state_periodic(&mevt->evt))
exynos4_mct_tick_stop(mevt); exynos4_mct_tick_stop(mevt);
/* Clear the MCT tick interrupt */
if (readl_relaxed(reg_base + mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1)
exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
}
static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
{
struct mct_clock_event_device *mevt = dev_id;
struct clock_event_device *evt = &mevt->evt;
exynos4_mct_tick_clear(mevt); exynos4_mct_tick_clear(mevt);
evt->event_handler(evt); evt->event_handler(evt);
...@@ -507,13 +506,12 @@ static int __init exynos4_timer_resources(struct device_node *np, void __iomem * ...@@ -507,13 +506,12 @@ static int __init exynos4_timer_resources(struct device_node *np, void __iomem *
int err, cpu; int err, cpu;
struct clk *mct_clk, *tick_clk; struct clk *mct_clk, *tick_clk;
tick_clk = np ? of_clk_get_by_name(np, "fin_pll") : tick_clk = of_clk_get_by_name(np, "fin_pll");
clk_get(NULL, "fin_pll");
if (IS_ERR(tick_clk)) if (IS_ERR(tick_clk))
panic("%s: unable to determine tick clock rate\n", __func__); panic("%s: unable to determine tick clock rate\n", __func__);
clk_rate = clk_get_rate(tick_clk); clk_rate = clk_get_rate(tick_clk);
mct_clk = np ? of_clk_get_by_name(np, "mct") : clk_get(NULL, "mct"); mct_clk = of_clk_get_by_name(np, "mct");
if (IS_ERR(mct_clk)) if (IS_ERR(mct_clk))
panic("%s: unable to retrieve mct clock instance\n", __func__); panic("%s: unable to retrieve mct clock instance\n", __func__);
clk_prepare_enable(mct_clk); clk_prepare_enable(mct_clk);
...@@ -562,7 +560,19 @@ static int __init exynos4_timer_resources(struct device_node *np, void __iomem * ...@@ -562,7 +560,19 @@ static int __init exynos4_timer_resources(struct device_node *np, void __iomem *
return 0; return 0;
out_irq: out_irq:
if (mct_int_type == MCT_INT_PPI) {
free_percpu_irq(mct_irqs[MCT_L0_IRQ], &percpu_mct_tick); free_percpu_irq(mct_irqs[MCT_L0_IRQ], &percpu_mct_tick);
} else {
for_each_possible_cpu(cpu) {
struct mct_clock_event_device *pcpu_mevt =
per_cpu_ptr(&percpu_mct_tick, cpu);
if (pcpu_mevt->evt.irq != -1) {
free_irq(pcpu_mevt->evt.irq, pcpu_mevt);
pcpu_mevt->evt.irq = -1;
}
}
}
return err; return err;
} }
...@@ -581,11 +591,7 @@ static int __init mct_init_dt(struct device_node *np, unsigned int int_type) ...@@ -581,11 +591,7 @@ static int __init mct_init_dt(struct device_node *np, unsigned int int_type)
* timer irqs are specified after the four global timer * timer irqs are specified after the four global timer
* irqs are specified. * irqs are specified.
*/ */
#ifdef CONFIG_OF
nr_irqs = of_irq_count(np); nr_irqs = of_irq_count(np);
#else
nr_irqs = 0;
#endif
for (i = MCT_L0_IRQ; i < nr_irqs; i++) for (i = MCT_L0_IRQ; i < nr_irqs; i++)
mct_irqs[i] = irq_of_parse_and_map(np, i); mct_irqs[i] = irq_of_parse_and_map(np, i);
......
...@@ -95,13 +95,30 @@ static int __init riscv_timer_init_dt(struct device_node *n) ...@@ -95,13 +95,30 @@ static int __init riscv_timer_init_dt(struct device_node *n)
struct clocksource *cs; struct clocksource *cs;
hartid = riscv_of_processor_hartid(n); hartid = riscv_of_processor_hartid(n);
if (hartid < 0) {
pr_warn("Not valid hartid for node [%pOF] error = [%d]\n",
n, hartid);
return hartid;
}
cpuid = riscv_hartid_to_cpuid(hartid); cpuid = riscv_hartid_to_cpuid(hartid);
if (cpuid < 0) {
pr_warn("Invalid cpuid for hartid [%d]\n", hartid);
return cpuid;
}
if (cpuid != smp_processor_id()) if (cpuid != smp_processor_id())
return 0; return 0;
pr_info("%s: Registering clocksource cpuid [%d] hartid [%d]\n",
__func__, cpuid, hartid);
cs = per_cpu_ptr(&riscv_clocksource, cpuid); cs = per_cpu_ptr(&riscv_clocksource, cpuid);
clocksource_register_hz(cs, riscv_timebase); error = clocksource_register_hz(cs, riscv_timebase);
if (error) {
pr_err("RISCV timer register failed [%d] for cpu = [%d]\n",
error, cpuid);
return error;
}
sched_clock_register(riscv_sched_clock, sched_clock_register(riscv_sched_clock,
BITS_PER_LONG, riscv_timebase); BITS_PER_LONG, riscv_timebase);
...@@ -110,8 +127,8 @@ static int __init riscv_timer_init_dt(struct device_node *n) ...@@ -110,8 +127,8 @@ static int __init riscv_timer_init_dt(struct device_node *n)
"clockevents/riscv/timer:starting", "clockevents/riscv/timer:starting",
riscv_timer_starting_cpu, riscv_timer_dying_cpu); riscv_timer_starting_cpu, riscv_timer_dying_cpu);
if (error) if (error)
pr_err("RISCV timer register failed [%d] for cpu = [%d]\n", pr_err("cpu hp setup state failed for RISCV timer [%d]\n",
error, cpuid); error);
return error; return error;
} }
......
...@@ -202,6 +202,11 @@ static int __init sun5i_setup_clocksource(struct device_node *node, ...@@ -202,6 +202,11 @@ static int __init sun5i_setup_clocksource(struct device_node *node,
} }
rate = clk_get_rate(clk); rate = clk_get_rate(clk);
if (!rate) {
pr_err("Couldn't get parent clock rate\n");
ret = -EINVAL;
goto err_disable_clk;
}
cs->timer.base = base; cs->timer.base = base;
cs->timer.clk = clk; cs->timer.clk = clk;
...@@ -275,6 +280,11 @@ static int __init sun5i_setup_clockevent(struct device_node *node, void __iomem ...@@ -275,6 +280,11 @@ static int __init sun5i_setup_clockevent(struct device_node *node, void __iomem
} }
rate = clk_get_rate(clk); rate = clk_get_rate(clk);
if (!rate) {
pr_err("Couldn't get parent clock rate\n");
ret = -EINVAL;
goto err_disable_clk;
}
ce->timer.base = base; ce->timer.base = base;
ce->timer.ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); ce->timer.ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
......
This diff is collapsed.
...@@ -76,6 +76,7 @@ config ARCH_TEGRA_210_SOC ...@@ -76,6 +76,7 @@ config ARCH_TEGRA_210_SOC
select PINCTRL_TEGRA210 select PINCTRL_TEGRA210
select SOC_TEGRA_FLOWCTRL select SOC_TEGRA_FLOWCTRL
select SOC_TEGRA_PMC select SOC_TEGRA_PMC
select TEGRA_TIMER
help help
Enable support for the NVIDIA Tegra210 SoC. Also known as Tegra X1, Enable support for the NVIDIA Tegra210 SoC. Also known as Tegra X1,
the Tegra210 has four Cortex-A57 cores paired with four Cortex-A53 the Tegra210 has four Cortex-A57 cores paired with four Cortex-A53
......
...@@ -121,6 +121,7 @@ enum cpuhp_state { ...@@ -121,6 +121,7 @@ enum cpuhp_state {
CPUHP_AP_EXYNOS4_MCT_TIMER_STARTING, CPUHP_AP_EXYNOS4_MCT_TIMER_STARTING,
CPUHP_AP_ARM_TWD_STARTING, CPUHP_AP_ARM_TWD_STARTING,
CPUHP_AP_QCOM_TIMER_STARTING, CPUHP_AP_QCOM_TIMER_STARTING,
CPUHP_AP_TEGRA_TIMER_STARTING,
CPUHP_AP_ARMADA_TIMER_STARTING, CPUHP_AP_ARMADA_TIMER_STARTING,
CPUHP_AP_MARCO_TIMER_STARTING, CPUHP_AP_MARCO_TIMER_STARTING,
CPUHP_AP_MIPS_GIC_TIMER_STARTING, CPUHP_AP_MIPS_GIC_TIMER_STARTING,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment