clocksource: ARM sp804: obtain sp804 timer rate via clks
authorRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 12 May 2011 12:31:48 +0000 (13:31 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Mon, 23 May 2011 17:04:53 +0000 (18:04 +0100)
This allows platforms to specify the rate of the SP804 clocksource via
the clk subsystem.  While ARM boards clock these at 1MHz, BCMRing also
has SP804 timers but are clocked at different rates.

Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/common/timer-sp.c
arch/arm/mach-integrator/integrator_cp.c
arch/arm/mach-realview/core.c
arch/arm/mach-versatile/core.c
arch/arm/mach-vexpress/ct-ca9x4.c
arch/arm/mach-vexpress/v2m.c

index f6b9011744aaebe469a8137ad7b4c34d71cb8fa3..166f892a24d5d0f9a09701f9605ab3198888d6be 100644 (file)
  * 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/clocksource.h>
 #include <linux/clockchips.h>
+#include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 #define TIMER_FREQ_KHZ (1000)
 #define TIMER_RELOAD   (TIMER_FREQ_KHZ * 1000 / HZ)
 
+static long __init sp804_get_clock_rate(const char *name)
+{
+       struct clk *clk;
+       long rate;
+       int err;
+
+       clk = clk_get_sys("sp804", name);
+       if (IS_ERR(clk)) {
+               pr_err("sp804: %s clock not found: %d\n", name,
+                       (int)PTR_ERR(clk));
+               return PTR_ERR(clk);
+       }
+
+       err = clk_enable(clk);
+       if (err) {
+               pr_err("sp804: %s clock failed to enable: %d\n", name, err);
+               clk_put(clk);
+               return err;
+       }
+
+       rate = clk_get_rate(clk);
+       if (rate < 0) {
+               pr_err("sp804: %s clock failed to get rate: %ld\n", name, rate);
+               clk_disable(clk);
+               clk_put(clk);
+       }
+
+       return rate;
+}
+
 void __init sp804_clocksource_init(void __iomem *base, const char *name)
 {
+       long rate = sp804_get_clock_rate(name);
+
+       if (rate < 0)
+               return;
+
        /* setup timer 0 as free-running clocksource */
        writel(0, base + TIMER_CTRL);
        writel(0xffffffff, base + TIMER_LOAD);
@@ -42,7 +79,7 @@ void __init sp804_clocksource_init(void __iomem *base, const char *name)
                base + TIMER_CTRL);
 
        clocksource_mmio_init(base + TIMER_VALUE, name,
-               TIMER_FREQ_KHZ * 1000, 200, 32, clocksource_mmio_readl_down);
+               rate, 200, 32, clocksource_mmio_readl_down);
 }
 
 
index 46fb7f580fef510508f2af2d3ddad168db580916..8fb8afb014efc16ee81916628fead06e6b3e2e38 100644 (file)
@@ -229,10 +229,17 @@ static struct clk cp_auxclk = {
        .vcoreg = CM_AUXOSC,
 };
 
+static struct clk sp804_clk = {
+       .rate   = 1000000,
+};
+
 static struct clk_lookup cp_lookups[] = {
        {       /* CLCD */
                .dev_id         = "mb:c0",
                .clk            = &cp_auxclk,
+       }, {    /* SP804 timers */
+               .dev_id         = "sp804",
+               .clk            = &sp804_clk,
        },
 };
 
index 6356b5e2e111af7f63e67e220ff30052c0a6c54d..6a9cd1eb4c2e23b080764ecbf46c4952d3f7339d 100644 (file)
@@ -315,6 +315,10 @@ static struct clk ref24_clk = {
        .rate   = 24000000,
 };
 
+static struct clk sp804_clk = {
+       .rate   = 1000000,
+};
+
 static struct clk dummy_apb_pclk;
 
 static struct clk_lookup lookups[] = {
@@ -357,7 +361,10 @@ static struct clk_lookup lookups[] = {
        }, {    /* SSP */
                .dev_id         = "dev:ssp0",
                .clk            = &ref24_clk,
-       }
+       }, {    /* SP804 timers */
+               .dev_id         = "sp804",
+               .clk            = &sp804_clk,
+       },
 };
 
 void __init realview_init_early(void)
index aad6d395be447fbe5df66ed404bc920a2afa11ab..b0b7de6875ab7da90367d650769ab24c868314ca 100644 (file)
@@ -375,6 +375,10 @@ static struct clk ref24_clk = {
        .rate   = 24000000,
 };
 
+static struct clk sp804_clk = {
+       .rate   = 1000000,
+};
+
 static struct clk dummy_apb_pclk;
 
 static struct clk_lookup lookups[] = {
@@ -411,7 +415,10 @@ static struct clk_lookup lookups[] = {
        }, {    /* CLCD */
                .dev_id         = "dev:20",
                .clk            = &osc4_clk,
-       }
+       }, {    /* SP804 timers */
+               .dev_id         = "sp804",
+               .clk            = &sp804_clk,
+       },
 };
 
 /*
index c833fd9505c5cd4c311b91882b7f94e94dff7fa2..6004f06cbde5e66d77228700f189a37847378b3b 100644 (file)
@@ -141,10 +141,18 @@ static struct clk osc1_clk = {
        .rate   = 24000000,
 };
 
+static struct clk ct_sp804_clk = {
+       .rate   = 1000000,
+};
+
 static struct clk_lookup lookups[] = {
        {       /* CLCD */
                .dev_id         = "ct:clcd",
                .clk            = &osc1_clk,
+       }, {    /* SP804 timers */
+               .dev_id         = "sp804",
+               .con_id         = "ct-timer1",
+               .clk            = &ct_sp804_clk,
        },
 };
 
index ccf1f899ac21b0eecd9f93785c553662bf45f12a..77d5db3d7808e9045172ccae544514c3fab1e1d0 100644 (file)
@@ -333,6 +333,10 @@ static struct clk osc2_clk = {
        .rate   = 24000000,
 };
 
+static struct clk v2m_sp804_clk = {
+       .rate   = 1000000,
+};
+
 static struct clk dummy_apb_pclk;
 
 static struct clk_lookup v2m_lookups[] = {
@@ -363,6 +367,10 @@ static struct clk_lookup v2m_lookups[] = {
        }, {    /* CLCD */
                .dev_id         = "mb:clcd",
                .clk            = &osc1_clk,
+       }, {    /* SP804 timers */
+               .dev_id         = "sp804",
+               .con_id         = "v2m-timer1",
+               .clk            = &v2m_sp804_clk,
        },
 };