microblaze: Add support for CCF
authorMichal Simek <michal.simek@xilinx.com>
Wed, 18 Dec 2013 16:18:48 +0000 (17:18 +0100)
committerMichal Simek <michal.simek@xilinx.com>
Mon, 27 Jan 2014 10:24:55 +0000 (11:24 +0100)
Add support for CCF for Microblaze.

Old binding:
system_timer: system-timer@41c00000 {
clock-frequency = <75000000>;
...
}

New binding:
system_timer: system-timer@41c00000 {
clocks = <&clk_bus>;
...
}

Both should be supported for a while

Microblaze clock binding:
clocks {
#address-cells = <1>;
#size-cells = <0>;
clk_bus: bus {
#clock-cells = <0>;
clock-frequency = <75000000>;
clock-output-names = "bus";
compatible = "fixed-clock";
reg = <1>;
} ;
clk_cpu: cpu {
#clock-cells = <0>;
clock-frequency = <75000000>;
clock-output-names = "cpu";
compatible = "fixed-clock";
reg = <0>;
} ;
} ;

Signed-off-by: Michal Simek <michal.simek@xilinx.com>
arch/microblaze/Kconfig
arch/microblaze/include/asm/cpuinfo.h
arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
arch/microblaze/kernel/cpu/cpuinfo-static.c
arch/microblaze/kernel/cpu/cpuinfo.c
arch/microblaze/kernel/setup.c
arch/microblaze/kernel/timer.c

index e23cccde9c2759b9ea798a3a0705f7f242acd474..a715eeaf99591e53df79ce1b1c9cb2396ab4507d 100644 (file)
@@ -26,6 +26,7 @@ config MICROBLAZE
        select GENERIC_CPU_DEVICES
        select GENERIC_ATOMIC64
        select GENERIC_CLOCKEVENTS
+       select COMMON_CLK
        select GENERIC_IDLE_POLL_SETUP
        select MODULES_USE_ELF_RELA
        select CLONE_BACKWARDS3
index 7161fb575861b35931a0fe85cabce251b3ea7e46..3337417fcdca3b6794d0e46dd65d150a472c00d6 100644 (file)
@@ -91,6 +91,7 @@ extern struct cpuinfo cpuinfo;
 
 /* fwd declarations of the various CPUinfo populators */
 void setup_cpuinfo(void);
+void setup_cpuinfo_clk(void);
 
 void set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu);
 void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu);
index ee46894154101cad22e70e4ccbf91b44172cee2d..93c26cf50de525db0a5bee58baa6b84bf92a53c3 100644 (file)
@@ -112,7 +112,4 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
        CI(num_wr_brk, NUMBER_OF_WR_ADDR_BRK);
 
        CI(fpga_family_code, TARGET_FAMILY);
-
-       /* take timebase-frequency from DTS */
-       ci->cpu_clock_freq = fcpu(cpu, "timebase-frequency");
 }
index 592bb2e838c4f5e0d0d25685d59373a73b7a579a..4854285b26e77876121de423b94db2059adcaa1a 100644 (file)
@@ -113,8 +113,6 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu)
        ci->num_rd_brk = fcpu(cpu, "xlnx,number-of-rd-addr-brk");
        ci->num_wr_brk = fcpu(cpu, "xlnx,number-of-wr-addr-brk");
 
-       ci->cpu_clock_freq = fcpu(cpu, "timebase-frequency");
-
        ci->pvr_user1 = fcpu(cpu, "xlnx,pvr-user1");
        ci->pvr_user2 = fcpu(cpu, "xlnx,pvr-user2");
 
index c9203b1007aad889a1cb742448b27397ccd83be9..ce1cfed731eac77f57f8fd9dde77004d2fdb61ca 100644 (file)
@@ -8,6 +8,7 @@
  * for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/init.h>
 #include <asm/cpuinfo.h>
 #include <asm/pvr.h>
@@ -68,11 +69,10 @@ const struct family_string_key family_string_lookup[] = {
 };
 
 struct cpuinfo cpuinfo;
+static struct device_node *cpu;
 
 void __init setup_cpuinfo(void)
 {
-       struct device_node *cpu = NULL;
-
        cpu = (struct device_node *) of_find_node_by_type(NULL, "cpu");
        if (!cpu)
                pr_err("You don't have cpu!!!\n");
@@ -102,3 +102,22 @@ void __init setup_cpuinfo(void)
                pr_warn("%s: Stream instructions enabled"
                        " - USERSPACE CAN LOCK THIS KERNEL!\n", __func__);
 }
+
+void __init setup_cpuinfo_clk(void)
+{
+       struct clk *clk;
+
+       clk = of_clk_get(cpu, 0);
+       if (IS_ERR(clk)) {
+               pr_err("ERROR: CPU CCF input clock not found\n");
+               /* take timebase-frequency from DTS */
+               cpuinfo.cpu_clock_freq = fcpu(cpu, "timebase-frequency");
+       } else {
+               cpuinfo.cpu_clock_freq = clk_get_rate(clk);
+       }
+
+       if (!cpuinfo.cpu_clock_freq) {
+               pr_err("ERROR: CPU clock frequency not setup\n");
+               BUG();
+       }
+}
index 603e22fec6d5b888d3f164cd08afa0d17ed3b037..9d972d2bd924b1a791884344d3b1ccf7d7d19992 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/clk-provider.h>
 #include <linux/clocksource.h>
 #include <linux/string.h>
 #include <linux/seq_file.h>
@@ -195,6 +196,8 @@ void __init machine_early_init(const char *cmdline, unsigned int ram,
 
 void __init time_init(void)
 {
+       of_clk_init(NULL);
+       setup_cpuinfo_clk();
        clocksource_of_init();
 }
 
index 3e39b1082fdf8433a030e851dfe37f2b63f8b766..55b19400951f5f0ee3ae86e42450924d79cd6de5 100644 (file)
@@ -230,9 +230,9 @@ static int timer_initialized;
 
 static void __init xilinx_timer_init(struct device_node *timer)
 {
+       struct clk *clk;
        u32 irq;
        u32 timer_num = 1;
-       int ret;
 
        timer_baseaddr = of_iomap(timer, 0);
        if (!timer_baseaddr) {
@@ -250,10 +250,20 @@ static void __init xilinx_timer_init(struct device_node *timer)
 
        pr_info("%s: irq=%d\n", timer->full_name, irq);
 
-       /* If there is clock-frequency property than use it */
-       ret = of_property_read_u32(timer, "clock-frequency", &timer_clock_freq);
-       if (ret < 0)
+       clk = of_clk_get(timer, 0);
+       if (IS_ERR(clk)) {
+               pr_err("ERROR: timer CCF input clock not found\n");
+               /* If there is clock-frequency property than use it */
+               of_property_read_u32(timer, "clock-frequency",
+                                   &timer_clock_freq);
+       } else {
+               timer_clock_freq = clk_get_rate(clk);
+       }
+
+       if (!timer_clock_freq) {
+               pr_err("ERROR: Using CPU clock frequency\n");
                timer_clock_freq = cpuinfo.cpu_clock_freq;
+       }
 
        freq_div_hz = timer_clock_freq / HZ;