Skip to contentSkip to conversation

ARM: timer-sp: support timer clock freq other than 1MHz

PATCH New Rob Herring 2 participants 2 messages Oct 1, 2010 Arm (32-bit)

lore
Share & tools
lore
#0 lore raw

PATCH 2/3 ARM: timer-sp: support timer clock freq other than 1MHz

The timer-sp code is fixed to 1MHz timer clock. Add clock api calls to get the timer clock frequency.

---
  arch/arm/common/timer-sp.c |   30 +++++++++++++++++++++++++-----
  1 files changed, 25 insertions(+), 5 deletions(-)
arch/arm/common/timer-sp.c +0 -0
index b552358..44e83a2 100644
@@ -18,6 +18,8 @@
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 

02111-1307 USA
*/
+#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/clocksource.h>
#include <linux/clockchips.h>
#include <linux/interrupt.h>
@@ -29,9 +31,9 @@
/*
* These timers are currently always setup to be clocked at 1MHz. */
-#define TIMER_FREQ_KHZ (1000)
-#define TIMER_RELOAD (TIMER_FREQ_KHZ * 1000 / HZ)
+#define TIMER_FREQ_HZ (1000000)
+static unsigned long sp804_rate;
static void __iomem *clksrc_base;
static cycle_t sp804_read(struct clocksource *cs)
@@ -50,10 +52,19 @@ static struct clocksource clocksource_sp804 = {
void __init sp804_clocksource_init(void __iomem *base)
{
+ struct clk *clk;
struct clocksource *cs = &clocksource_sp804; clksrc_base = base;
+ if (sp804_rate == 0) {
+ clk = clk_get_sys(NULL, "sp804_timer");
+ if (!IS_ERR(clk))
+ sp804_rate = clk_get_rate(clk);
+ else
+ sp804_rate = TIMER_FREQ_HZ;
+ }
+
/* setup timer 0 as free-running clocksource */ writel(0, clksrc_base + TIMER_CTRL);
writel(0xffffffff, clksrc_base + TIMER_LOAD);
@@ -61,7 +72,7 @@ void __init sp804_clocksource_init(void __iomem *base)
writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
clksrc_base + TIMER_CTRL);
- cs->mult = clocksource_khz2mult(TIMER_FREQ_KHZ, cs->shift);
+ cs->mult = clocksource_khz2mult(sp804_rate / 1000, cs->shift);
clocksource_register(cs);
}
@@ -92,7 +103,7 @@ static void sp804_set_mode(enum clock_event_mode mode,
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
- writel(TIMER_RELOAD, clkevt_base + TIMER_LOAD);
+ writel(sp804_rate / HZ, clkevt_base + TIMER_LOAD);
ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; break;
@@ -140,12 +151,21 @@ static struct irqaction sp804_timer_irq = {
void __init sp804_clockevents_init(void __iomem *base, unsigned int
timer_irq)
{
+ struct clk *clk;
struct clock_event_device *evt = &sp804_clockevent; clkevt_base = base;
+ if (sp804_rate == 0) {
+ clk = clk_get_sys(NULL, "sp804_timer");
+ if (!IS_ERR(clk))
+ sp804_rate = clk_get_rate(clk);
+ else
+ sp804_rate = TIMER_FREQ_HZ;
+ }
+
evt->irq = timer_irq;
- evt->mult = div_sc(TIMER_FREQ_KHZ, NSEC_PER_MSEC, evt->shift);
+ evt->mult = div_sc(sp804_rate / 1000, NSEC_PER_MSEC, evt->shift);
evt->max_delta_ns = clockevent_delta2ns(0xffffffff, evt); evt->min_delta_ns = clockevent_delta2ns(0xf, evt);
-- 1.7.0.4

#1 lore raw

PATCH 2/3 ARM: timer-sp: support timer clock freq other than 1MHz

Quoted 2 lines · Rob Herring

The timer-sp code is fixed to 1MHz timer clock. Add clock api calls to get the timer clock frequency.

This patch isn't threaded with the others (and as a result is separated by at least 50 messages in my mailbox!) Also the patch seems to be broken by "inteligent" formatting.

Review static struct clocksource clocksource_sp804 = { · line 58

Quoted 8 lines
(quoted diff) +2 -0
@@ -50,10 +52,19 @@ static struct clocksource clocksource_sp804 = {
  void __init sp804_clocksource_init(void __iomem *base)
 {
+	struct clk *clk;
 	struct clocksource *cs = &clocksource_sp804;
  	clksrc_base = base;
 +	if (sp804_rate == 0) {
+		clk = clk_get_sys(NULL, "sp804_timer");

Why just a connection ID with a NULL device name? This is wrong. It should at least be:

		clk = clk_get_sys("sp804", NULL);

Now, one issue here is that the ARM platforms have several of these - normally 4, or maybe 8. Some ARM platforms have them clocked differently (they're even on two different boards.) So we do need some kind of connection ID there to identify which one.

I'd suggest passing in a const string to this function to set both the clocksource name (to identify which sp804 is being used) and used as a connection ID with clk_get_sys().

Review static struct clocksource clocksource_sp804 = {

Quoted 9 lines
(quoted diff) +2 -0
 @@ -140,12 +151,21 @@ static struct irqaction sp804_timer_irq = {
  void __init sp804_clockevents_init(void __iomem *base, unsigned int  
 timer_irq)
 {
+	struct clk *clk;
 	struct clock_event_device *evt = &sp804_clockevent;
  	clkevt_base = base;
 +	if (sp804_rate == 0) {
+		clk = clk_get_sys(NULL, "sp804_timer");

Same comments here.