diff options
47 files changed, 495 insertions, 304 deletions
diff --git a/Documentation/devicetree/bindings/timer/cortina,gemini-timer.txt b/Documentation/devicetree/bindings/timer/cortina,gemini-timer.txt deleted file mode 100644 index 16ea1d3b2e9e..000000000000 --- a/Documentation/devicetree/bindings/timer/cortina,gemini-timer.txt +++ /dev/null @@ -1,22 +0,0 @@ -Cortina Systems Gemini timer - -This timer is embedded in the Cortina Systems Gemini SoCs. - -Required properties: - -- compatible : Must be "cortina,gemini-timer" -- reg : Should contain registers location and length -- interrupts : Should contain the three timer interrupts with - flags for rising edge -- syscon : a phandle to the global Gemini system controller - -Example: - -timer@43000000 { - compatible = "cortina,gemini-timer"; - reg = <0x43000000 0x1000>; - interrupts = <14 IRQ_TYPE_EDGE_RISING>, /* Timer 1 */ - <15 IRQ_TYPE_EDGE_RISING>, /* Timer 2 */ - <16 IRQ_TYPE_EDGE_RISING>; /* Timer 3 */ - syscon = <&syscon>; -}; diff --git a/Documentation/devicetree/bindings/timer/faraday,fttmr010.txt b/Documentation/devicetree/bindings/timer/faraday,fttmr010.txt new file mode 100644 index 000000000000..b73ca6cd07f8 --- /dev/null +++ b/Documentation/devicetree/bindings/timer/faraday,fttmr010.txt @@ -0,0 +1,33 @@ +Faraday Technology timer + +This timer is a generic IP block from Faraday Technology, embedded in the +Cortina Systems Gemini SoCs and other designs. + +Required properties: + +- compatible : Must be one of + "faraday,fttmr010" + "cortina,gemini-timer" +- reg : Should contain registers location and length +- interrupts : Should contain the three timer interrupts usually with + flags for falling edge + +Optionally required properties: + +- clocks : a clock to provide the tick rate for "faraday,fttmr010" +- clock-names : should be "EXTCLK" and "PCLK" for the external tick timer + and peripheral clock respectively, for "faraday,fttmr010" +- syscon : a phandle to the global Gemini system controller if the compatible + type is "cortina,gemini-timer" + +Example: + +timer@43000000 { + compatible = "faraday,fttmr010"; + reg = <0x43000000 0x1000>; + interrupts = <14 IRQ_TYPE_EDGE_FALLING>, /* Timer 1 */ + <15 IRQ_TYPE_EDGE_FALLING>, /* Timer 2 */ + <16 IRQ_TYPE_EDGE_FALLING>; /* Timer 3 */ + clocks = <&extclk>, <&pclk>; + clock-names = "EXTCLK", "PCLK"; +}; diff --git a/Documentation/devicetree/bindings/timer/rockchip,rk-timer.txt b/Documentation/devicetree/bindings/timer/rockchip,rk-timer.txt index a41b184d5538..16a5f4577a61 100644 --- a/Documentation/devicetree/bindings/timer/rockchip,rk-timer.txt +++ b/Documentation/devicetree/bindings/timer/rockchip,rk-timer.txt @@ -1,9 +1,15 @@ Rockchip rk timer Required properties: -- compatible: shall be one of: - "rockchip,rk3288-timer" - for rk3066, rk3036, rk3188, rk322x, rk3288, rk3368 - "rockchip,rk3399-timer" - for rk3399 +- compatible: should be: + "rockchip,rk3036-timer", "rockchip,rk3288-timer": for Rockchip RK3036 + "rockchip,rk3066-timer", "rockchip,rk3288-timer": for Rockchip RK3066 + "rockchip,rk3188-timer", "rockchip,rk3288-timer": for Rockchip RK3188 + "rockchip,rk3228-timer", "rockchip,rk3288-timer": for Rockchip RK3228 + "rockchip,rk3229-timer", "rockchip,rk3288-timer": for Rockchip RK3229 + "rockchip,rk3288-timer": for Rockchip RK3288 + "rockchip,rk3368-timer", "rockchip,rk3288-timer": for Rockchip RK3368 + "rockchip,rk3399-timer": for Rockchip RK3399 - reg: base address of the timer register starting with TIMERS CONTROL register - interrupts: should contain the interrupts for Timer0 - clocks : must contain an entry for each entry in clock-names diff --git a/MAINTAINERS b/MAINTAINERS index c776906f67a9..68b1a1492e96 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11099,6 +11099,7 @@ F: drivers/power/supply/bq27xxx_battery_i2c.c TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER M: John Stultz <john.stultz@linaro.org> M: Thomas Gleixner <tglx@linutronix.de> +R: Stephen Boyd <sboyd@codeaurora.org> L: linux-kernel@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core S: Supported diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi index cf91254d0a43..1aff4ad22fc4 100644 --- a/arch/arm/boot/dts/rk3188.dtsi +++ b/arch/arm/boot/dts/rk3188.dtsi @@ -106,6 +106,22 @@ }; }; + timer3: timer@2000e000 { + compatible = "rockchip,rk3188-timer", "rockchip,rk3288-timer"; + reg = <0x2000e000 0x20>; + interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru SCLK_TIMER3>, <&cru PCLK_TIMER3>; + clock-names = "timer", "pclk"; + }; + + timer6: timer@200380a0 { + compatible = "rockchip,rk3188-timer", "rockchip,rk3288-timer"; + reg = <0x200380a0 0x20>; + interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru SCLK_TIMER6>, <&cru PCLK_TIMER0>; + clock-names = "timer", "pclk"; + }; + i2s0: i2s@1011a000 { compatible = "rockchip,rk3188-i2s", "rockchip,rk3066-i2s"; reg = <0x1011a000 0x2000>; @@ -530,6 +546,7 @@ &global_timer { interrupts = <GIC_PPI 11 0xf04>; + status = "disabled"; }; &local_timer { diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi index 9dff8221112c..641607d9ad29 100644 --- a/arch/arm/boot/dts/rk322x.dtsi +++ b/arch/arm/boot/dts/rk322x.dtsi @@ -325,7 +325,7 @@ }; timer: timer@110c0000 { - compatible = "rockchip,rk3288-timer"; + compatible = "rockchip,rk3228-timer", "rockchip,rk3288-timer"; reg = <0x110c0000 0x20>; interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>; clocks = <&xin24m>, <&cru PCLK_TIMER>; diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index af80a7c44faf..545d541ae20e 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -67,20 +67,22 @@ 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 depends on ARM || ARM64 select CLKSRC_OF + select CLKSRC_MMIO help Enables the support for the rockchip timer driver. 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/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 bf9e9d76375e..74183a7315ac 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -1269,7 +1269,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/em_sti.c b/drivers/clocksource/em_sti.c index aff87df07449..bc48cbf6a795 100644 --- a/drivers/clocksource/em_sti.c +++ b/drivers/clocksource/em_sti.c @@ -78,15 +78,12 @@ 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; } - /* 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); @@ -107,7 +104,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) @@ -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) @@ -303,6 +293,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 +314,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,12 +328,20 @@ 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; + } + + 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); 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); } 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/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 <linux/clockchips.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/sched_clock.h> +#include <linux/slab.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> @@ -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); 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/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) 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) { 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 a28f496e97cf..b9b97f630c4d 100644 --- a/drivers/clocksource/time-orion.c +++ b/drivers/clocksource/time-orion.c @@ -15,6 +15,7 @@ #include <linux/bitops.h> #include <linux/clk.h> #include <linux/clockchips.h> +#include <linux/delay.h> #include <linux/interrupt.h> #include <linux/of_address.h> #include <linux/of_irq.h> @@ -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. */ @@ -106,6 +122,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; @@ -124,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; } @@ -135,6 +152,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 +161,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"); + pr_err("Failed to initialize mmio timer\n"); 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,9 +181,12 @@ 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); + + orion_delay_timer_init(rate); + return 0; } CLOCKSOURCE_OF_DECLARE(orion_timer, "marvell,orion-timer", orion_timer_init); 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-gemini.c b/drivers/clocksource/timer-fttmr010.c index dda27b7bf1a1..b4a6f1e4bc54 100644 --- a/drivers/clocksource/timer-gemini.c +++ b/drivers/clocksource/timer-fttmr010.c @@ -1,5 +1,5 @@ /* - * Gemini timer driver + * Faraday Technology FTTMR010 timer driver * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org> * * Based on a rewrite of arch/arm/mach-gemini/timer.c: @@ -16,17 +16,7 @@ #include <linux/clockchips.h> #include <linux/clocksource.h> #include <linux/sched_clock.h> - -/* - * 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 <linux/clk.h> /* * Register definitions for the timers @@ -77,12 +67,12 @@ static unsigned int tick_rate; static void __iomem *base; -static u64 notrace gemini_read_sched_clock(void) +static u64 notrace fttmr010_read_sched_clock(void) { return readl(base + TIMER3_COUNT); } -static int gemini_timer_set_next_event(unsigned long cycles, +static int fttmr010_timer_set_next_event(unsigned long cycles, struct clock_event_device *evt) { u32 cr; @@ -96,7 +86,7 @@ static int gemini_timer_set_next_event(unsigned long cycles, return 0; } -static int gemini_timer_shutdown(struct clock_event_device *evt) +static int fttmr010_timer_shutdown(struct clock_event_device *evt) { u32 cr; @@ -127,7 +117,7 @@ static int gemini_timer_shutdown(struct clock_event_device *evt) return 0; } -static int gemini_timer_set_periodic(struct clock_event_device *evt) +static int fttmr010_timer_set_periodic(struct clock_event_device *evt) { u32 period = DIV_ROUND_CLOSEST(tick_rate, HZ); u32 cr; @@ -158,54 +148,40 @@ static int gemini_timer_set_periodic(struct clock_event_device *evt) } /* Use TIMER1 as clock event */ -static struct clock_event_device gemini_clockevent = { +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 = 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, + .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 gemini_timer_interrupt(int irq, void *dev_id) +static irqreturn_t fttmr010_timer_interrupt(int irq, void *dev_id) { - struct clock_event_device *evt = &gemini_clockevent; + struct clock_event_device *evt = &fttmr010_clockevent; evt->event_handler(evt); return IRQ_HANDLED; } -static struct irqaction gemini_timer_irq = { - .name = "Gemini Timer Tick", +static struct irqaction fttmr010_timer_irq = { + .name = "Faraday FTTMR010 Timer Tick", .flags = IRQF_TIMER, - .handler = gemini_timer_interrupt, + .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 */ @@ -255,9 +211,9 @@ static int __init gemini_timer_of_init(struct device_node *np) writel(0, base + TIMER3_MATCH1); writel(0, base + TIMER3_MATCH2); clocksource_mmio_init(base + TIMER3_COUNT, - "gemini_clocksource", tick_rate, + "fttmr010_clocksource", tick_rate, 300, 32, clocksource_mmio_readl_up); - sched_clock_register(gemini_read_sched_clock, 32, tick_rate); + sched_clock_register(fttmr010_read_sched_clock, 32, tick_rate); /* * Setup clockevent timer (interrupt-driven.) @@ -266,12 +222,82 @@ static int __init gemini_timer_of_init(struct device_node *np) 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, + 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(nomadik_mtu, "cortina,gemini-timer", - gemini_timer_of_init); + +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); 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; } diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h index 5d3053c34fb3..eef1569e5cd0 100644 --- a/include/linux/clockchips.h +++ b/include/linux/clockchips.h @@ -182,7 +182,6 @@ extern u64 clockevent_delta2ns(unsigned long latch, struct clock_event_device *e extern void clockevents_register_device(struct clock_event_device *dev); extern int clockevents_unbind_device(struct clock_event_device *ced, int cpu); -extern void clockevents_config(struct clock_event_device *dev, u32 freq); extern void clockevents_config_and_register(struct clock_event_device *dev, u32 freq, unsigned long min_delta, unsigned long max_delta); diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 249e579ecd4c..23d58fcd4d9a 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -276,8 +276,6 @@ static inline int hrtimer_is_hres_active(struct hrtimer *timer) return timer->base->cpu_base->hres_active; } -extern void hrtimer_peek_ahead_timers(void); - /* * The resolution of the clocks. The resolution value is returned in * the clock_getres() system call to give application programmers an @@ -300,8 +298,6 @@ extern unsigned int hrtimer_resolution; #define hrtimer_resolution (unsigned int)LOW_RES_NSEC -static inline void hrtimer_peek_ahead_timers(void) { } - static inline int hrtimer_is_hres_active(struct hrtimer *timer) { return 0; diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 97ac0951f164..4237e0744e26 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -468,7 +468,7 @@ void clockevents_register_device(struct clock_event_device *dev) } EXPORT_SYMBOL_GPL(clockevents_register_device); -void clockevents_config(struct clock_event_device *dev, u32 freq) +static void clockevents_config(struct clock_event_device *dev, u32 freq) { u64 sec; diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index ec08f527d7ee..1ef82cdb61ff 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -1368,10 +1368,7 @@ retry: ktime_to_ns(delta)); } -/* - * local version of hrtimer_peek_ahead_timers() called with interrupts - * disabled. - */ +/* called with interrupts disabled */ static inline void __hrtimer_peek_ahead_timers(void) { struct tick_device *td; diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c index 4513ad16a253..76bea3a47d4b 100644 --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c @@ -825,6 +825,8 @@ static void check_thread_timers(struct task_struct *tsk, * At the hard limit, we just die. * No need to calculate anything else now. */ + pr_info("CPU Watchdog Timeout (hard): %s[%d]\n", + tsk->comm, task_pid_nr(tsk)); __group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk); return; } @@ -836,8 +838,7 @@ static void check_thread_timers(struct task_struct *tsk, soft += USEC_PER_SEC; sig->rlim[RLIMIT_RTTIME].rlim_cur = soft; } - printk(KERN_INFO - "RT Watchdog Timeout: %s[%d]\n", + pr_info("RT Watchdog Timeout (soft): %s[%d]\n", tsk->comm, task_pid_nr(tsk)); __group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk); } @@ -935,6 +936,8 @@ static void check_process_timers(struct task_struct *tsk, * At the hard limit, we just die. * No need to calculate anything else now. */ + pr_info("RT Watchdog Timeout (hard): %s[%d]\n", + tsk->comm, task_pid_nr(tsk)); __group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk); return; } @@ -942,6 +945,8 @@ static void check_process_timers(struct task_struct *tsk, /* * At the soft limit, send a SIGXCPU every second. */ + pr_info("CPU Watchdog Timeout (soft): %s[%d]\n", + tsk->comm, task_pid_nr(tsk)); __group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk); if (soft < hard) { soft++; diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c index ea6b610c4c57..2d8f05aad442 100644 --- a/kernel/time/sched_clock.c +++ b/kernel/time/sched_clock.c @@ -206,6 +206,11 @@ sched_clock_register(u64 (*read)(void), int bits, unsigned long rate) update_clock_read_data(&rd); + if (sched_clock_timer.function != NULL) { + /* update timeout for clock wrap */ + hrtimer_start(&sched_clock_timer, cd.wrap_kt, HRTIMER_MODE_REL); + } + r = rate; if (r >= 4000000) { r /= 1000000; diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 5b63a2102c29..9652bc57fd09 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -996,8 +996,7 @@ static int adjust_historical_crosststamp(struct system_time_snapshot *history, return 0; /* Interpolate shortest distance from beginning or end of history */ - interp_forward = partial_history_cycles > total_history_cycles/2 ? - true : false; + interp_forward = partial_history_cycles > total_history_cycles / 2; partial_history_cycles = interp_forward ? total_history_cycles - partial_history_cycles : partial_history_cycles; diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c index ff8d5c13d04b..0e7f5428a148 100644 --- a/kernel/time/timer_list.c +++ b/kernel/time/timer_list.c @@ -16,6 +16,7 @@ #include <linux/sched.h> #include <linux/seq_file.h> #include <linux/kallsyms.h> +#include <linux/nmi.h> #include <linux/uaccess.h> @@ -86,6 +87,9 @@ print_active_timers(struct seq_file *m, struct hrtimer_clock_base *base, next_one: i = 0; + + touch_nmi_watchdog(); + raw_spin_lock_irqsave(&base->cpu_base->lock, flags); curr = timerqueue_getnext(&base->active); @@ -197,6 +201,8 @@ print_tickdevice(struct seq_file *m, struct tick_device *td, int cpu) { struct clock_event_device *dev = td->evtdev; + touch_nmi_watchdog(); + SEQ_printf(m, "Tick Device: mode: %d\n", td->mode); if (cpu < 0) SEQ_printf(m, "Broadcast device\n"); |