diff options
Diffstat (limited to 'drivers/clocksource')
24 files changed, 375 insertions, 41 deletions
| diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index a7726db13abb..71cfdf7c9708 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -2,6 +2,14 @@ menu "Clock Source drivers"  config CLKSRC_OF  	bool +	select CLKSRC_PROBE + +config CLKSRC_ACPI +	bool +	select CLKSRC_PROBE + +config CLKSRC_PROBE +	bool  config CLKSRC_I8253  	bool @@ -115,6 +123,14 @@ config CLKSRC_PISTACHIO  	bool  	select CLKSRC_OF +config CLKSRC_TI_32K +	bool "Texas Instruments 32.768 Hz Clocksource" if COMPILE_TEST +	depends on GENERIC_SCHED_CLOCK +	select CLKSRC_OF if OF +	help +	  This option enables support for Texas Instruments 32.768 Hz clocksource +	  available on many OMAP-like platforms. +  config CLKSRC_STM32  	bool "Clocksource for STM32 SoCs" if !ARCH_STM32  	depends on OF && ARM && (ARCH_STM32 || COMPILE_TEST) @@ -123,6 +139,7 @@ config CLKSRC_STM32  config ARM_ARCH_TIMER  	bool  	select CLKSRC_OF if OF +	select CLKSRC_ACPI if ACPI  config ARM_ARCH_TIMER_EVTSTREAM  	bool "Support for ARM architected timer event stream generation" @@ -279,6 +296,10 @@ config CLKSRC_MIPS_GIC  	depends on MIPS_GIC  	select CLKSRC_OF +config CLKSRC_TANGO_XTAL +	bool +	select CLKSRC_OF +  config CLKSRC_PXA  	def_bool y if ARCH_PXA || ARCH_SA1100  	select CLKSRC_OF if OF diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 5c00863c3e33..56bd16e77ae3 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -1,4 +1,4 @@ -obj-$(CONFIG_CLKSRC_OF)	+= clksrc-of.o +obj-$(CONFIG_CLKSRC_PROBE)	+= clksrc-probe.o  obj-$(CONFIG_ATMEL_PIT)		+= timer-atmel-pit.o  obj-$(CONFIG_ATMEL_ST)		+= timer-atmel-st.o  obj-$(CONFIG_ATMEL_TCB_CLKSRC)	+= tcb_clksrc.o @@ -45,6 +45,7 @@ obj-$(CONFIG_VF_PIT_TIMER)	+= vf_pit_timer.o  obj-$(CONFIG_CLKSRC_QCOM)	+= qcom-timer.o  obj-$(CONFIG_MTK_TIMER)		+= mtk_timer.o  obj-$(CONFIG_CLKSRC_PISTACHIO)	+= time-pistachio.o +obj-$(CONFIG_CLKSRC_TI_32K)	+= timer-ti-32k.o  obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o  obj-$(CONFIG_ARM_GLOBAL_TIMER)		+= arm_global_timer.o @@ -56,9 +57,11 @@ obj-$(CONFIG_ARCH_KEYSTONE)		+= timer-keystone.o  obj-$(CONFIG_ARCH_INTEGRATOR_AP)	+= timer-integrator-ap.o  obj-$(CONFIG_CLKSRC_VERSATILE)		+= versatile.o  obj-$(CONFIG_CLKSRC_MIPS_GIC)		+= mips-gic-timer.o +obj-$(CONFIG_CLKSRC_TANGO_XTAL)		+= tango_xtal.o  obj-$(CONFIG_CLKSRC_IMX_GPT)		+= timer-imx-gpt.o  obj-$(CONFIG_ASM9260_TIMER)		+= asm9260_timer.o  obj-$(CONFIG_H8300)			+= h8300_timer8.o  obj-$(CONFIG_H8300_TMR16)		+= h8300_timer16.o  obj-$(CONFIG_H8300_TPU)			+= h8300_tpu.o  obj-$(CONFIG_CLKSRC_ST_LPC)		+= clksrc_st_lpc.o +obj-$(CONFIG_X86_NUMACHIP)		+= numachip.o diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index d6e3e49399dd..c64d543d64bf 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -864,13 +864,5 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table)  	arch_timer_init();  	return 0;  } - -/* Initialize all the generic timers presented in GTDT */ -void __init acpi_generic_timer_init(void) -{ -	if (acpi_disabled) -		return; - -	acpi_table_parse(ACPI_SIG_GTDT, arch_timer_acpi_init); -} +CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);  #endif diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c index 29ea50ac366a..a2cb6fae9295 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c @@ -60,7 +60,7 @@ static struct clock_event_device __percpu *gt_evt;   *  different to the 32-bit upper value read previously, go back to step 2.   *  Otherwise the 64-bit timer counter value is correct.   */ -static u64 gt_counter_read(void) +static u64 notrace _gt_counter_read(void)  {  	u64 counter;  	u32 lower; @@ -79,6 +79,11 @@ static u64 gt_counter_read(void)  	return counter;  } +static u64 gt_counter_read(void) +{ +	return _gt_counter_read(); +} +  /**   * To ensure that updates to comparator value register do not set the   * Interrupt Status Register proceed as follows: @@ -201,7 +206,7 @@ static struct clocksource gt_clocksource = {  #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK  static u64 notrace gt_sched_clock_read(void)  { -	return gt_counter_read(); +	return _gt_counter_read();  }  #endif diff --git a/drivers/clocksource/clksrc-of.c b/drivers/clocksource/clksrc-probe.c index 0093a8e49e14..7cb6c923a836 100644 --- a/drivers/clocksource/clksrc-of.c +++ b/drivers/clocksource/clksrc-probe.c @@ -14,6 +14,7 @@   * along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ +#include <linux/acpi.h>  #include <linux/init.h>  #include <linux/of.h>  #include <linux/clocksource.h> @@ -23,7 +24,7 @@ extern struct of_device_id __clksrc_of_table[];  static const struct of_device_id __clksrc_of_table_sentinel  	__used __section(__clksrc_of_table_end); -void __init clocksource_of_init(void) +void __init clocksource_probe(void)  {  	struct device_node *np;  	const struct of_device_id *match; @@ -38,6 +39,9 @@ void __init clocksource_of_init(void)  		init_func(np);  		clocksources++;  	} + +	clocksources += acpi_probe_device_table(clksrc); +  	if (!clocksources)  		pr_crit("%s: no matching clocksources found\n", __func__);  } diff --git a/drivers/clocksource/em_sti.c b/drivers/clocksource/em_sti.c index 7a97a34dba70..19bb1792d647 100644 --- a/drivers/clocksource/em_sti.c +++ b/drivers/clocksource/em_sti.c @@ -228,7 +228,6 @@ static int em_sti_register_clocksource(struct em_sti_priv *p)  {  	struct clocksource *cs = &p->cs; -	memset(cs, 0, sizeof(*cs));  	cs->name = dev_name(&p->pdev->dev);  	cs->rating = 200;  	cs->read = em_sti_clocksource_read; @@ -285,7 +284,6 @@ static void em_sti_register_clockevent(struct em_sti_priv *p)  {  	struct clock_event_device *ced = &p->ced; -	memset(ced, 0, sizeof(*ced));  	ced->name = dev_name(&p->pdev->dev);  	ced->features = CLOCK_EVT_FEAT_ONESHOT;  	ced->rating = 200; diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index 029f96ab131a..ff44082a0827 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c @@ -382,24 +382,28 @@ static void exynos4_mct_tick_start(unsigned long cycles,  static int exynos4_tick_set_next_event(unsigned long cycles,  				       struct clock_event_device *evt)  { -	struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick); +	struct mct_clock_event_device *mevt; +	mevt = container_of(evt, struct mct_clock_event_device, evt);  	exynos4_mct_tick_start(cycles, mevt); -  	return 0;  }  static int set_state_shutdown(struct clock_event_device *evt)  { -	exynos4_mct_tick_stop(this_cpu_ptr(&percpu_mct_tick)); +	struct mct_clock_event_device *mevt; + +	mevt = container_of(evt, struct mct_clock_event_device, evt); +	exynos4_mct_tick_stop(mevt);  	return 0;  }  static int set_state_periodic(struct clock_event_device *evt)  { -	struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick); +	struct mct_clock_event_device *mevt;  	unsigned long cycles_per_jiffy; +	mevt = container_of(evt, struct mct_clock_event_device, evt);  	cycles_per_jiffy = (((unsigned long long)NSEC_PER_SEC / HZ * evt->mult)  			    >> evt->shift);  	exynos4_mct_tick_stop(mevt); diff --git a/drivers/clocksource/fsl_ftm_timer.c b/drivers/clocksource/fsl_ftm_timer.c index ef434699c80a..10202f1fdfd7 100644 --- a/drivers/clocksource/fsl_ftm_timer.c +++ b/drivers/clocksource/fsl_ftm_timer.c @@ -118,7 +118,7 @@ static inline void ftm_reset_counter(void __iomem *base)  	ftm_writel(0x00, base + FTM_CNT);  } -static u64 ftm_read_sched_clock(void) +static u64 notrace ftm_read_sched_clock(void)  {  	return ftm_readl(priv->clksrc_base + FTM_CNT);  } diff --git a/drivers/clocksource/h8300_timer16.c b/drivers/clocksource/h8300_timer16.c index 82941c1e9e33..0e076c6fc006 100644 --- a/drivers/clocksource/h8300_timer16.c +++ b/drivers/clocksource/h8300_timer16.c @@ -153,7 +153,6 @@ static int timer16_setup(struct timer16_priv *p, struct platform_device *pdev)  	int ret, irq;  	unsigned int ch; -	memset(p, 0, sizeof(*p));  	p->pdev = pdev;  	res[REG_CH] = platform_get_resource(p->pdev, diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c index f9b3b7033a97..44375d8b9bc4 100644 --- a/drivers/clocksource/h8300_timer8.c +++ b/drivers/clocksource/h8300_timer8.c @@ -215,7 +215,6 @@ static int timer8_setup(struct timer8_priv *p,  	int irq;  	int ret; -	memset(p, 0, sizeof(*p));  	p->pdev = pdev;  	res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0); diff --git a/drivers/clocksource/h8300_tpu.c b/drivers/clocksource/h8300_tpu.c index 64195fdd78bf..5487410bfabb 100644 --- a/drivers/clocksource/h8300_tpu.c +++ b/drivers/clocksource/h8300_tpu.c @@ -123,7 +123,6 @@ static int __init tpu_setup(struct tpu_priv *p, struct platform_device *pdev)  {  	struct resource *res[2]; -	memset(p, 0, sizeof(*p));  	p->pdev = pdev;  	res[CH_L] = platform_get_resource(p->pdev, IORESOURCE_MEM, CH_L); diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c index 50f0641c65b6..fbfc74685e6a 100644 --- a/drivers/clocksource/mtk_timer.c +++ b/drivers/clocksource/mtk_timer.c @@ -24,6 +24,7 @@  #include <linux/of.h>  #include <linux/of_address.h>  #include <linux/of_irq.h> +#include <linux/sched_clock.h>  #include <linux/slab.h>  #define GPT_IRQ_EN_REG		0x00 @@ -59,6 +60,13 @@ struct mtk_clock_event_device {  	struct clock_event_device dev;  }; +static void __iomem *gpt_sched_reg __read_mostly; + +static u64 notrace mtk_read_sched_clock(void) +{ +	return readl_relaxed(gpt_sched_reg); +} +  static inline struct mtk_clock_event_device *to_mtk_clk(  				struct clock_event_device *c)  { @@ -141,14 +149,6 @@ static irqreturn_t mtk_timer_interrupt(int irq, void *dev_id)  	return IRQ_HANDLED;  } -static void mtk_timer_global_reset(struct mtk_clock_event_device *evt) -{ -	/* Disable all interrupts */ -	writel(0x0, evt->gpt_base + GPT_IRQ_EN_REG); -	/* Acknowledge all interrupts */ -	writel(0x3f, evt->gpt_base + GPT_IRQ_ACK_REG); -} -  static void  mtk_timer_setup(struct mtk_clock_event_device *evt, u8 timer, u8 option)  { @@ -168,6 +168,12 @@ static void mtk_timer_enable_irq(struct mtk_clock_event_device *evt, u8 timer)  {  	u32 val; +	/* Disable all interrupts */ +	writel(0x0, evt->gpt_base + GPT_IRQ_EN_REG); + +	/* Acknowledge all spurious pending interrupts */ +	writel(0x3f, evt->gpt_base + GPT_IRQ_ACK_REG); +  	val = readl(evt->gpt_base + GPT_IRQ_EN_REG);  	writel(val | GPT_IRQ_ENABLE(timer),  			evt->gpt_base + GPT_IRQ_EN_REG); @@ -220,8 +226,6 @@ static void __init mtk_timer_init(struct device_node *node)  	}  	rate = clk_get_rate(clk); -	mtk_timer_global_reset(evt); -  	if (request_irq(evt->dev.irq, mtk_timer_interrupt,  			IRQF_TIMER | IRQF_IRQPOLL, "mtk_timer", evt)) {  		pr_warn("failed to setup irq %d\n", evt->dev.irq); @@ -234,6 +238,8 @@ static void __init mtk_timer_init(struct device_node *node)  	mtk_timer_setup(evt, GPT_CLK_SRC, TIMER_CTRL_OP_FREERUN);  	clocksource_mmio_init(evt->gpt_base + TIMER_CNT_REG(GPT_CLK_SRC),  			node->name, rate, 300, 32, clocksource_mmio_readl_up); +	gpt_sched_reg = evt->gpt_base + TIMER_CNT_REG(GPT_CLK_SRC); +	sched_clock_register(mtk_read_sched_clock, 32, rate);  	/* Configure clock event */  	mtk_timer_setup(evt, GPT_CLK_EVT, TIMER_CTRL_OP_REPEAT); diff --git a/drivers/clocksource/numachip.c b/drivers/clocksource/numachip.c new file mode 100644 index 000000000000..4e0f11fd2617 --- /dev/null +++ b/drivers/clocksource/numachip.c @@ -0,0 +1,95 @@ +/* + * + * Copyright (C) 2015 Numascale AS. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + */ + +#include <linux/clockchips.h> + +#include <asm/irq.h> +#include <asm/numachip/numachip.h> +#include <asm/numachip/numachip_csr.h> + +static DEFINE_PER_CPU(struct clock_event_device, numachip2_ced); + +static cycles_t numachip2_timer_read(struct clocksource *cs) +{ +	return numachip2_read64_lcsr(NUMACHIP2_TIMER_NOW); +} + +static struct clocksource numachip2_clocksource = { +	.name            = "numachip2", +	.rating          = 295, +	.read            = numachip2_timer_read, +	.mask            = CLOCKSOURCE_MASK(64), +	.flags           = CLOCK_SOURCE_IS_CONTINUOUS, +	.mult            = 1, +	.shift           = 0, +}; + +static int numachip2_set_next_event(unsigned long delta, struct clock_event_device *ced) +{ +	numachip2_write64_lcsr(NUMACHIP2_TIMER_DEADLINE + numachip2_timer(), +		delta); +	return 0; +} + +static struct clock_event_device numachip2_clockevent = { +	.name            = "numachip2", +	.rating          = 400, +	.set_next_event  = numachip2_set_next_event, +	.features        = CLOCK_EVT_FEAT_ONESHOT, +	.mult            = 1, +	.shift           = 0, +	.min_delta_ns    = 1250, +	.max_delta_ns    = LONG_MAX, +}; + +static void numachip_timer_interrupt(void) +{ +	struct clock_event_device *ced = this_cpu_ptr(&numachip2_ced); + +	ced->event_handler(ced); +} + +static __init void numachip_timer_each(struct work_struct *work) +{ +	unsigned local_apicid = __this_cpu_read(x86_cpu_to_apicid) & 0xff; +	struct clock_event_device *ced = this_cpu_ptr(&numachip2_ced); + +	/* Setup IPI vector to local core and relative timing mode */ +	numachip2_write64_lcsr(NUMACHIP2_TIMER_INT + numachip2_timer(), +		(3 << 22) | (X86_PLATFORM_IPI_VECTOR << 14) | +		(local_apicid << 6)); + +	*ced = numachip2_clockevent; +	ced->cpumask = cpumask_of(smp_processor_id()); +	clockevents_register_device(ced); +} + +static int __init numachip_timer_init(void) +{ +	if (numachip_system != 2) +		return -ENODEV; + +	/* Reset timer */ +	numachip2_write64_lcsr(NUMACHIP2_TIMER_RESET, 0); +	clocksource_register_hz(&numachip2_clocksource, NSEC_PER_SEC); + +	/* Setup per-cpu clockevents */ +	x86_platform_ipi_callback = numachip_timer_interrupt; +	schedule_on_each_cpu(&numachip_timer_each); + +	return 0; +} + +arch_initcall(numachip_timer_init); diff --git a/drivers/clocksource/samsung_pwm_timer.c b/drivers/clocksource/samsung_pwm_timer.c index bc90e13338cc..9502bc4c3f6d 100644 --- a/drivers/clocksource/samsung_pwm_timer.c +++ b/drivers/clocksource/samsung_pwm_timer.c @@ -307,7 +307,7 @@ static void samsung_clocksource_resume(struct clocksource *cs)  	samsung_time_start(pwm.source_id, true);  } -static cycle_t samsung_clocksource_read(struct clocksource *c) +static cycle_t notrace samsung_clocksource_read(struct clocksource *c)  {  	return ~readl_relaxed(pwm.source_reg);  } diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index ba73a6eb8d66..103c49362c68 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -962,7 +962,6 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)  	unsigned int i;  	int ret; -	memset(cmt, 0, sizeof(*cmt));  	cmt->pdev = pdev;  	raw_spin_lock_init(&cmt->lock); diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index f1985da8113f..53aa7e92a7d7 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c @@ -280,7 +280,9 @@ static int sh_mtu2_clock_event_shutdown(struct clock_event_device *ced)  {  	struct sh_mtu2_channel *ch = ced_to_sh_mtu2(ced); -	sh_mtu2_disable(ch); +	if (clockevent_state_periodic(ced)) +		sh_mtu2_disable(ch); +  	return 0;  } diff --git a/drivers/clocksource/tango_xtal.c b/drivers/clocksource/tango_xtal.c new file mode 100644 index 000000000000..d297b30d2bc0 --- /dev/null +++ b/drivers/clocksource/tango_xtal.c @@ -0,0 +1,66 @@ +#include <linux/clocksource.h> +#include <linux/sched_clock.h> +#include <linux/of_address.h> +#include <linux/printk.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/clk.h> + +static void __iomem *xtal_in_cnt; +static struct delay_timer delay_timer; + +static unsigned long notrace read_xtal_counter(void) +{ +	return readl_relaxed(xtal_in_cnt); +} + +static u64 notrace read_sched_clock(void) +{ +	return read_xtal_counter(); +} + +static cycle_t read_clocksource(struct clocksource *cs) +{ +	return read_xtal_counter(); +} + +static struct clocksource tango_xtal = { +	.name	= "tango-xtal", +	.rating	= 350, +	.read	= read_clocksource, +	.mask	= CLOCKSOURCE_MASK(32), +	.flags	= CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static void __init tango_clocksource_init(struct device_node *np) +{ +	struct clk *clk; +	int xtal_freq, ret; + +	xtal_in_cnt = of_iomap(np, 0); +	if (xtal_in_cnt == NULL) { +		pr_err("%s: invalid address\n", np->full_name); +		return; +	} + +	clk = of_clk_get(np, 0); +	if (IS_ERR(clk)) { +		pr_err("%s: invalid clock\n", np->full_name); +		return; +	} + +	xtal_freq = clk_get_rate(clk); +	delay_timer.freq = xtal_freq; +	delay_timer.read_current_timer = read_xtal_counter; + +	ret = clocksource_register_hz(&tango_xtal, xtal_freq); +	if (ret != 0) { +		pr_err("%s: registration failed\n", np->full_name); +		return; +	} + +	sched_clock_register(read_sched_clock, 32, xtal_freq); +	register_current_timer_delay(&delay_timer); +} + +CLOCKSOURCE_OF_DECLARE(tango, "sigma,tick-counter", tango_clocksource_init); diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c index 2162796fd504..d93ec3c4f139 100644 --- a/drivers/clocksource/time-armada-370-xp.c +++ b/drivers/clocksource/time-armada-370-xp.c @@ -45,6 +45,8 @@  #include <linux/percpu.h>  #include <linux/syscore_ops.h> +#include <asm/delay.h> +  /*   * Timer block registers.   */ @@ -249,6 +251,15 @@ struct syscore_ops armada_370_xp_timer_syscore_ops = {  	.resume		= armada_370_xp_timer_resume,  }; +static unsigned long armada_370_delay_timer_read(void) +{ +	return ~readl(timer_base + TIMER0_VAL_OFF); +} + +static struct delay_timer armada_370_delay_timer = { +	.read_current_timer = armada_370_delay_timer_read, +}; +  static void __init armada_370_xp_timer_common_init(struct device_node *np)  {  	u32 clr = 0, set = 0; @@ -287,6 +298,9 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np)  		TIMER0_RELOAD_EN | enable_mask,  		TIMER0_RELOAD_EN | enable_mask); +	armada_370_delay_timer.freq = timer_clk; +	register_current_timer_delay(&armada_370_delay_timer); +  	/*  	 * Set scale and timer for sched_clock.  	 */ diff --git a/drivers/clocksource/time-pistachio.c b/drivers/clocksource/time-pistachio.c index 18d4266c2986..bba679900054 100644 --- a/drivers/clocksource/time-pistachio.c +++ b/drivers/clocksource/time-pistachio.c @@ -67,7 +67,8 @@ static inline void gpt_writel(void __iomem *base, u32 value, u32 offset,  	writel(value, base + 0x20 * gpt_id + offset);  } -static cycle_t pistachio_clocksource_read_cycles(struct clocksource *cs) +static cycle_t notrace +pistachio_clocksource_read_cycles(struct clocksource *cs)  {  	struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs);  	u32 counter, overflw; diff --git a/drivers/clocksource/timer-digicolor.c b/drivers/clocksource/timer-digicolor.c index e73947f0f86d..a536eeb634d8 100644 --- a/drivers/clocksource/timer-digicolor.c +++ b/drivers/clocksource/timer-digicolor.c @@ -143,7 +143,7 @@ static irqreturn_t digicolor_timer_interrupt(int irq, void *dev_id)  	return IRQ_HANDLED;  } -static u64 digicolor_timer_sched_read(void) +static u64 notrace digicolor_timer_sched_read(void)  {  	return ~readl(dc_timer_dev.base + COUNT(TIMER_B));  } diff --git a/drivers/clocksource/timer-imx-gpt.c b/drivers/clocksource/timer-imx-gpt.c index 839aba92fc39..99ec96769dda 100644 --- a/drivers/clocksource/timer-imx-gpt.c +++ b/drivers/clocksource/timer-imx-gpt.c @@ -305,13 +305,14 @@ static int __init mxc_clockevent_init(struct imx_timer *imxtm)  	struct irqaction *act = &imxtm->act;  	ced->name = "mxc_timer1"; -	ced->features = CLOCK_EVT_FEAT_ONESHOT; +	ced->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_DYNIRQ;  	ced->set_state_shutdown = mxc_shutdown;  	ced->set_state_oneshot = mxc_set_oneshot;  	ced->tick_resume = mxc_shutdown;  	ced->set_next_event = imxtm->gpt->set_next_event;  	ced->rating = 200;  	ced->cpumask = cpumask_of(0); +	ced->irq = imxtm->irq;  	clockevents_config_and_register(ced, clk_get_rate(imxtm->clk_per),  					0xff, 0xfffffffe); diff --git a/drivers/clocksource/timer-prima2.c b/drivers/clocksource/timer-prima2.c index 78de982cc640..2854c663e8b5 100644 --- a/drivers/clocksource/timer-prima2.c +++ b/drivers/clocksource/timer-prima2.c @@ -73,7 +73,7 @@ static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)  }  /* read 64-bit timer counter */ -static cycle_t sirfsoc_timer_read(struct clocksource *cs) +static cycle_t notrace sirfsoc_timer_read(struct clocksource *cs)  {  	u64 cycles; diff --git a/drivers/clocksource/timer-ti-32k.c b/drivers/clocksource/timer-ti-32k.c new file mode 100644 index 000000000000..8518d9dfba5c --- /dev/null +++ b/drivers/clocksource/timer-ti-32k.c @@ -0,0 +1,126 @@ +/** + * timer-ti-32k.c - OMAP2 32k Timer Support + * + * Copyright (C) 2009 Nokia Corporation + * + * Update to use new clocksource/clockevent layers + * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com> + * Copyright (C) 2007 MontaVista Software, Inc. + * + * Original driver: + * Copyright (C) 2005 Nokia Corporation + * Author: Paul Mundt <paul.mundt@nokia.com> + *         Juha Yrjölä <juha.yrjola@nokia.com> + * OMAP Dual-mode timer framework support by Timo Teras + * + * Some parts based off of TI's 24xx code: + * + * Copyright (C) 2004-2009 Texas Instruments, Inc. + * + * Roughly modelled after the OMAP1 MPU timer code. + * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com> + * + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2  of + * the License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/init.h> +#include <linux/time.h> +#include <linux/sched_clock.h> +#include <linux/clocksource.h> +#include <linux/of.h> +#include <linux/of_address.h> + +/* + * 32KHz clocksource ... always available, on pretty most chips except + * OMAP 730 and 1510.  Other timers could be used as clocksources, with + * higher resolution in free-running counter modes (e.g. 12 MHz xtal), + * but systems won't necessarily want to spend resources that way. + */ + +#define OMAP2_32KSYNCNT_REV_OFF		0x0 +#define OMAP2_32KSYNCNT_REV_SCHEME	(0x3 << 30) +#define OMAP2_32KSYNCNT_CR_OFF_LOW	0x10 +#define OMAP2_32KSYNCNT_CR_OFF_HIGH	0x30 + +struct ti_32k { +	void __iomem		*base; +	void __iomem		*counter; +	struct clocksource	cs; +}; + +static inline struct ti_32k *to_ti_32k(struct clocksource *cs) +{ +	return container_of(cs, struct ti_32k, cs); +} + +static cycle_t ti_32k_read_cycles(struct clocksource *cs) +{ +	struct ti_32k *ti = to_ti_32k(cs); + +	return (cycle_t)readl_relaxed(ti->counter); +} + +static struct ti_32k ti_32k_timer = { +	.cs = { +		.name		= "32k_counter", +		.rating		= 250, +		.read		= ti_32k_read_cycles, +		.mask		= CLOCKSOURCE_MASK(32), +		.flags		= CLOCK_SOURCE_IS_CONTINUOUS | +				CLOCK_SOURCE_SUSPEND_NONSTOP, +	}, +}; + +static u64 notrace omap_32k_read_sched_clock(void) +{ +	return ti_32k_read_cycles(&ti_32k_timer.cs); +} + +static void __init ti_32k_timer_init(struct device_node *np) +{ +	int ret; + +	ti_32k_timer.base = of_iomap(np, 0); +	if (!ti_32k_timer.base) { +		pr_err("Can't ioremap 32k timer base\n"); +		return; +	} + +	ti_32k_timer.counter = ti_32k_timer.base; + +	/* +	 * 32k sync Counter IP register offsets vary between the highlander +	 * version and the legacy ones. +	 * +	 * The 'SCHEME' bits(30-31) of the revision register is used to identify +	 * the version. +	 */ +	if (readl_relaxed(ti_32k_timer.base + OMAP2_32KSYNCNT_REV_OFF) & +			OMAP2_32KSYNCNT_REV_SCHEME) +		ti_32k_timer.counter += OMAP2_32KSYNCNT_CR_OFF_HIGH; +	else +		ti_32k_timer.counter += OMAP2_32KSYNCNT_CR_OFF_LOW; + +	ret = clocksource_register_hz(&ti_32k_timer.cs, 32768); +	if (ret) { +		pr_err("32k_counter: can't register clocksource\n"); +		return; +	} + +	sched_clock_register(omap_32k_read_sched_clock, 32, 32768); +	pr_info("OMAP clocksource: 32k_counter at 32768 Hz\n"); +} +CLOCKSOURCE_OF_DECLARE(ti_32k_timer, "ti,omap-counter32k", +		ti_32k_timer_init); diff --git a/drivers/clocksource/vf_pit_timer.c b/drivers/clocksource/vf_pit_timer.c index f07ba9932171..a0e6c68536a1 100644 --- a/drivers/clocksource/vf_pit_timer.c +++ b/drivers/clocksource/vf_pit_timer.c @@ -52,7 +52,7 @@ static inline void pit_irq_acknowledge(void)  	__raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG);  } -static u64 pit_read_sched_clock(void) +static u64 notrace pit_read_sched_clock(void)  {  	return ~__raw_readl(clksrc_base + PITCVAL);  } | 
