From 27e7d0cf5b89ae9f5abdc8e8720b3c6d130e7a2a Mon Sep 17 00:00:00 2001 From: Zhangfei Gao Date: Wed, 21 Aug 2013 10:34:54 +0800 Subject: ARM: hs: add clk-hi3716 Signed-off-by: Zhangfei Gao Signed-off-by: Zhang Mingjun --- Documentation/devicetree/bindings/clock/hi3716.txt | 121 ++++++++++ drivers/clk/hisilicon/Makefile | 2 +- drivers/clk/hisilicon/clk-hi3716.c | 268 +++++++++++++++++++++ 3 files changed, 390 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/clock/hi3716.txt create mode 100644 drivers/clk/hisilicon/clk-hi3716.c diff --git a/Documentation/devicetree/bindings/clock/hi3716.txt b/Documentation/devicetree/bindings/clock/hi3716.txt new file mode 100644 index 000000000000..60af61e1a413 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/hi3716.txt @@ -0,0 +1,121 @@ +Device Tree Clock bindings for hi3716 + +This binding uses the common clock binding[1]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt + +Clock control register +Required properties: +- compatible : "hisilicon,clkbase" +- reg : Address and size of clkbase. + +Device Clocks + +Device clocks are required to have one or both of the following sets of +properties: + + +Gated device clocks: + +Required properties: +- compatible : "hisilicon,hi3716-clk-gate" +- gate-reg : shall be the register offset from clkbase and enable bit, reset bit +- clock-output-names : shall be reference name + + +Mux device clocks: + +Required properties: +- compatible : "hisilicon,hi3716-clk-mux" +- mux-reg : shall be the register offset from clkbase and mux_shift mux_width +- mux-table : shall be reg value to be choose clocks accordingly +- clock-output-names : shall be reference name + + +Fixed divisor device clocks: + +Required properties: +- compatible : "hisilicon,hi3716-fixed-divider" +- div-table : shall be divisor sequence +- clock-output-names : shall be reference name according to divisor + + +Fixed pll clocks: + +Required properties: +- compatible : "hisilicon,hi3716-fixed-pll" +- clock-frequency : shall be output clock frequence sequence +- clock-output-names : shall be reference name according to clock-frequnce + +For example: + clkbase@f8a22000 { + compatible = "hisilicon,clkbase"; + reg = <0xf8a22000 0x1000>; + }; + + osc24m: osc { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "osc24mhz"; + }; + + bpll: bpll { + compatible = "hisilicon,hi3716-fixed-pll"; + #clock-cells = <1>; + clocks = <&osc24m>; + clock-frequency = <1200000000>, + <600000000>, + <300000000>, + <200000000>, + <150000000>; + clock-output-names = "bpll_fout0", + "bpll_fout1", + "bpll_fout2", + "bpll_fout3", + "bpll_fout4"; + }; + + bpll_fout0_div: bpll_fout0_div {/* 1200Mhz */ + compatible = "hisilicon,hi3716-fixed-divider"; + #clock-cells = <1>; + clocks = <&bpll 0>; + div-table = <3 14 25 50>; + clock-output-names = "fout0_400m", "fout0_86m", + "fout0_48m", "fout0_24m"; + }; + + bpll_fout3_div: bpll_fout3_div { + compatible = "hisilicon,hi3716-fixed-divider"; + #clock-cells = <1>; + clocks = <&bpll 3>; + div-table = <2 4 5 8>; + clock-output-names = "fout3_100m", "fout3_50m", + "fout3_40m", "fout3_25m"; + }; + + clk_sfc_mux: clk_sfc_mux { + compatible = "hisilicon,hi3716-clk-mux"; + #clock-cells = <0>; + /* clks: 24M 75M 100M 150M 200M */ + clocks = <&osc24m>, <&bpll_fout2_div>, + <&bpll_fout3_div 0>, <&bpll 4>, <&bpll 3>; + + /* offset mux_shift mux_width */ + mux-reg = <0x5c 8 3>; + /* mux reg value to choose clks */ + mux-table = <0 7 6 4 5>; + + clock-output-names = "sfc_mux"; + }; + + clk_sfc: clk_sfc { + compatible = "hisilicon,hi3716-clk-gate"; + #clock-cells = <0>; + clocks = <&clk_sfc_mux>; + + /* offset, enable, reset */ + gate-reg = <0x5c 0 4>; + + clock-output-names = "sfc"; + }; diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile index d5be1b002e5f..682b8dc12b04 100644 --- a/drivers/clk/hisilicon/Makefile +++ b/drivers/clk/hisilicon/Makefile @@ -1 +1 @@ -obj-$(CONFIG_HI3xxx_CLK_CORE) += clk-hi3xxx.o +obj-$(CONFIG_HI3xxx_CLK_CORE) += clk-hi3xxx.o clk-hi3716.o diff --git a/drivers/clk/hisilicon/clk-hi3716.c b/drivers/clk/hisilicon/clk-hi3716.c new file mode 100644 index 000000000000..887ffe90fba5 --- /dev/null +++ b/drivers/clk/hisilicon/clk-hi3716.c @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2013 Linaro Ltd. + * Copyright (c) 2013 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_SPINLOCK(_lock); + +static void __iomem *clk_base; + +struct hi3716_clk { + struct clk_gate gate; + void __iomem *reg; + u8 reset_bit; +}; + +#define MAX_NUMS 10 + +static struct hi3716_clk *to_clk_hi3716(struct clk_hw *hw) +{ + return container_of(hw, struct hi3716_clk, gate.hw); +} + +static void __init hi3716_map_io(void) +{ + struct device_node *node; + + if (clk_base) + return; + + node = of_find_compatible_node(NULL, NULL, "hisilicon,clkbase"); + if (node) + clk_base = of_iomap(node, 0); + WARN_ON(!clk_base); +} + +static int hi3716_clkgate_prepare(struct clk_hw *hw) +{ + struct hi3716_clk *clk = to_clk_hi3716(hw); + unsigned long flags = 0; + u32 reg; + + spin_lock_irqsave(&_lock, flags); + + reg = readl_relaxed(clk->reg); + reg &= ~BIT(clk->reset_bit); + writel_relaxed(reg, clk->reg); + + spin_unlock_irqrestore(&_lock, flags); + + return 0; +} + +static void hi3716_clkgate_unprepare(struct clk_hw *hw) +{ + struct hi3716_clk *clk = to_clk_hi3716(hw); + unsigned long flags = 0; + u32 reg; + + spin_lock_irqsave(&_lock, flags); + + reg = readl_relaxed(clk->reg); + reg |= BIT(clk->reset_bit); + writel_relaxed(reg, clk->reg); + + spin_unlock_irqrestore(&_lock, flags); +} + +static struct clk_ops hi3716_clkgate_ops = { + .prepare = hi3716_clkgate_prepare, + .unprepare = hi3716_clkgate_unprepare, +}; + +void __init hi3716_clkgate_setup(struct device_node *node) +{ + struct clk *clk; + struct hi3716_clk *p_clk; + struct clk_init_data init; + const char *parent_name; + u32 array[3]; /* reg, enable_bit, reset_bit */ + int err; + + hi3716_map_io(); + err = of_property_read_u32_array(node, "gate-reg", &array[0], 3); + if (WARN_ON(err)) + return; + + err = of_property_read_string(node, "clock-output-names", &init.name); + if (WARN_ON(err)) + return; + + p_clk = kzalloc(sizeof(*p_clk), GFP_KERNEL); + if (WARN_ON(!p_clk)) + return; + + hi3716_clkgate_ops.enable = clk_gate_ops.enable; + hi3716_clkgate_ops.disable = clk_gate_ops.disable; + hi3716_clkgate_ops.is_enabled = clk_gate_ops.is_enabled; + + init.ops = &hi3716_clkgate_ops; + init.flags = CLK_SET_RATE_PARENT; + parent_name = of_clk_get_parent_name(node, 0); + init.parent_names = &parent_name; + init.num_parents = 1; + + p_clk->reg = p_clk->gate.reg = clk_base + array[0]; + p_clk->gate.bit_idx = array[1]; + p_clk->gate.flags = 0; + p_clk->gate.lock = &_lock; + p_clk->gate.hw.init = &init; + p_clk->reset_bit = array[2]; + + clk = clk_register(NULL, &p_clk->gate.hw); + if (WARN_ON(IS_ERR(clk))) { + kfree(p_clk); + return; + } + + of_clk_add_provider(node, of_clk_src_simple_get, clk); +} + +static void __init hi3716_clkmux_setup(struct device_node *node) +{ + int num = 0, err; + void __iomem *reg; + unsigned int shift, width; + u32 array[3]; /* reg, mux_shift, mux_width */ + u32 *table = NULL; + const char *clk_name = node->name; + const char *parents[MAX_NUMS]; + struct clk *clk; + + hi3716_map_io(); + err = of_property_read_string(node, "clock-output-names", &clk_name); + if (WARN_ON(err)) + return; + + err = of_property_read_u32_array(node, "mux-reg", &array[0], 3); + if (WARN_ON(err)) + return; + + reg = clk_base + array[0]; + shift = array[1]; + width = array[2]; + + while ((num < MAX_NUMS) && + ((parents[num] = of_clk_get_parent_name(node, num)) != NULL)) + num++; + if (!num) + return; + + table = kzalloc(sizeof(u32 *) * num, GFP_KERNEL); + if (WARN_ON(!table)) + return; + + err = of_property_read_u32_array(node, "mux-table", table, num); + if (WARN_ON(err)) + goto err; + + clk = clk_register_mux_table(NULL, clk_name, parents, num, + CLK_SET_RATE_PARENT, reg, shift, BIT(width) - 1, + 0, table, &_lock); + if (WARN_ON(IS_ERR(clk))) + goto err; + + clk_register_clkdev(clk, clk_name, NULL); + of_clk_add_provider(node, of_clk_src_simple_get, clk); + return; + +err: + kfree(table); + return; +} + +static void __init hi3716_fixed_pll_setup(struct device_node *node) +{ + const char *clk_name, *parent_name; + struct clk *clks[MAX_NUMS]; + u32 rate[MAX_NUMS]; + struct clk_onecell_data *clk_data; + int i, err, nums = 0; + + nums = of_property_count_strings(node, "clock-output-names"); + if (WARN_ON((nums < 0) || (nums > MAX_NUMS))) + return; + + err = of_property_read_u32_array(node, "clock-frequency", + &rate[0], nums); + WARN_ON(err); + + parent_name = of_clk_get_parent_name(node, 0); + + for (i = 0; i < nums; i++) { + err = of_property_read_string_index(node, "clock-output-names", + i, &clk_name); + WARN_ON(err); + + clks[i] = clk_register_fixed_rate(NULL, clk_name, + parent_name, 0, rate[i]); + WARN_ON(IS_ERR(clks[i])); + } + + clk_data = kzalloc(sizeof(*clk_data) + nums * sizeof(struct clk *), + GFP_KERNEL); + if (WARN_ON(!clk_data)) + return; + + memcpy(&clk_data[1], clks, nums * sizeof(struct clk *)); + clk_data->clks = (struct clk **)&clk_data[1]; + clk_data->clk_num = nums; + of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); +} + +void __init hi3716_fixed_divider_setup(struct device_node *node) +{ + const char *clk_parent; + const char *clk_name; + u32 div[MAX_NUMS]; + struct clk *clks[MAX_NUMS]; + struct clk_onecell_data *clk_data; + int err, i, nums = 0; + + clk_parent = of_clk_get_parent_name(node, 0); + + nums = of_property_count_strings(node, "clock-output-names"); + if (WARN_ON((nums < 0) || (nums > MAX_NUMS))) + return; + + err = of_property_read_u32_array(node, "div-table", &div[0], nums); + WARN_ON(err); + + for (i = 0; i < nums; i++) { + err = of_property_read_string_index(node, + "clock-output-names", i, &clk_name); + WARN_ON(err); + + clks[i] = clk_register_fixed_factor(NULL, clk_name, + clk_parent, CLK_SET_RATE_PARENT, 1, div[i]); + WARN_ON(IS_ERR(clks[i])); + } + + clk_data = kzalloc(sizeof(*clk_data) + nums * sizeof(struct clk *), + GFP_KERNEL); + if (WARN_ON(!clk_data)) + return; + + memcpy(&clk_data[1], clks, nums * sizeof(struct clk *)); + clk_data->clks = (struct clk **)&clk_data[1]; + clk_data->clk_num = nums; + of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); +} + +CLK_OF_DECLARE(hi3716_fixed_rate, "fixed-clock", of_fixed_clk_setup) +CLK_OF_DECLARE(hi3716_fixed_pll, "hisilicon,hi3716-fixed-pll", hi3716_fixed_pll_setup) +CLK_OF_DECLARE(hi3716_divider, "hisilicon,hi3716-fixed-divider", hi3716_fixed_divider_setup) +CLK_OF_DECLARE(hi3716_mux, "hisilicon,hi3716-clk-mux", hi3716_clkmux_setup) +CLK_OF_DECLARE(hi3716_gate, "hisilicon,hi3716-clk-gate", hi3716_clkgate_setup) -- cgit v1.2.3 From 4e743fe9ad57459ac425a86c7097a4b07e1a2013 Mon Sep 17 00:00:00 2001 From: Zhangfei Gao Date: Tue, 13 Aug 2013 15:37:28 +0800 Subject: ARM: hs: support hi3716-dkb board Signed-off-by: Zhangfei Gao Signed-off-by: Zhang Mingjun Signed-off-by: Haojian Zhuang --- arch/arm/boot/dts/Makefile | 3 +- arch/arm/boot/dts/hi3716-dkb.dts | 56 +++++++++ arch/arm/boot/dts/hi3716.dtsi | 256 +++++++++++++++++++++++++++++++++++++++ arch/arm/mach-hs/hs-dt.c | 1 + 4 files changed, 315 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/hi3716-dkb.dts create mode 100644 arch/arm/boot/dts/hi3716.dtsi diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 57cb00ce5d75..c1f09712080e 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -60,7 +60,8 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \ exynos5440-ssdk5440.dtb dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb \ ecx-2000.dtb -dtb-$(CONFIG_ARCH_HS) += hi4511.dtb +dtb-$(CONFIG_ARCH_HS) += hi4511.dtb \ + hi3716-dkb.dtb dtb-$(CONFIG_ARCH_INTEGRATOR) += integratorap.dtb \ integratorcp.dtb dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb diff --git a/arch/arm/boot/dts/hi3716-dkb.dts b/arch/arm/boot/dts/hi3716-dkb.dts new file mode 100644 index 000000000000..91beec5f236f --- /dev/null +++ b/arch/arm/boot/dts/hi3716-dkb.dts @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013 Linaro Ltd. + * Copyright (c) 2013 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * publishhed by the Free Software Foundation. + */ + +/dts-v1/; +/include/ "hi3716.dtsi" + +/ { + model = "Hisilicon Hi3716 Development Board"; + compatible = "hisilicon,hi3716"; + + chosen { + bootargs = "console=ttyAMA0,115200"; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + compatible = "arm,cortex-a9"; + device_type = "cpu"; + reg = <0>; + next-level-cache = <&l2>; + }; + + cpu@1 { + compatible = "arm,cortex-a9"; + device_type = "cpu"; + reg = <1>; + next-level-cache = <&l2>; + }; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x80000000>; + }; + + soc { + amba { + timer0: timer@f8002000 { + status = "okay"; + }; + + uart0: uart@f8b00000 { + status = "okay"; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/hi3716.dtsi b/arch/arm/boot/dts/hi3716.dtsi new file mode 100644 index 000000000000..5eea43c055f5 --- /dev/null +++ b/arch/arm/boot/dts/hi3716.dtsi @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2013 Linaro Ltd. + * Copyright (c) 2013 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * publishhed by the Free Software Foundation. + */ + +/include/ "skeleton.dtsi" + +/ { + aliases { + serial0 = &uart0; + }; + + gic: interrupt-controller@fc001000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + /* gic dist base, gic cpu base */ + reg = <0xf8a01000 0x1000>, <0xf8a00100 0x100>; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + device_type = "soc"; + interrupt-parent = <&gic>; + ranges; + + amba { + #address-cells = <1>; + #size-cells = <1>; + compatible = "arm,amba-bus"; + ranges; + + timer0: timer@f8002000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0xf8002000 0x1000>; + /* timer00 & timer01 */ + interrupts = <0 24 4>; + clocks = <&osc24m>; + status = "disabled"; + }; + + timer1: timer@f8a29000 { + /* + * Only used in NORMAL state, not available ins + * SLOW or DOZE state. + * The rate is fixed in 24MHz. + */ + compatible = "arm,sp804", "arm,primecell"; + reg = <0xf8a29000 0x1000>; + /* timer10 & timer11 */ + interrupts = <0 25 4>; + clocks = <&osc24m>; + status = "disabled"; + }; + + timer2: timer@f8a2a000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0xf8a2a000 0x1000>; + /* timer20 & timer21 */ + interrupts = <0 26 4>; + clocks = <&osc24m>; + status = "disabled"; + }; + + timer3: timer@f8a2b000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0xf8a2b000 0x1000>; + /* timer30 & timer31 */ + interrupts = <0 27 4>; + clocks = <&osc24m>; + status = "disabled"; + }; + + timer4: timer@f8a81000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0xf8a81000 0x1000>; + /* timer30 & timer31 */ + interrupts = <0 28 4>; + clocks = <&osc24m>; + status = "disabled"; + }; + + uart0: uart@f8b00000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0xf8b00000 0x1000>; + interrupts = <0 49 4>; + clocks = <&bpll_fout0_div 1>; + clock-names = "apb_pclk"; + status = "disabled"; + }; + + uart1: uart@f8006000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0xf8006000 0x1000>; + interrupts = <0 50 4>; + clocks = <&bpll_fout0_div 1>; + clock-names = "apb_pclk"; + status = "disabled"; + }; + + uart2: uart@f8b02000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0xf8b02000 0x1000>; + interrupts = <0 51 4>; + clocks = <&bpll_fout0_div 1>; + clock-names = "apb_pclk"; + status = "disabled"; + }; + + uart3: uart@f8b03000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0xf8b03000 0x1000>; + interrupts = <0 52 4>; + clocks = <&bpll_fout0_div 1>; + clock-names = "apb_pclk"; + status = "disabled"; + }; + + uart4: uart@f8b04000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0xf8b04000 0x1000>; + interrupts = <0 53 4>; + clocks = <&bpll_fout0_div 1>; + clock-names = "apb_pclk"; + status = "disabled"; + }; + }; + + clocks { + #address-cells = <1>; + #size-cells = <0>; + + osc24m: osc { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "osc24mhz"; + }; + + bpll: bpll { + compatible = "hisilicon,hi3716-fixed-pll"; + #clock-cells = <1>; + clocks = <&osc24m>; + clock-frequency = <1200000000>, + <600000000>, + <300000000>, + <200000000>, + <150000000>; + clock-output-names = "bpll_fout0", + "bpll_fout1", + "bpll_fout2", + "bpll_fout3", + "bpll_fout4"; + }; + + bpll_fout0_div: bpll_fout0_div {/* 1200Mhz */ + compatible = "hisilicon,hi3716-fixed-divider"; + #clock-cells = <1>; + clocks = <&bpll 0>; + div-table = <3 14 25 50>; + clock-output-names = "fout0_400m", "fout0_86m", + "fout0_48m", "fout0_24m"; + }; + + bpll_fout1_div: bpll_fout1_div { + compatible = "hisilicon,hi3716-fixed-divider"; + #clock-cells = <0>; + clocks = <&bpll 1>; + div-table = <10>; + clock-output-names = "fout1_60m"; + }; + + bpll_fout2_div: bpll_fout2_div { + compatible = "hisilicon,hi3716-fixed-divider"; + #clock-cells = <0>; + clocks = <&bpll 2>; + div-table = <4>; + clock-output-names = "fout2_75m"; + }; + + bpll_fout3_div: bpll_fout3_div { + compatible = "hisilicon,hi3716-fixed-divider"; + #clock-cells = <1>; + clocks = <&bpll 3>; + div-table = <2 4 5 8>; + clock-output-names = "fout3_100m", "fout3_50m", + "fout3_40m", "fout3_25m"; + }; + + clk_sfc_mux: clk_sfc_mux { + compatible = "hisilicon,hi3716-clk-mux"; + #clock-cells = <0>; + /* clks: 24M 75M 100M 150M 200M */ + clocks = <&osc24m>, <&bpll_fout2_div>, + <&bpll_fout3_div 0>, <&bpll 4>, <&bpll 3>; + + /* offset mux_shift mux_width */ + mux-reg = <0x5c 8 3>; + /* mux reg value to choose clks */ + mux-table = <0 7 6 4 5>; + + clock-output-names = "sfc_mux"; + }; + + clk_sfc: clk_sfc { + compatible = "hisilicon,hi3716-clk-gate"; + #clock-cells = <0>; + clocks = <&clk_sfc_mux>; + + /* offset, enable, reset */ + gate-reg = <0x5c 0 4>; + + clock-output-names = "sfc"; + }; + }; + + local_timer@f8a00600 { + compatible = "arm,cortex-a9-twd-timer"; + reg = <0xf8a00600 0x20>; + interrupts = <1 13 0xf01>; + }; + + l2: l2-cache { + compatible = "arm,pl310-cache"; + reg = <0xf8a10000 0x100000>; + interrupts = <0 15 4>; + cache-unified; + cache-level = <2>; + hisilicon,l2cache-aux = <0x00050000 0xfff0ffff>; + }; + + sctrl@f8000000 { + compatible = "hisilicon,sctrl"; + reg = <0xf8000000 0x1000>; + smp_reg = <0xc0>; + reboot_reg = <0x4>; + }; + + clkbase@f8a22000 { + compatible = "hisilicon,clkbase"; + reg = <0xf8a22000 0x1000>; + }; + + cpuctrl@f8a22000 { + compatible = "hisilicon,cpuctrl"; + reg = <0xf8a22000 0x2000>; + }; + }; +}; diff --git a/arch/arm/mach-hs/hs-dt.c b/arch/arm/mach-hs/hs-dt.c index c3e0636a513e..774ace66cc22 100644 --- a/arch/arm/mach-hs/hs-dt.c +++ b/arch/arm/mach-hs/hs-dt.c @@ -66,6 +66,7 @@ static void __init hs_init(void) static const char *hs_compat[] __initdata = { "hisilicon,hi3620-hi4511", + "hisilicon,hi3716", NULL, }; -- cgit v1.2.3 From ae90e250147423c60915b9499b29358a4bdcbac5 Mon Sep 17 00:00:00 2001 From: Zhangfei Gao Date: Fri, 16 Aug 2013 11:38:12 +0800 Subject: clk: debugfs add clk_rate_fops with DEBUG clk_rate_fops is added to debug 1. set_rate (e.g. PLL) 2. Choose mux parent, since mux could choose parent accordingly when set_rate. Causion: set_rate can be called directly from user space Example: sfc_mux have two parents: 24M and 200M cat clk_summary clock enable_cnt prepare_cnt rate --------------------------------------------------------------------- osc24mhz 3 3 24000000 bpll_fout3 0 0 200000000 sfc_mux 0 0 200000000 sfc 0 0 200000000 cat osc24mhz/bpll/bpll_fout3/sfc_mux/sfc/clk_rate 200000000 echo 24000000 > osc24mhz/bpll/bpll_fout3/sfc_mux/sfc/clk_rate cat clk_summary clock enable_cnt prepare_cnt rate --------------------------------------------------------------------- osc24mhz 3 3 24000000 sfc_mux 0 0 24000000 sfc 0 0 24000000 bpll_fout3 0 0 200000000 cat osc24mhz/sfc_mux/sfc/clk_rate 24000000 Signed-off-by: Zhangfei Gao --- drivers/clk/clk.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 373cd545b969..6b582f730a05 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -226,6 +226,35 @@ static const struct file_operations clk_dump_fops = { .release = single_release, }; +#ifdef DEBUG +static int clk_rate_fops_get(void *data, u64 *rate) +{ + struct clk *clk = data; + + *rate = clk->rate; + + return 0; +}; + +static int clk_rate_fops_set(void *data, u64 rate) +{ + struct clk *clk = data; + int ret = 0; + + ret = clk_prepare_enable(clk); + if (ret) + goto out; + clk_set_rate(clk, rate); + clk_disable_unprepare(clk); + +out: + return ret; +}; + +DEFINE_SIMPLE_ATTRIBUTE(clk_rate_fops, clk_rate_fops_get, + clk_rate_fops_set, "%llu\n"); +#endif + /* caller must hold prepare_lock */ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry) { @@ -243,8 +272,13 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry) clk->dentry = d; +#ifdef DEBUG + d = debugfs_create_file("clk_rate", S_IWUSR | S_IRUGO, clk->dentry, + clk, &clk_rate_fops); +#else d = debugfs_create_u32("clk_rate", S_IRUGO, clk->dentry, (u32 *)&clk->rate); +#endif if (!d) goto err_out; -- cgit v1.2.3