[PATCHv6 22/45] CLK: TI: add interface clock support for OMAP3
From: Tero Kristo <hidden>
Date: 2013-08-29 13:16:14
Also in:
linux-arm-kernel, linux-omap
Subsystem:
arm port, common clk framework, omap clock framework support, omap2+ support, open firmware and flattened device tree bindings, the rest, ti clock driver · Maintainers:
Russell King, Michael Turquette, Stephen Boyd, Paul Walmsley, Aaro Koskinen, Andreas Kemnade, Kevin Hilman, Roger Quadros, Tony Lindgren, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Torvalds, Tero Kristo
OMAP3 has interface clocks in addition to functional clocks, which require special handling for the autoidle and idle status register offsets mainly. Signed-off-by: Tero Kristo <redacted> --- .../devicetree/bindings/clock/ti/interface.txt | 53 +++++++++ arch/arm/mach-omap2/clock.h | 6 - drivers/clk/ti/Makefile | 3 +- drivers/clk/ti/interface.c | 124 ++++++++++++++++++++ include/linux/clk/ti.h | 7 ++ 5 files changed, 186 insertions(+), 7 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/ti/interface.txt create mode 100644 drivers/clk/ti/interface.c
diff --git a/Documentation/devicetree/bindings/clock/ti/interface.txt b/Documentation/devicetree/bindings/clock/ti/interface.txt
new file mode 100644
index 0000000..297b3e3
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti/interface.txt@@ -0,0 +1,53 @@ +Binding for Texas Instruments interface clock. + +This binding uses the common clock binding[1]. This clock is +quite much similar to the basic gate-clock [2], however, +it supports a number of additional features, including +companion clock finding (match corresponding functional gate +clock) and hardware autoidle enable / disable. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt +[2] Documentation/devicetree/bindings/clock/gate-clock.txt + +Required properties: +- compatible : shall be one of: + "ti,omap3-interface-clock" - basic OMAP3 interface clock + "ti,omap3-no-wait-interface-clock" - interface clock which has no hardware + capability for waiting clock to be ready + "ti,omap3-hsotgusb-interface-clock" - interface clock with USB specific HW + handling + "ti,omap3-dss-interface-clock" - interface clock with DSS specific HW handling + "ti,omap3-ssi-interface-clock" - interface clock with SSI specific HW handling + "ti,am35xx-interface-clock" - interface clock with AM35xx specific HW handling +- #clock-cells : from common clock binding; shall be set to 0 +- clocks : link to phandle of parent clock +- reg : base address for the control register + +Optional properties: +- ti,enable-bit : bit shift for the bit enabling/disabling the clock + (default 0) + +Examples: + aes1_ick: aes1_ick@48004a14 { + #clock-cells = <0>; + compatible = "ti,omap3-interface-clock"; + clocks = <&security_l4_ick2>; + reg = <0x48004a14 0x4>; + ti,enable-bit = <3>; + }; + + cam_ick: cam_ick@48004f10 { + #clock-cells = <0>; + compatible = "ti,omap3-no-wait-interface-clock"; + clocks = <&l4_ick>; + reg = <0x48004f10 0x4>; + ti,enable-bit = <0>; + }; + + ssi_ick_3430es2: ssi_ick_3430es2@48004a10 { + #clock-cells = <0>; + compatible = "ti,omap3-ssi-interface-clock"; + clocks = <&ssi_l4_ick>; + reg = <0x48004a10 0x4>; + ti,enable-bit = <0>; + };
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 2e6cbeb..d1b227e 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h@@ -266,14 +266,8 @@ extern const struct clksel_rate gfx_l3_rates[]; extern const struct clksel_rate dsp_ick_rates[]; extern struct clk dummy_ck; -extern const struct clk_hw_omap_ops clkhwops_iclk_wait; -extern const struct clk_hw_omap_ops clkhwops_iclk; extern const struct clk_hw_omap_ops clkhwops_omap3430es2_ssi_wait; -extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait; -extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait; -extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait; extern const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait; -extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait; extern const struct clk_hw_omap_ops clkhwops_apll54; extern const struct clk_hw_omap_ops clkhwops_apll96; extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll;
diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile
index bdc632c..d681ae7 100644
--- a/drivers/clk/ti/Makefile
+++ b/drivers/clk/ti/Makefile@@ -1,5 +1,6 @@ ifneq ($(CONFIG_OF),) obj-y += clk.o dpll.o autoidle.o gate.o \ clockdomain.o apll.o clk-44xx.o \ - clk-54xx.o clk-7xx.o clk-33xx.o + clk-54xx.o clk-7xx.o clk-33xx.o \ + interface.o endif
diff --git a/drivers/clk/ti/interface.c b/drivers/clk/ti/interface.c
new file mode 100644
index 0000000..17e293f
--- /dev/null
+++ b/drivers/clk/ti/interface.c@@ -0,0 +1,124 @@ +/* + * OMAP interface clock support + * + * Copyright (C) 2013 Texas Instruments, Inc. + * + * Tero Kristo <t-kristo@ti.com> + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/clk-provider.h> +#include <linux/slab.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/clk/ti.h> + +static const struct clk_ops omap_interface_clk_ops = { + .init = &omap2_init_clk_clkdm, + .enable = &omap2_dflt_clk_enable, + .disable = &omap2_dflt_clk_disable, + .is_enabled = &omap2_dflt_clk_is_enabled, +}; + +void __init _of_omap_interface_clk_setup(struct device_node *node, + const struct clk_hw_omap_ops *ops) +{ + struct clk *clk; + struct clk_init_data init = { 0 }; + struct clk_hw_omap *clk_hw; + const char *clk_name = node->name; + const char *parent_name; + u32 val; + + clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); + if (!clk_hw) { + pr_err("%s: could not allocate clk_hw_omap\n", __func__); + return; + } + + clk_hw->hw.init = &init; + clk_hw->ops = ops; + clk_hw->enable_reg = of_iomap(node, 0); + + if (!of_property_read_u32(node, "ti,enable-bit", &val)) + clk_hw->enable_bit = val; + + of_property_read_string(node, "clock-output-names", &clk_name); + + init.name = clk_name; + init.ops = &omap_interface_clk_ops; + init.flags = 0; + + parent_name = of_clk_get_parent_name(node, 0); + if (!parent_name) { + pr_err("%s: %s must have a parent\n", __func__, clk_name); + goto cleanup; + } + + init.num_parents = 1; + init.parent_names = &parent_name; + + clk = clk_register(NULL, &clk_hw->hw); + + if (!IS_ERR(clk)) { + of_clk_add_provider(node, of_clk_src_simple_get, clk); + omap2_init_clk_hw_omap_clocks(clk); + return; + } + +cleanup: + kfree(clk_hw); +} + +static void __init of_omap_interface_clk_setup(struct device_node *node) +{ + _of_omap_interface_clk_setup(node, &clkhwops_iclk_wait); +} +CLK_OF_DECLARE(omap_interface_clk, "ti,omap3-interface-clock", + of_omap_interface_clk_setup); + +static void __init of_omap_no_wait_interface_clk_setup(struct device_node *node) +{ + _of_omap_interface_clk_setup(node, &clkhwops_iclk); +} +CLK_OF_DECLARE(omap_no_wait_interface_clk, "ti,omap3-no-wait-interface-clock", + of_omap_no_wait_interface_clk_setup); + +static void __init +of_omap_hsotgusb_interface_clk_setup(struct device_node *node) +{ + _of_omap_interface_clk_setup(node, + &clkhwops_omap3430es2_iclk_hsotgusb_wait); +} +CLK_OF_DECLARE(omap_hsotgusb_interface_clk, "ti,omap3-hsotgusb-interface-clock", + of_omap_hsotgusb_interface_clk_setup); + +static void __init of_omap_dss_interface_clk_setup(struct device_node *node) +{ + _of_omap_interface_clk_setup(node, + &clkhwops_omap3430es2_iclk_dss_usbhost_wait); +} +CLK_OF_DECLARE(omap_dss_interface_clk, "ti,omap3-dss-interface-clock", + of_omap_dss_interface_clk_setup); + +static void __init of_omap_ssi_interface_clk_setup(struct device_node *node) +{ + _of_omap_interface_clk_setup(node, &clkhwops_omap3430es2_iclk_ssi_wait); +} +CLK_OF_DECLARE(omap_ssi_interface_clk, "ti,omap3-ssi-interface-clock", + of_omap_ssi_interface_clk_setup); + +static void __init of_omap_am35xx_interface_clk_setup(struct device_node *node) +{ + _of_omap_interface_clk_setup(node, &clkhwops_am35xx_ipss_wait); +} +CLK_OF_DECLARE(omap_am35xx_interface_clk, "ti,am35xx-interface-clock", + of_omap_am35xx_interface_clk_setup);
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 9039b24..1e189af 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h@@ -231,5 +231,12 @@ extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx; extern const struct clk_hw_omap_ops clkhwops_wait; extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait; extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait; +extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait; + +extern const struct clk_hw_omap_ops clkhwops_iclk_wait; +extern const struct clk_hw_omap_ops clkhwops_iclk; +extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait; +extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait; +extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait; #endif
--
1.7.9.5