diff options
Diffstat (limited to 'drivers/clocksource/timer-ti-dm-systimer.c')
| -rw-r--r-- | drivers/clocksource/timer-ti-dm-systimer.c | 46 | 
1 files changed, 36 insertions, 10 deletions
| diff --git a/drivers/clocksource/timer-ti-dm-systimer.c b/drivers/clocksource/timer-ti-dm-systimer.c index 6fd1f219a512..f6fd1c1cc527 100644 --- a/drivers/clocksource/timer-ti-dm-systimer.c +++ b/drivers/clocksource/timer-ti-dm-systimer.c @@ -19,7 +19,7 @@  /* For type1, set SYSC_OMAP2_CLOCKACTIVITY for fck off on idle, l4 clock on */  #define DMTIMER_TYPE1_ENABLE	((1 << 9) | (SYSC_IDLE_SMART << 3) | \  				 SYSC_OMAP2_ENAWAKEUP | SYSC_OMAP2_AUTOIDLE) - +#define DMTIMER_TYPE1_DISABLE	(SYSC_OMAP2_SOFTRESET | SYSC_OMAP2_AUTOIDLE)  #define DMTIMER_TYPE2_ENABLE	(SYSC_IDLE_SMART_WKUP << 2)  #define DMTIMER_RESET_WAIT	100000 @@ -44,6 +44,8 @@ struct dmtimer_systimer {  	u8 ctrl;  	u8 wakeup;  	u8 ifctrl; +	struct clk *fck; +	struct clk *ick;  	unsigned long rate;  }; @@ -298,16 +300,20 @@ static void __init dmtimer_systimer_select_best(void)  }  /* Interface clocks are only available on some SoCs variants */ -static int __init dmtimer_systimer_init_clock(struct device_node *np, +static int __init dmtimer_systimer_init_clock(struct dmtimer_systimer *t, +					      struct device_node *np,  					      const char *name,  					      unsigned long *rate)  {  	struct clk *clock;  	unsigned long r; +	bool is_ick = false;  	int error; +	is_ick = !strncmp(name, "ick", 3); +  	clock = of_clk_get_by_name(np, name); -	if ((PTR_ERR(clock) == -EINVAL) && !strncmp(name, "ick", 3)) +	if ((PTR_ERR(clock) == -EINVAL) && is_ick)  		return 0;  	else if (IS_ERR(clock))  		return PTR_ERR(clock); @@ -320,6 +326,11 @@ static int __init dmtimer_systimer_init_clock(struct device_node *np,  	if (!r)  		return -ENODEV; +	if (is_ick) +		t->ick = clock; +	else +		t->fck = clock; +  	*rate = r;  	return 0; @@ -339,7 +350,10 @@ static void dmtimer_systimer_enable(struct dmtimer_systimer *t)  static void dmtimer_systimer_disable(struct dmtimer_systimer *t)  { -	writel_relaxed(0, t->base + t->sysc); +	if (!dmtimer_systimer_revision1(t)) +		return; + +	writel_relaxed(DMTIMER_TYPE1_DISABLE, t->base + t->sysc);  }  static int __init dmtimer_systimer_setup(struct device_node *np, @@ -366,13 +380,13 @@ static int __init dmtimer_systimer_setup(struct device_node *np,  		pr_err("%s: clock source init failed: %i\n", __func__, error);  	/* For ti-sysc, we have timer clocks at the parent module level */ -	error = dmtimer_systimer_init_clock(np->parent, "fck", &rate); +	error = dmtimer_systimer_init_clock(t, np->parent, "fck", &rate);  	if (error)  		goto err_unmap;  	t->rate = rate; -	error = dmtimer_systimer_init_clock(np->parent, "ick", &rate); +	error = dmtimer_systimer_init_clock(t, np->parent, "ick", &rate);  	if (error)  		goto err_unmap; @@ -496,12 +510,18 @@ static void omap_clockevent_idle(struct clock_event_device *evt)  	struct dmtimer_systimer *t = &clkevt->t;  	dmtimer_systimer_disable(t); +	clk_disable(t->fck);  }  static void omap_clockevent_unidle(struct clock_event_device *evt)  {  	struct dmtimer_clockevent *clkevt = to_dmtimer_clockevent(evt);  	struct dmtimer_systimer *t = &clkevt->t; +	int error; + +	error = clk_enable(t->fck); +	if (error) +		pr_err("could not enable timer fck on resume: %i\n", error);  	dmtimer_systimer_enable(t);  	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->irq_ena); @@ -570,8 +590,8 @@ static int __init dmtimer_clockevent_init(struct device_node *np)  					3, /* Timer internal resynch latency */  					0xffffffff); -	if (of_device_is_compatible(np, "ti,am33xx") || -	    of_device_is_compatible(np, "ti,am43")) { +	if (of_machine_is_compatible("ti,am33xx") || +	    of_machine_is_compatible("ti,am43")) {  		dev->suspend = omap_clockevent_idle;  		dev->resume = omap_clockevent_unidle;  	} @@ -616,12 +636,18 @@ static void dmtimer_clocksource_suspend(struct clocksource *cs)  	clksrc->loadval = readl_relaxed(t->base + t->counter);  	dmtimer_systimer_disable(t); +	clk_disable(t->fck);  }  static void dmtimer_clocksource_resume(struct clocksource *cs)  {  	struct dmtimer_clocksource *clksrc = to_dmtimer_clocksource(cs);  	struct dmtimer_systimer *t = &clksrc->t; +	int error; + +	error = clk_enable(t->fck); +	if (error) +		pr_err("could not enable timer fck on resume: %i\n", error);  	dmtimer_systimer_enable(t);  	writel_relaxed(clksrc->loadval, t->base + t->counter); @@ -653,8 +679,8 @@ static int __init dmtimer_clocksource_init(struct device_node *np)  	dev->mask = CLOCKSOURCE_MASK(32);  	dev->flags = CLOCK_SOURCE_IS_CONTINUOUS; -	if (of_device_is_compatible(np, "ti,am33xx") || -	    of_device_is_compatible(np, "ti,am43")) { +	/* Unlike for clockevent, legacy code sets suspend only for am4 */ +	if (of_machine_is_compatible("ti,am43")) {  		dev->suspend = dmtimer_clocksource_suspend;  		dev->resume = dmtimer_clocksource_resume;  	} |