Commit dabc4df2 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'timers-core-2020-06-02' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull timer updates from Thomas Gleixner:
 "The truly boring timer and clocksource updates for 5.8:

   - Not a single new clocksource or clockevent driver!

   - Device tree updates for various chips

   - Fixes and improvements and cleanups all over the place"

* tag 'timers-core-2020-06-02' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (27 commits)
  dt-bindings: timer: Add renesas,em-sti bindings
  clocksource/drivers/timer-versatile: Clear OF_POPULATED flag
  clocksource: mips-gic-timer: Mark GIC timer as unstable if ref clock changes
  clocksource: mips-gic-timer: Register as sched_clock
  clocksource: dw_apb_timer_of: Fix missing clockevent timers
  clocksource: dw_apb_timer: Affiliate of-based timer with any CPU
  clocksource: dw_apb_timer: Make CPU-affiliation being optional
  dt-bindings: timer: Move snps,dw-apb-timer DT schema from rtc
  dt-bindings: rtc: Convert snps,dw-apb-timer to DT schema
  clocksource/drivers/timer-ti-dm: Do one override clock parent in prepare()
  clocksource/drivers/timer-ti-dm: Fix spelling mistake "detectt" -> "detect"
  clocksource/drivers/timer-ti-dm: Fix warning for set but not used
  clocksource/drivers/timer-ti-dm: Add clockevent and clocksource support
  clocksource/drivers/timer-ti-32k: Add support for initializing directly
  drivers/clocksource/arm_arch_timer: Remove duplicate error message
  clocksource/drivers/arc_timer: Remove duplicate error message
  clocksource/drivers/rda: drop redundant Kconfig dependency
  clocksource/drivers/timer-ti-dm: Fix warning for set but not used
  clocksource/drivers/timer-ti-dm: Add clockevent and clocksource support
  clocksource/drivers/timer-ti-32k: Add support for initializing directly
  ...
parents f6606d0c 809eb4e9
* Designware APB timer
Required properties:
- compatible: One of:
"snps,dw-apb-timer"
"snps,dw-apb-timer-sp" <DEPRECATED>
"snps,dw-apb-timer-osc" <DEPRECATED>
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: IRQ line for the timer.
- either clocks+clock-names or clock-frequency properties
Optional properties:
- clocks : list of clock specifiers, corresponding to entries in
the clock-names property;
- clock-names : should contain "timer" and "pclk" entries, matching entries
in the clocks property.
- clock-frequency: The frequency in HZ of the timer.
- clock-freq: For backwards compatibility with picoxcell
If using the clock specifiers, the pclk clock is optional, as not all
systems may use one.
Example:
timer@ffe00000 {
compatible = "snps,dw-apb-timer";
interrupts = <0 170 4>;
reg = <0xffe00000 0x1000>;
clocks = <&timer_clk>, <&timer_pclk>;
clock-names = "timer", "pclk";
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/timer/renesas,em-sti.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas EMMA Mobile System Timer
maintainers:
- Magnus Damm <magnus.damm@gmail.com>
properties:
compatible:
const: renesas,em-sti
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
clock-names:
const: sclk
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
timer@e0180000 {
compatible = "renesas,em-sti";
reg = <0xe0180000 0x54>;
interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sti_sclk>;
clock-names = "sclk";
};
# SPDX-License-Identifier: GPL-2.0-only
%YAML 1.2
---
$id: http://devicetree.org/schemas/timer/snps,dw-apb-timer.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Synopsys DesignWare APB Timer
maintainers:
- Daniel Lezcano <daniel.lezcano@linaro.org>
properties:
compatible:
oneOf:
- const: snps,dw-apb-timer
- enum:
- snps,dw-apb-timer-sp
- snps,dw-apb-timer-osc
deprecated: true
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
minItems: 1
items:
- description: Timer ticks reference clock source
- description: APB interface clock source
clock-names:
minItems: 1
items:
- const: timer
- const: pclk
clock-frequency: true
clock-freq:
$ref: "/schemas/types.yaml#/definitions/uint32"
description: |
Has the same meaning as the 'clock-frequency' property - timer clock
frequency in HZ, but is defined only for the backwards compatibility
with the picoxcell platform.
unevaluatedProperties: false
required:
- compatible
- reg
- interrupts
oneOf:
- required:
- clocks
- clock-names
- required:
- clock-frequency
- required:
- clock-freq
examples:
- |
timer@ffe00000 {
compatible = "snps,dw-apb-timer";
interrupts = <0 170 4>;
reg = <0xffe00000 0x1000>;
clocks = <&timer_clk>, <&timer_pclk>;
clock-names = "timer", "pclk";
};
- |
timer@ffe00000 {
compatible = "snps,dw-apb-timer";
interrupts = <0 170 4>;
reg = <0xffe00000 0x1000>;
clocks = <&timer_clk>;
clock-names = "timer";
};
- |
timer@ffe00000 {
compatible = "snps,dw-apb-timer";
interrupts = <0 170 4>;
reg = <0xffe00000 0x1000>;
clock-frequency = <25000000>;
};
...
...@@ -105,6 +105,7 @@ pwm7: dmtimer-pwm { ...@@ -105,6 +105,7 @@ pwm7: dmtimer-pwm {
ti,timers = <&timer7>; ti,timers = <&timer7>;
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&dmtimer7_pins>; pinctrl-0 = <&dmtimer7_pins>;
ti,clock-source = <0x01>;
}; };
vmmcsd_fixed: regulator-3v3 { vmmcsd_fixed: regulator-3v3 {
......
...@@ -156,6 +156,7 @@ pwm11: dmtimer-pwm@11 { ...@@ -156,6 +156,7 @@ pwm11: dmtimer-pwm@11 {
pinctrl-0 = <&pwm_pins>; pinctrl-0 = <&pwm_pins>;
ti,timers = <&timer11>; ti,timers = <&timer11>;
#pwm-cells = <3>; #pwm-cells = <3>;
ti,clock-source = <0x01>;
}; };
/* HS USB Host PHY on PORT 1 */ /* HS USB Host PHY on PORT 1 */
......
...@@ -65,6 +65,7 @@ pwm10: dmtimer-pwm { ...@@ -65,6 +65,7 @@ pwm10: dmtimer-pwm {
pinctrl-0 = <&pwm_pins>; pinctrl-0 = <&pwm_pins>;
ti,timers = <&timer10>; ti,timers = <&timer10>;
#pwm-cells = <3>; #pwm-cells = <3>;
ti,clock-source = <0x01>;
}; };
}; };
......
...@@ -150,6 +150,7 @@ pwm11: dmtimer-pwm { ...@@ -150,6 +150,7 @@ pwm11: dmtimer-pwm {
compatible = "ti,omap-dmtimer-pwm"; compatible = "ti,omap-dmtimer-pwm";
ti,timers = <&timer11>; ti,timers = <&timer11>;
#pwm-cells = <3>; #pwm-cells = <3>;
ti,clock-source = <0x01>;
}; };
hsusb2_phy: hsusb2_phy { hsusb2_phy: hsusb2_phy {
......
...@@ -120,7 +120,6 @@ config OWL_TIMER ...@@ -120,7 +120,6 @@ config OWL_TIMER
config RDA_TIMER config RDA_TIMER
bool "RDA timer driver" if COMPILE_TEST bool "RDA timer driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
select CLKSRC_MMIO select CLKSRC_MMIO
select TIMER_OF select TIMER_OF
help help
...@@ -562,16 +561,16 @@ config CLKSRC_VERSATILE ...@@ -562,16 +561,16 @@ config CLKSRC_VERSATILE
bool "ARM Versatile (Express) reference platforms clock source" if COMPILE_TEST bool "ARM Versatile (Express) reference platforms clock source" if COMPILE_TEST
depends on GENERIC_SCHED_CLOCK && !ARCH_USES_GETTIMEOFFSET depends on GENERIC_SCHED_CLOCK && !ARCH_USES_GETTIMEOFFSET
select TIMER_OF select TIMER_OF
default y if MFD_VEXPRESS_SYSREG default y if (ARCH_VEXPRESS || ARCH_VERSATILE) && ARM
help help
This option enables clock source based on free running This option enables clock source based on free running
counter available in the "System Registers" block of counter available in the "System Registers" block of
ARM Versatile, RealView and Versatile Express reference ARM Versatile and Versatile Express reference platforms.
platforms.
config CLKSRC_MIPS_GIC config CLKSRC_MIPS_GIC
bool bool
depends on MIPS_GIC depends on MIPS_GIC
select CLOCKSOURCE_WATCHDOG
select TIMER_OF select TIMER_OF
config CLKSRC_TANGO_XTAL config CLKSRC_TANGO_XTAL
...@@ -709,6 +708,7 @@ config MICROCHIP_PIT64B ...@@ -709,6 +708,7 @@ config MICROCHIP_PIT64B
bool "Microchip PIT64B support" bool "Microchip PIT64B support"
depends on OF || COMPILE_TEST depends on OF || COMPILE_TEST
select CLKSRC_MMIO select CLKSRC_MMIO
select TIMER_OF
help help
This option enables Microchip PIT64B timer for Atmel This option enables Microchip PIT64B timer for Atmel
based system. It supports the oneshot, the periodic based system. It supports the oneshot, the periodic
......
...@@ -18,6 +18,7 @@ obj-$(CONFIG_CLKSRC_MMIO) += mmio.o ...@@ -18,6 +18,7 @@ obj-$(CONFIG_CLKSRC_MMIO) += mmio.o
obj-$(CONFIG_DAVINCI_TIMER) += timer-davinci.o obj-$(CONFIG_DAVINCI_TIMER) += timer-davinci.o
obj-$(CONFIG_DIGICOLOR_TIMER) += timer-digicolor.o obj-$(CONFIG_DIGICOLOR_TIMER) += timer-digicolor.o
obj-$(CONFIG_OMAP_DM_TIMER) += timer-ti-dm.o obj-$(CONFIG_OMAP_DM_TIMER) += timer-ti-dm.o
obj-$(CONFIG_OMAP_DM_TIMER) += timer-ti-dm-systimer.o
obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o
obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_timer_of.o obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_timer_of.o
obj-$(CONFIG_FTTMR010_TIMER) += timer-fttmr010.o obj-$(CONFIG_FTTMR010_TIMER) += timer-fttmr010.o
......
...@@ -334,10 +334,8 @@ static int __init arc_clockevent_setup(struct device_node *node) ...@@ -334,10 +334,8 @@ static int __init arc_clockevent_setup(struct device_node *node)
} }
ret = arc_get_timer_clk(node); ret = arc_get_timer_clk(node);
if (ret) { if (ret)
pr_err("clockevent: missing clk\n");
return ret; return ret;
}
/* Needs apriori irq_set_percpu_devid() done in intc map function */ /* Needs apriori irq_set_percpu_devid() done in intc map function */
ret = request_percpu_irq(arc_timer_irq, timer_irq_handler, ret = request_percpu_irq(arc_timer_irq, timer_irq_handler,
......
...@@ -1588,10 +1588,8 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table) ...@@ -1588,10 +1588,8 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table)
arch_timers_present |= ARCH_TIMER_TYPE_CP15; arch_timers_present |= ARCH_TIMER_TYPE_CP15;
ret = acpi_gtdt_init(table, &platform_timer_count); ret = acpi_gtdt_init(table, &platform_timer_count);
if (ret) { if (ret)
pr_err("Failed to init GTDT table.\n");
return ret; return ret;
}
arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI] = arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI] =
acpi_gtdt_map_ppi(ARCH_TIMER_PHYS_NONSECURE_PPI); acpi_gtdt_map_ppi(ARCH_TIMER_PHYS_NONSECURE_PPI);
......
...@@ -222,7 +222,8 @@ static int apbt_next_event(unsigned long delta, ...@@ -222,7 +222,8 @@ static int apbt_next_event(unsigned long delta,
/** /**
* dw_apb_clockevent_init() - use an APB timer as a clock_event_device * dw_apb_clockevent_init() - use an APB timer as a clock_event_device
* *
* @cpu: The CPU the events will be targeted at. * @cpu: The CPU the events will be targeted at or -1 if CPU affiliation
* isn't required.
* @name: The name used for the timer and the IRQ for it. * @name: The name used for the timer and the IRQ for it.
* @rating: The rating to give the timer. * @rating: The rating to give the timer.
* @base: I/O base for the timer registers. * @base: I/O base for the timer registers.
...@@ -257,7 +258,7 @@ dw_apb_clockevent_init(int cpu, const char *name, unsigned rating, ...@@ -257,7 +258,7 @@ dw_apb_clockevent_init(int cpu, const char *name, unsigned rating,
dw_ced->ced.max_delta_ticks = 0x7fffffff; dw_ced->ced.max_delta_ticks = 0x7fffffff;
dw_ced->ced.min_delta_ns = clockevent_delta2ns(5000, &dw_ced->ced); dw_ced->ced.min_delta_ns = clockevent_delta2ns(5000, &dw_ced->ced);
dw_ced->ced.min_delta_ticks = 5000; dw_ced->ced.min_delta_ticks = 5000;
dw_ced->ced.cpumask = cpumask_of(cpu); dw_ced->ced.cpumask = cpu < 0 ? cpu_possible_mask : cpumask_of(cpu);
dw_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC | dw_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC |
CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_DYNIRQ; CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_DYNIRQ;
dw_ced->ced.set_state_shutdown = apbt_shutdown; dw_ced->ced.set_state_shutdown = apbt_shutdown;
......
...@@ -73,7 +73,7 @@ static void __init add_clockevent(struct device_node *event_timer) ...@@ -73,7 +73,7 @@ static void __init add_clockevent(struct device_node *event_timer)
timer_get_base_and_rate(event_timer, &iobase, &rate); timer_get_base_and_rate(event_timer, &iobase, &rate);
ced = dw_apb_clockevent_init(0, event_timer->name, 300, iobase, irq, ced = dw_apb_clockevent_init(-1, event_timer->name, 300, iobase, irq,
rate); rate);
if (!ced) if (!ced)
panic("Unable to initialise clockevent device"); panic("Unable to initialise clockevent device");
...@@ -147,10 +147,6 @@ static int num_called; ...@@ -147,10 +147,6 @@ static int num_called;
static int __init dw_apb_timer_init(struct device_node *timer) static int __init dw_apb_timer_init(struct device_node *timer)
{ {
switch (num_called) { switch (num_called) {
case 0:
pr_debug("%s: found clockevent timer\n", __func__);
add_clockevent(timer);
break;
case 1: case 1:
pr_debug("%s: found clocksource timer\n", __func__); pr_debug("%s: found clocksource timer\n", __func__);
add_clocksource(timer); add_clocksource(timer);
...@@ -161,6 +157,8 @@ static int __init dw_apb_timer_init(struct device_node *timer) ...@@ -161,6 +157,8 @@ static int __init dw_apb_timer_init(struct device_node *timer)
#endif #endif
break; break;
default: default:
pr_debug("%s: found clockevent timer\n", __func__);
add_clockevent(timer);
break; break;
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/percpu.h> #include <linux/percpu.h>
#include <linux/sched_clock.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/time.h> #include <linux/time.h>
#include <asm/mips-cps.h> #include <asm/mips-cps.h>
...@@ -23,14 +24,14 @@ ...@@ -23,14 +24,14 @@
static DEFINE_PER_CPU(struct clock_event_device, gic_clockevent_device); static DEFINE_PER_CPU(struct clock_event_device, gic_clockevent_device);
static int gic_timer_irq; static int gic_timer_irq;
static unsigned int gic_frequency; static unsigned int gic_frequency;
static bool __read_mostly gic_clock_unstable;
static u64 notrace gic_read_count(void) static void gic_clocksource_unstable(char *reason);
static u64 notrace gic_read_count_2x32(void)
{ {
unsigned int hi, hi2, lo; unsigned int hi, hi2, lo;
if (mips_cm_is64)
return read_gic_counter();
do { do {
hi = read_gic_counter_32h(); hi = read_gic_counter_32h();
lo = read_gic_counter_32l(); lo = read_gic_counter_32l();
...@@ -40,6 +41,19 @@ static u64 notrace gic_read_count(void) ...@@ -40,6 +41,19 @@ static u64 notrace gic_read_count(void)
return (((u64) hi) << 32) + lo; return (((u64) hi) << 32) + lo;
} }
static u64 notrace gic_read_count_64(void)
{
return read_gic_counter();
}
static u64 notrace gic_read_count(void)
{
if (mips_cm_is64)
return gic_read_count_64();
return gic_read_count_2x32();
}
static int gic_next_event(unsigned long delta, struct clock_event_device *evt) static int gic_next_event(unsigned long delta, struct clock_event_device *evt)
{ {
int cpu = cpumask_first(evt->cpumask); int cpu = cpumask_first(evt->cpumask);
...@@ -114,8 +128,10 @@ static int gic_clk_notifier(struct notifier_block *nb, unsigned long action, ...@@ -114,8 +128,10 @@ static int gic_clk_notifier(struct notifier_block *nb, unsigned long action,
{ {
struct clk_notifier_data *cnd = data; struct clk_notifier_data *cnd = data;
if (action == POST_RATE_CHANGE) if (action == POST_RATE_CHANGE) {
gic_clocksource_unstable("ref clock rate change");
on_each_cpu(gic_update_frequency, (void *)cnd->new_rate, 1); on_each_cpu(gic_update_frequency, (void *)cnd->new_rate, 1);
}
return NOTIFY_OK; return NOTIFY_OK;
} }
...@@ -161,6 +177,18 @@ static struct clocksource gic_clocksource = { ...@@ -161,6 +177,18 @@ static struct clocksource gic_clocksource = {
.vdso_clock_mode = VDSO_CLOCKMODE_GIC, .vdso_clock_mode = VDSO_CLOCKMODE_GIC,
}; };
static void gic_clocksource_unstable(char *reason)
{
if (gic_clock_unstable)
return;
gic_clock_unstable = true;
pr_info("GIC timer is unstable due to %s\n", reason);
clocksource_mark_unstable(&gic_clocksource);
}
static int __init __gic_clocksource_init(void) static int __init __gic_clocksource_init(void)
{ {
unsigned int count_width; unsigned int count_width;
...@@ -228,6 +256,18 @@ static int __init gic_clocksource_of_init(struct device_node *node) ...@@ -228,6 +256,18 @@ static int __init gic_clocksource_of_init(struct device_node *node)
/* And finally start the counter */ /* And finally start the counter */
clear_gic_config(GIC_CONFIG_COUNTSTOP); clear_gic_config(GIC_CONFIG_COUNTSTOP);
/*
* It's safe to use the MIPS GIC timer as a sched clock source only if
* its ticks are stable, which is true on either the platforms with
* stable CPU frequency or on the platforms with CM3 and CPU frequency
* change performed by the CPC core clocks divider.
*/
if (mips_cm_revision() >= CM_REV_CM3 || !IS_ENABLED(CONFIG_CPU_FREQ)) {
sched_clock_register(mips_cm_is64 ?
gic_read_count_64 : gic_read_count_2x32,
64, gic_frequency);
}
return 0; return 0;
} }
TIMER_OF_DECLARE(mips_gic_timer, "mti,gic-timer", TIMER_OF_DECLARE(mips_gic_timer, "mti,gic-timer",
......
...@@ -139,7 +139,6 @@ static int ...@@ -139,7 +139,6 @@ static int
clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev) clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
{ {
u32 alm; u32 alm;
int status = 0;
unsigned int val; unsigned int val;
BUG_ON(delta < 2); BUG_ON(delta < 2);
...@@ -163,7 +162,7 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev) ...@@ -163,7 +162,7 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
alm += delta; alm += delta;
regmap_write(regmap_st, AT91_ST_RTAR, alm); regmap_write(regmap_st, AT91_ST_RTAR, alm);
return status; return 0;
} }
static struct clock_event_device clkevt = { static struct clock_event_device clkevt = {
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include <clocksource/timer-davinci.h> #include <clocksource/timer-davinci.h>
#undef pr_fmt #undef pr_fmt
#define pr_fmt(fmt) "%s: " fmt "\n", __func__ #define pr_fmt(fmt) "%s: " fmt, __func__
#define DAVINCI_TIMER_REG_TIM12 0x10 #define DAVINCI_TIMER_REG_TIM12 0x10
#define DAVINCI_TIMER_REG_TIM34 0x14 #define DAVINCI_TIMER_REG_TIM34 0x14
...@@ -250,31 +250,29 @@ int __init davinci_timer_register(struct clk *clk, ...@@ -250,31 +250,29 @@ int __init davinci_timer_register(struct clk *clk,
rv = clk_prepare_enable(clk); rv = clk_prepare_enable(clk);
if (rv) { if (rv) {
pr_err("Unable to prepare and enable the timer clock"); pr_err("Unable to prepare and enable the timer clock\n");
return rv; return rv;
} }
if (!request_mem_region(timer_cfg->reg.start, if (!request_mem_region(timer_cfg->reg.start,
resource_size(&timer_cfg->reg), resource_size(&timer_cfg->reg),
"davinci-timer")) { "davinci-timer")) {
pr_err("Unable to request memory region"); pr_err("Unable to request memory region\n");
return -EBUSY; return -EBUSY;
} }
base = ioremap(timer_cfg->reg.start, resource_size(&timer_cfg->reg)); base = ioremap(timer_cfg->reg.start, resource_size(&timer_cfg->reg));
if (!base) { if (!base) {
pr_err("Unable to map the register range"); pr_err("Unable to map the register range\n");
return -ENOMEM; return -ENOMEM;
} }
davinci_timer_init(base); davinci_timer_init(base);
tick_rate = clk_get_rate(clk); tick_rate = clk_get_rate(clk);
clockevent = kzalloc(sizeof(*clockevent), GFP_KERNEL | __GFP_NOFAIL); clockevent = kzalloc(sizeof(*clockevent), GFP_KERNEL);
if (!clockevent) { if (!clockevent)
pr_err("Error allocating memory for clockevent data");
return -ENOMEM; return -ENOMEM;
}
clockevent->dev.name = "tim12"; clockevent->dev.name = "tim12";
clockevent->dev.features = CLOCK_EVT_FEAT_ONESHOT; clockevent->dev.features = CLOCK_EVT_FEAT_ONESHOT;
...@@ -298,7 +296,7 @@ int __init davinci_timer_register(struct clk *clk, ...@@ -298,7 +296,7 @@ int __init davinci_timer_register(struct clk *clk,
davinci_timer_irq_timer, IRQF_TIMER, davinci_timer_irq_timer, IRQF_TIMER,
"clockevent/tim12", clockevent); "clockevent/tim12", clockevent);
if (rv) { if (rv) {
pr_err("Unable to request the clockevent interrupt"); pr_err("Unable to request the clockevent interrupt\n");
return rv; return rv;
} }
...@@ -325,7 +323,7 @@ int __init davinci_timer_register(struct clk *clk, ...@@ -325,7 +323,7 @@ int __init davinci_timer_register(struct clk *clk,
rv = clocksource_register_hz(&davinci_clocksource.dev, tick_rate); rv = clocksource_register_hz(&davinci_clocksource.dev, tick_rate);
if (rv) { if (rv) {
pr_err("Unable to register clocksource"); pr_err("Unable to register clocksource\n");
return rv; return rv;
} }
...@@ -343,20 +341,20 @@ static int __init of_davinci_timer_register(struct device_node *np) ...@@ -343,20 +341,20 @@ static int __init of_davinci_timer_register(struct device_node *np)
rv = of_address_to_resource(np, 0, &timer_cfg.reg); rv = of_address_to_resource(np, 0, &timer_cfg.reg);
if (rv) { if (rv) {
pr_err("Unable to get the register range for timer"); pr_err("Unable to get the register range for timer\n");
return rv; return rv;
} }
rv = of_irq_to_resource_table(np, timer_cfg.irq, rv = of_irq_to_resource_table(np, timer_cfg.irq,
DAVINCI_TIMER_NUM_IRQS); DAVINCI_TIMER_NUM_IRQS);
if (rv != DAVINCI_TIMER_NUM_IRQS) { if (rv != DAVINCI_TIMER_NUM_IRQS) {
pr_err("Unable to get the interrupts for timer"); pr_err("Unable to get the interrupts for timer\n");
return rv; return rv;
} }
clk = of_clk_get(np, 0); clk = of_clk_get(np, 0);
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
pr_err("Unable to get the timer clock"); pr_err("Unable to get the timer clock\n");
return PTR_ERR(clk); return PTR_ERR(clk);
} }
......
...@@ -61,17 +61,19 @@ static inline void tpm_irq_acknowledge(void) ...@@ -61,17 +61,19 @@ static inline void tpm_irq_acknowledge(void)
writel(TPM_STATUS_CH0F, timer_base + TPM_STATUS); writel(TPM_STATUS_CH0F, timer_base + TPM_STATUS);
} }
static struct delay_timer tpm_delay_timer;
static inline unsigned long tpm_read_counter(void) static inline unsigned long tpm_read_counter(void)
{ {
return readl(timer_base + TPM_CNT); return readl(timer_base + TPM_CNT);
} }
#if defined(CONFIG_ARM)
static struct delay_timer tpm_delay_timer;
static unsigned long tpm_read_current_timer(void) static unsigned long tpm_read_current_timer(void)
{ {
return tpm_read_counter(); return tpm_read_counter();
} }
#endif
static u64 notrace tpm_read_sched_clock(void) static u64 notrace tpm_read_sched_clock(void)
{ {
...@@ -144,9 +146,11 @@ static struct timer_of to_tpm = { ...@@ -144,9 +146,11 @@ static struct timer_of to_tpm = {
static int __init tpm_clocksource_init(void) static int __init tpm_clocksource_init(void)
{ {
#if defined(CONFIG_ARM)
tpm_delay_timer.read_current_timer = &tpm_read_current_timer; tpm_delay_timer.read_current_timer = &tpm_read_current_timer;
tpm_delay_timer.freq = timer_of_rate(&to_tpm) >> 3; tpm_delay_timer.freq = timer_of_rate(&to_tpm) >> 3;
register_current_timer_delay(&tpm_delay_timer); register_current_timer_delay(&tpm_delay_timer);
#endif
sched_clock_register(tpm_read_sched_clock, counter_width, sched_clock_register(tpm_read_sched_clock, counter_width,
timer_of_rate(&to_tpm) >> 3); timer_of_rate(&to_tpm) >> 3);
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com
*/ */
#include <linux/clk.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/sched_clock.h> #include <linux/sched_clock.h>
...@@ -76,6 +77,49 @@ static u64 notrace omap_32k_read_sched_clock(void) ...@@ -76,6 +77,49 @@ static u64 notrace omap_32k_read_sched_clock(void)
return ti_32k_read_cycles(&ti_32k_timer.cs); return ti_32k_read_cycles(&ti_32k_timer.cs);
} }
static void __init ti_32k_timer_enable_clock(struct device_node *np,
const char *name)
{
struct clk *clock;
int error;
clock = of_clk_get_by_name(np->parent, name);
if (IS_ERR(clock)) {
/* Only some SoCs have a separate interface clock */
if (PTR_ERR(clock) == -EINVAL && !strncmp("ick", name, 3))
return;
pr_warn("%s: could not get clock %s %li\n",
__func__, name, PTR_ERR(clock));
return;
}
error = clk_prepare_enable(clock);
if (error) {
pr_warn("%s: could not enable %s: %i\n",
__func__, name, error);
return;
}
}
static void __init ti_32k_timer_module_init(struct device_node *np,
void __iomem *base)
{
void __iomem *sysc = base + 4;
if (!of_device_is_compatible(np->parent, "ti,sysc"))
return;
ti_32k_timer_enable_clock(np, "fck");
ti_32k_timer_enable_clock(np, "ick");
/*
* Force idle module as wkup domain is active with MPU.
* No need to tag the module disabled for ti-sysc probe.
*/
writel_relaxed(0, sysc);
}
static int __init ti_32k_timer_init(struct device_node *np) static int __init ti_32k_timer_init(struct device_node *np)
{ {
int ret; int ret;
...@@ -90,6 +134,7 @@ static int __init ti_32k_timer_init(struct device_node *np) ...@@ -90,6 +134,7 @@ static int __init ti_32k_timer_init(struct device_node *np)
ti_32k_timer.cs.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP; ti_32k_timer.cs.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
ti_32k_timer.counter = ti_32k_timer.base; ti_32k_timer.counter = ti_32k_timer.base;
ti_32k_timer_module_init(np, ti_32k_timer.base);
/* /*
* 32k sync Counter IP register offsets vary between the highlander * 32k sync Counter IP register offsets vary between the highlander
...@@ -104,6 +149,8 @@ static int __init ti_32k_timer_init(struct device_node *np) ...@@ -104,6 +149,8 @@ static int __init ti_32k_timer_init(struct device_node *np)
else else
ti_32k_timer.counter += OMAP2_32KSYNCNT_CR_OFF_LOW; ti_32k_timer.counter += OMAP2_32KSYNCNT_CR_OFF_LOW;
pr_info("OMAP clocksource: 32k_counter at 32768 Hz\n");
ret = clocksource_register_hz(&ti_32k_timer.cs, 32768); ret = clocksource_register_hz(&ti_32k_timer.cs, 32768);
if (ret) { if (ret) {
pr_err("32k_counter: can't register clocksource\n"); pr_err("32k_counter: can't register clocksource\n");
...@@ -111,7 +158,6 @@ static int __init ti_32k_timer_init(struct device_node *np) ...@@ -111,7 +158,6 @@ static int __init ti_32k_timer_init(struct device_node *np)
} }
sched_clock_register(omap_32k_read_sched_clock, 32, 32768); sched_clock_register(omap_32k_read_sched_clock, 32, 32768);
pr_info("OMAP clocksource: 32k_counter at 32768 Hz\n");
return 0; return 0;
} }
......
This diff is collapsed.
...@@ -258,9 +258,7 @@ static int omap_dm_timer_prepare(struct omap_dm_timer *timer) ...@@ -258,9 +258,7 @@ static int omap_dm_timer_prepare(struct omap_dm_timer *timer)
__omap_dm_timer_enable_posted(timer); __omap_dm_timer_enable_posted(timer);
omap_dm_timer_disable(timer); omap_dm_timer_disable(timer);
rc = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ); return 0;
return rc;
} }
static inline u32 omap_dm_timer_reserved_systimer(int id) static inline u32 omap_dm_timer_reserved_systimer(int id)
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <linux/clocksource.h> #include <linux/clocksource.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/sched_clock.h> #include <linux/sched_clock.h>
...@@ -22,6 +23,8 @@ static int __init versatile_sched_clock_init(struct device_node *node) ...@@ -22,6 +23,8 @@ static int __init versatile_sched_clock_init(struct device_node *node)
{ {
void __iomem *base = of_iomap(node, 0); void __iomem *base = of_iomap(node, 0);
of_node_clear_flag(node, OF_POPULATED);
if (!base) if (!base)
return -ENXIO; return -ENXIO;
......
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