aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/boot/dts/hi3620.dtsi522
-rw-r--r--drivers/clk/clk-hs.c194
2 files changed, 680 insertions, 36 deletions
diff --git a/arch/arm/boot/dts/hi3620.dtsi b/arch/arm/boot/dts/hi3620.dtsi
index 50968980474..7f78f3a6bda 100644
--- a/arch/arm/boot/dts/hi3620.dtsi
+++ b/arch/arm/boot/dts/hi3620.dtsi
@@ -24,39 +24,497 @@
interrupt-parent = <&intc>;
ranges;
- osc32k: osc@0 {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <32768>;
- clock-output-names = "osc32khz";
+ pmctrl: pmctrl@fca08000 {
+ compatible = "hisilicon,pmctrl";
+ reg = <0xfca08000 0x1000>;
};
- osc26m: osc@1 {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <26000000>;
- clock-output-names = "osc26mhz";
+ sctrl: sctrl@fc802000 {
+ compatible = "hisilicon,sctrl";
+ reg = <0xfc802000 0x1000>;
};
- pclk: clk@0 {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <26000000>;
- clock-output-names = "apb_pclk";
- };
+ /*clocks begins*/
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
- timclk0: clk@1 {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <60000000>;
- clock-output-names = "timer0";
- };
+ osc32k: osc@0 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "osc32khz";
+ };
+
+ osc26m: osc@1 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <26000000>;
+ clock-output-names = "osc26mhz";
+ };
+
+ pclk: clk@0 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <26000000>;
+ clock-output-names = "apb_pclk";
+ };
+
+ timclk0: clk@1 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <60000000>;
+ clock-output-names = "timer0";
+ };
+
+ timclk1: clk@2 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <60000000>;
+ clock-output-names = "timer1";
+ };
+
+ /*------pll clk------*/
+ armpll0: pll0 {
+ compatible = "hisilicon,pll";
+ #clock-cells = <0>;
+ clocks = <&osc26m>;
+ clock-frequency = <1600000000>;
+ clock-output-names = "clk_armpll0";
+ };
+ armpll1: pll1 {
+ compatible = "hisilicon,pll";
+ #clock-cells = <0>;
+ clocks = <&osc26m>;
+ clock-frequency = <1600000000>;
+ clock-output-names = "clk_armpll1";
+ };
+ peripll: pll2 {
+ compatible = "hisilicon,pll";
+ #clock-cells = <0>;
+ clocks = <&osc26m>;
+ clock-frequency = <1440000000>;
+ clock-output-names = "clk_armpll2";
+ };
+ usbpll: pll3 {
+ compatible = "hisilicon,pll";
+ #clock-cells = <0>;
+ clocks = <&osc26m>;
+ clock-frequency = <1440000000>;
+ clock-output-names = "clk_armpll3";
+ };
+
+ hdmipll: pll4 {
+ compatible = "hisilicon,pll";
+ #clock-cells = <0>;
+ clocks = <&osc26m>;
+ clock-frequency = <1188000000>;
+ clock-output-names = "clk_armpll4";
+ };
+
+ gpupll: pll5 {
+ compatible = "hisilicon,pll";
+ #clock-cells = <0>;
+ clocks = <&osc26m>;
+ clock-frequency = <1300000000>;
+ clock-output-names = "clk_armpll5";
+ };
+
+ /*--------------cfgaxi clock--------------------*/
+ clk_cfgaxi: cfgaxi {
+ compatible = "hisilicon,cfgaxi";
+ #clock-cells = <0>;
+ clocks = <&peripll>;
+ /*mult, div*/
+ hisilicon,fixed-factor = <1 30>;
+ };
+
+ /*-------------------mux clock-------------------*/
+ clk_uart0_mux: uart0_mux {
+ compatible = "hisilicon,muxclock";
+ #clock-cells = <0>;
+ clocks = <&osc26m &clk_cfgaxi>;
+ /*select register offset, mask*/
+ hisilicon,hi3620-clkmux = <0x100 0x80>;
+ };
+
+ clk_uart1_mux: uart1_mux {
+ compatible = "hisilicon,muxclock";
+ #clock-cells = <0>;
+ clocks = <&osc26m &clk_cfgaxi>;
+ hisilicon,hi3620-clkmux = <0x100 0x100>;
+ };
+
+ clk_uart2_mux: uart2_mux {
+ compatible = "hisilicon,muxclock";
+ #clock-cells = <0>;
+ clocks = <&osc26m &clk_cfgaxi>;
+ hisilicon,hi3620-clkmux = <0x100 0x200>;
+ };
+
+ clk_uart3_mux: uart3_mux {
+ compatible = "hisilicon,muxclock";
+ #clock-cells = <0>;
+ clocks = <&osc26m &clk_cfgaxi>;
+ hisilicon,hi3620-clkmux = <0x100 0x400>;
+ };
+
+ clk_uart4_mux: uart4_mux {
+ compatible = "hisilicon,muxclock";
+ #clock-cells = <0>;
+ clocks = <&osc26m &clk_cfgaxi>;
+ hisilicon,hi3620-clkmux = <0x100 0x800>;
+ };
+
+ /*---------------------gate clock-------------------*/
+ clk_uart0: uart0 {
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ clocks = <&clk_uart0_mux>;
+ /*enable register, enable bit*/
+ hisilicon,hi3620-clkgate = <0x40 16>;
+ clock-output-names = "clk_uart0";
+ };
+
+ clk_uart1: uart1 {
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ clocks = <&clk_uart1_mux>;
+ hisilicon,hi3620-clkgate = <0x40 17>;
+ clock-output-names = "clk_uart1";
+ };
+
+ clk_uart2: uart2 {
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ clocks = <&clk_uart2_mux>;
+ hisilicon,hi3620-clkgate = <0x40 18>;
+ clock-output-names = "clk_uart2";
+ };
+
+ clk_uart3: uart3 {
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ clocks = <&clk_uart3_mux>;
+ hisilicon,hi3620-clkgate = <0x40 19>;
+ clock-output-names = "clk_uart3";
+ };
+
+ clk_uart4: uart4 {
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ clocks = <&clk_uart4_mux>;
+ hisilicon,hi3620-clkgate = <0x40 20>;
+ clock-output-names = "clk_uart4";
+ };
+
+
+ /*-------------------spi clock----------------*/
+
+ clk_spi0_mux: spi0_mux {
+ compatible = "hisilicon,muxclock";
+ #clock-cells = <0>;
+ clocks = <&osc26m &clk_cfgaxi>;
+ hisilicon,hi3620-clkmux = <0x100 0x1000>;
+ };
+
+ clk_spi1_mux: spi1_mux {
+ compatible = "hisilicon,muxclock";
+ #clock-cells = <0>;
+ clocks = <&osc26m &clk_cfgaxi>;
+ hisilicon,hi3620-clkmux = <0x100 0x2000>;
+ };
+
+ clk_spi2_mux: spi2_mux {
+ compatible = "hisilicon,muxclock";
+ #clock-cells = <0>;
+ clocks = <&osc26m &clk_cfgaxi>;
+ hisilicon,hi3620-clkmux = <0x100 0x4000>;
+ };
+
+ clk_spi0: spi0 {
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ clocks = <&clk_spi0_mux>;
+ hisilicon,hi3620-clkgate = <0x40 21>;
+ clock-output-names = "clk_spi0";
+ };
+
+ clk_spi1: spi1 {
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ clocks = <&clk_spi1_mux>;
+ hisilicon,hi3620-clkgate = <0x40 22>;
+ clock-output-names = "clk_spi1";
+ };
+
+ clk_spi2: spi2 {
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ clocks = <&clk_spi2_mux>;
+ hisilicon,hi3620-clkgate = <0x40 23>;
+ clock-output-names = "clk_spi2";
+ };
+
+ /*-------------------mux clock----------------*/
+ clk_pwm0_mux: pwm0_mux{
+ compatible = "hisilicon,muxclock";
+ #clock-cells = <0>;
+ clocks = <&osc32k &osc26m>;
+ hisilicon,hi3620-clkmux = <0x104 0x400>;
+ };
- timclk1: clk@2 {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <60000000>;
- clock-output-names = "timer1";
+ clk_mmc1_mux: mmc1_mux{
+ compatible = "hisilicon,muxclock";
+ #clock-cells = <0>;
+ clocks = <&osc26m &clk_cfgaxi>;
+ hisilicon,hi3620-clkmux = <0x108 0x200>;
+ };
+
+ clk_venc_mux: venc_mux{
+ compatible = "hisilicon,muxclock";
+ #clock-cells = <0>;
+ clocks = <&peripll &usbpll>;
+ hisilicon,hi3620-clkmux = <0x10c 0x800>;
+ };
+
+ clk_g2d_mux: g2d_mux{
+ compatible = "hisilicon,muxclock";
+ #clock-cells = <0>;
+ clocks = <&peripll &usbpll>;
+ hisilicon,hi3620-clkmux = <0x10c 0x20>;
+ };
+
+ clk_vdec_mux: vdec_mux{
+ compatible = "hisilicon,muxclock";
+ #clock-cells = <0>;
+ clocks = <&peripll &usbpll>;
+ hisilicon,hi3620-clkmux = <0x110 0x20>;
+ };
+
+ clk_vpp_mux: vpp_mux{
+ compatible = "hisilicon,muxclock";
+ #clock-cells = <0>;
+ clocks = <&peripll &usbpll>;
+ hisilicon,hi3620-clkmux = <0x110 0x800>;
+ };
+
+ clk_ldi0_mux: ldi0_mux{
+ compatible = "hisilicon,muxclock";
+ #clock-cells = <0>;
+ clocks = <&peripll &usbpll &hdmipll>;
+ hisilicon,hi3620-clkmux = <0x114 0x6000>;
+ };
+
+ clk_ldi1_mux: ldi1_mux{
+ compatible = "hisilicon,muxclock";
+ #clock-cells = <0>;
+ clocks = <&peripll &usbpll &hdmipll>;
+ hisilicon,hi3620-clkmux = <0x118 0xc000>;
+ };
+
+ /*----periclock: gate clk, reg offset to sctrl-----*/
+
+ clk_sci: sci {
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ clocks = <&osc26m>;
+ /*enable register, enable bit*/
+ hisilicon,hi3620-clkgate = <0x40 26>;
+ clock-output-names = "clk_sci";
+ };
+
+ clk_dphy0: dphy0 {
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ clocks = <&osc26m>;
+ hisilicon,hi3620-clkgate = <0x30 15>;
+ clock-output-names = "clk_dphy0";
+ };
+
+ clk_dphy1: dphy1 {
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ clocks = <&osc26m>;
+ hisilicon,hi3620-clkgate = <0x30 16>;
+ };
+
+ clk_dphy2: dphy2 {
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ clocks = <&osc26m>;
+ hisilicon,hi3620-clkgate = <0x30 17>;
+ };
+
+ clk_kpc: kpc {
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ clocks = <&osc32k>;
+ hisilicon,hi3620-clkgate = <0x20 6>;
+ };
+
+ clk_pwm0_gate: pwm0_gate {
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ clocks = <&osc32k &osc26m>;
+ hisilicon,hi3620-clkgate = <0x40 7>;
+ };
+
+ /*gpio0-----gpio21 gate clock*/
+ clk_gpio0: gpio0{
+ compatible = "hisilicon,periclock";
+ hisilicon,hi3620-clkgate = <0x20 8>;
+ clock-output-names = "clk_gpio0";
+ };
+ clk_gpio1: gpio1{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 9>;
+ clock-output-names = "clk_gpio1";
+ };
+ clk_gpio2: gpio2{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 10>;
+ clock-output-names = "clk_gpio2";
+ };
+ clk_gpio3: gpio3{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 11>;
+ clock-output-names = "clk_gpio3";
+ };
+ clk_gpio4: gpio4{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 12>;
+ clock-output-names = "clk_gpio4";
+ };
+ clk_gpio5: gpio5{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 13>;
+ clock-output-names = "clk_gpio5";
+ };
+ clk_gpio6: gpio6{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 14>;
+ clock-output-names = "clk_gpio6";
+ };
+
+ clk_gpio7: gpio7{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 15>;
+ clock-output-names = "clk_gpio7";
+ };
+ clk_gpio8: gpio8{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 16>;
+ clock-output-names = "clk_gpio8";
+ };
+ clk_gpio9: gpio9{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 17>;
+ clock-output-names = "clk_gpio9";
+ };
+ clk_gpio10: gpio10{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 18>;
+ clock-output-names = "clk_gpio10";
+ };
+ clk_gpio11: gpio11{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 19>;
+ clock-output-names = "clk_gpio11";
+ };
+ clk_gpio12: gpio12{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 20>;
+ clock-output-names = "clk_gpio12";
+ };
+ clk_gpio13: gpio13{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 21>;
+ clock-output-names = "clk_gpio13";
+ };
+ clk_gpio14: gpio14{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 22>;
+ clock-output-names = "clk_gpio14";
+ };
+ clk_gpio15: gpio15{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 23>;
+ clock-output-names = "clk_gpio15";
+ };
+ clk_gpio16: gpio16{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 24>;
+ clock-output-names = "clk_gpio16";
+ };
+ clk_gpio17: gpio17{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 25>;
+ clock-output-names = "clk_gpio17";
+ };
+ clk_gpio18: gpio18{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 26>;
+ clock-output-names = "clk_gpio18";
+ };
+ clk_gpio19: gpio19{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 27>;
+ clock-output-names = "clk_gpio19";
+ };
+ clk_gpio20: gpio20{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 28>;
+ clock-output-names = "clk_gpio20";
+ };
+ clk_gpio21: gpio21{
+ compatible = "hisilicon,periclock";
+ #clock-cells = <0>;
+ hisilicon,hi3620-clkgate = <0x20 29>;
+ clock-output-names = "clk_gpio21";
+ };
+
+ /*--------------------divider clock -------------------*/
+ divtable: clkdiv {
+ #hisilicon,clkdiv-table-cells = <2>;
+ };
+
+ clk_div_shaxi: div_shaxi{
+ compatible = "hisilicon,divclock";
+ #clock-cells = <0>;
+ clocks = <&peripll>;
+ hisilicon,clkdiv-table = <&divtable 0x04 5>;
+ /*divider register offset, shift, width*/
+ hisilicon,hi3620-clkdiv = <0x100 0 5>;
+ };
+
+ clk_div_cfgaxi: div_cfgaxi{
+ compatible = "hisilicon,divclock";
+ #clock-cells = <0>;
+ clocks = <&clk_div_shaxi>;
+ hisilicon,clkdiv-table = <&divtable 0x01 2>;
+ hisilicon,hi3620-clkdiv = <0x100 5 2>;
+ };
};
rtc0: rtc@fc804000 {
@@ -145,7 +603,7 @@
compatible = "arm,pl011", "arm,primecell";
reg = <0xfcb00000 0x1000>;
interrupts = <0 20 4>;
- clocks = <&pclk>;
+ clocks = <&clk_uart0>;
clock-names = "apb_pclk";
status = "disabled";
};
@@ -154,7 +612,7 @@
compatible = "arm,pl011", "arm,primecell";
reg = <0xfcb01000 0x1000>;
interrupts = <0 21 4>;
- clocks = <&pclk>;
+ clocks = <&clk_uart1>;
clock-names = "apb_pclk";
status = "disabled";
};
@@ -163,7 +621,7 @@
compatible = "arm,pl011", "arm,primecell";
reg = <0xfcb02000 0x1000>;
interrupts = <0 22 4>;
- clocks = <&pclk>;
+ clocks = <&clk_uart2>;
clock-names = "apb_pclk";
status = "disabled";
};
@@ -172,7 +630,7 @@
compatible = "arm,pl011", "arm,primecell";
reg = <0xfcb03000 0x1000>;
interrupts = <0 23 4>;
- clocks = <&pclk>;
+ clocks = <&clk_uart3>;
clock-names = "apb_pclk";
status = "disabled";
};
@@ -181,7 +639,7 @@
compatible = "arm,pl011", "arm,primecell";
reg = <0xfcb04000 0x1000>;
interrupts = <0 24 4>;
- clocks = <&pclk>;
+ clocks = <&clk_uart4>;
clock-names = "apb_pclk";
status = "disabled";
};
diff --git a/drivers/clk/clk-hs.c b/drivers/clk/clk-hs.c
index 99f907f0d23..88ad41c59fa 100644
--- a/drivers/clk/clk-hs.c
+++ b/drivers/clk/clk-hs.c
@@ -23,23 +23,209 @@
#include <linux/kernel.h>
#include <linux/clk-provider.h>
+#include <linux/clk-private.h>
#include <linux/clkdev.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_device.h>
#include <linux/slab.h>
+#include <linux/clk.h>
+
+static DEFINE_SPINLOCK(_lock);
+
+
+void __iomem *pmctrl_base;
+void __iomem *sctrl_base;
+
+
+void __init of_gate_clk_setup(struct device_node *node)
+{
+ struct clk *clk;
+ const char *clk_name = node->name;
+ const char *clk_parnet;
+ int err;
+ u32 data[2];
+ void __iomem *reg;
+ u8 enable_bit;
+
+ err = of_property_read_u32_array(node, "hisilicon,hi3620-clkgate", &data[0], 2);
+ if (err) {
+ printk("[%s] cann't values form hisilicon,hi3620-clkgate property! \n", node->name);
+ return ;
+ }
+
+ reg = sctrl_base + data[0];
+ enable_bit = (u8)data[1];
+
+ clk_parnet = of_clk_get_parent_name(node, 0);
+
+ clk = clk_register_gate(NULL, clk_name, clk_parnet, CLK_IS_BASIC,
+ reg, enable_bit, 1, &_lock);
+ if (!IS_ERR(clk))
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+
+
+void __init of_fixed_factor_clk_setup(struct device_node *node)
+{
+ struct clk *clk;
+ const char *clk_name = node->name;
+ const char *clk_parnet;
+ int err;
+ unsigned long rate;
+ u32 vals[2];
+
+ clk_parnet = of_clk_get_parent_name(node, 0);
+
+ err = of_property_read_u32_array(node, "hisilicon,fixed-factor", vals, 2);
+ if (err) {
+ printk("[%s] cann't values form hisilicon,fixed_factor property! \n", node->name);
+ return ;
+ }
+
+ clk = clk_register_fixed_factor(NULL, clk_name, clk_parnet, CLK_IS_BASIC, vals[0], vals[1]);
+ if (!IS_ERR(clk))
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+
+void __init of_divider_clk_setup(struct device_node *node)
+{
+ struct clk *clk;
+ const char *clk_name = node->name;
+ const char *clk_parnet;
+ struct clk_div_table *table;
+ int err;
+ void __iomem *reg;
+ u8 shift,width;
+ unsigned int table_num;
+ int i;
+ u32 data[3];
+ char *propname = "hisilicon,clkdiv-table";
+ char *cellname = "#hisilicon,clkdiv-table-cells";
+ struct of_phandle_args div_table;
+
+ /*process the div_table*/
+ for (i = 0; ; i++) {
+ err = of_parse_phandle_with_args(node, propname, cellname, i, &div_table);
+ if (err)
+ break;
+ }
+
+ /*table ends with <0, 0>, so plus one to table_num*/
+ table_num = i + 1;
+
+ table = kzalloc(sizeof(struct clk_div_table) * table_num, GFP_KERNEL);
+ if (!table)
+ return ;
+
+ for (i = 0; ; i++) {
+ err = of_parse_phandle_with_args(node, propname, cellname, i, &div_table);
+ if (err)
+ break;
+
+ table[i].val = div_table.args[0];
+ table[i].div = div_table.args[1];
+ }
+
+ err = of_property_read_u32_array(node, "hisilicon,hi3620-clkdiv", &data[0], 3);
+ if (err) {
+ printk("[%s] cann't values form hisilicon,hi3620-clkdiv property! \n", node->name);
+ kfree(table);
+ return ;
+ }
+
+ reg = sctrl_base + data[0];
+ shift = (u8)data[1];
+ width = (u8)data[2];
+
+ clk_parnet = of_clk_get_parent_name(node, 0);
+
+ clk = clk_register_divider_table(NULL, clk_name, clk_parnet, CLK_IS_BASIC, reg,
+ shift, width, 0, table, &_lock);
+ if (!IS_ERR(clk))
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ else
+ kfree(table);
+}
+
+
+static void __init of_mux_clk_setup(struct device_node *node)
+{
+ int i, err;
+ void __iomem *clk_sel;
+ u8 num_parents;
+ const char *clk_name = node->name;
+ const char **parent_names;
+ struct clk *clk;
+ unsigned int shift,width;
+ u32 vals[2];
+
+ /* get the count of items in mux */
+ for (i = 0; ; i++) {
+ /* parent's #clock-cells property is always 0 */
+ if (!of_parse_phandle(node, "clocks", i))
+ break;
+ }
+
+ num_parents = i;
+
+ if (!num_parents)
+ return;
+
+ err = of_property_read_u32_array(node, "hisilicon,hi3620-clkmux", &vals[0], 2);
+ if (err) {
+ printk("cann't values form hisilicon,hi3620-clkmux property!\n");
+ return;
+ }
+ clk_sel = sctrl_base + vals[0];
+
+ shift = ffs(vals[1]) - 1;
+ width = fls(vals[1]) - ffs(vals[1]) + 1;
+
+ parent_names = kzalloc(sizeof(char *) * num_parents, GFP_KERNEL);
+ if (!parent_names)
+ return;
+
+ for (i = 0; i < num_parents; i++) {
+ parent_names[i] = of_clk_get_parent_name(node, i);
+ }
+ clk = clk_register_mux(NULL, clk_name, parent_names, num_parents,
+ CLK_SET_RATE_PARENT,
+ clk_sel, shift, width, 0, &_lock);
+ if (IS_ERR(clk))
+ goto err_mux;
+
+ clk_register_clkdev(clk, clk_name, NULL);
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+ return;
+err_mux:
+ kfree(parent_names);
+}
static const __initconst struct of_device_id hs_clk_match[] = {
- {
- .compatible = "fixed-clock",
- .data = of_fixed_clk_setup,
- },
+ { .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
+ { .compatible = "hisilicon,pll", .data = of_fixed_clk_setup, },
+ { .compatible = "hisilicon,muxclock", .data = of_mux_clk_setup, },
+ { .compatible = "hisilicon,periclock", .data = of_gate_clk_setup, },
+ { .compatible = "hisilicon,divclock", .data = of_divider_clk_setup, },
+ { .compatible = "hisilicon,cfgaxi", .data = of_fixed_factor_clk_setup,},
+ {}
};
void __init hs_init_clocks(void)
{
struct device_node *node;
+ /*map pmctrl registers*/
+ node = of_find_compatible_node(NULL, NULL, "hisilicon,pmctrl");
+ pmctrl_base = of_iomap(node, 0);
+ WARN_ON(!pmctrl_base);
+
+ node = of_find_compatible_node(NULL, NULL, "hisilicon,sctrl");
+ sctrl_base = of_iomap(node, 0);
+
of_clk_init(hs_clk_match);
}