aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Murphy2014-09-02 12:42:20 -0500
committerDan Murphy2014-09-02 12:42:20 -0500
commit2d41bcbd6e94ac20cee375807b700074275a2d59 (patch)
tree4dbc4cd104d99ae896b3774dc37a422f94da196c
parent40f44c741f16d770209753f685a94674e07bd7b3 (diff)
parent2d16cd0976d6b1721e7e432a8f7f6cf986a663bc (diff)
downloadkernel-video-ti-linux-3.14.y-mm.tar.gz
kernel-video-ti-linux-3.14.y-mm.tar.xz
kernel-video-ti-linux-3.14.y-mm.zip
Merge branch 'platform-ti-linux-3.14.y' of git://git.ti.com/~rrnayak/ti-linux-kernel/platform-linux-feature-tree into ti-linux-3.14.yti-linux-3.14.y-mmti-linux-3.14.y
TI-Feature: platform_base TI-Tree: git://git.ti.com/~rrnayak/ti-linux-kernel/platform-linux-feature-tree.git TI-Branch: platform-ti-linux-3.14.y * 'platform-ti-linux-3.14.y' of git://git.ti.com/~rrnayak/ti-linux-kernel/platform-linux-feature-tree: clk: ti: add "ti,gpio-gate-clock" controlled clock ARM: DTS: dra72-evm: Rename mmc2_3v3 regulator to the board level power name ARM: DTS: dra7-evm: Rename mmc2_3v3 regulator to the board level power name clk: ti: set CLK_SET_RATE_NO_REPARENT for ti,mux-clock clk: ti: fix clk_init retry logic with generic of_clk_init use Conflicts: arch/arm/boot/dts/dra7-evm.dts arch/arm/boot/dts/dra72-evm.dts Signed-off-by: Dan Murphy <DMurphy@ti.com>
-rw-r--r--Documentation/devicetree/bindings/clock/ti/gpio-gate-clock.txt21
-rw-r--r--arch/arm/boot/dts/dra7-evm.dts6
-rw-r--r--arch/arm/boot/dts/dra72-evm.dts6
-rw-r--r--arch/arm/mach-omap2/io.c2
-rw-r--r--drivers/clk/ti/Makefile2
-rw-r--r--drivers/clk/ti/clk.c22
-rw-r--r--drivers/clk/ti/gpio.c202
-rw-r--r--drivers/clk/ti/mux.c2
-rw-r--r--include/linux/clk/ti.h1
9 files changed, 249 insertions, 15 deletions
diff --git a/Documentation/devicetree/bindings/clock/ti/gpio-gate-clock.txt b/Documentation/devicetree/bindings/clock/ti/gpio-gate-clock.txt
new file mode 100644
index 00000000000..6156f827f72
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti/gpio-gate-clock.txt
@@ -0,0 +1,21 @@
1Binding for simple gpio controlled clock.
2
3This binding uses the common clock binding[1].
4
5[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
6
7Required properties:
8- compatible : shall be "ti,gpio-gate-clock".
9- #clock-cells : from common clock binding; shall be set to 0.
10- enable-gpios : GPIO reference for enabling and disabling the clock.
11
12Optional properties:
13- clocks: Maximum of one parent clock is supported.
14
15Example:
16 clock {
17 compatible = "ti,gpio-gate-clock";
18 clocks = <&parentclk>;
19 #clock-cells = <0>;
20 enable-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>;
21 };
diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts
index 911b4f4f0f0..adf1cac7773 100644
--- a/arch/arm/boot/dts/dra7-evm.dts
+++ b/arch/arm/boot/dts/dra7-evm.dts
@@ -54,9 +54,9 @@
54 }; 54 };
55 }; 55 };
56 56
57 mmc2_3v3: fixedregulator-mmc2 { 57 evm_3v3_sw: fixedregulator-evm_3v3_sw {
58 compatible = "regulator-fixed"; 58 compatible = "regulator-fixed";
59 regulator-name = "mmc2_3v3"; 59 regulator-name = "evm_3v3_sw";
60 regulator-min-microvolt = <3300000>; 60 regulator-min-microvolt = <3300000>;
61 regulator-max-microvolt = <3300000>; 61 regulator-max-microvolt = <3300000>;
62 }; 62 };
@@ -683,7 +683,7 @@
683 683
684&mmc2 { 684&mmc2 {
685 status = "okay"; 685 status = "okay";
686 vmmc-supply = <&mmc2_3v3>; 686 vmmc-supply = <&evm_3v3_sw>;
687 bus-width = <8>; 687 bus-width = <8>;
688}; 688};
689 689
diff --git a/arch/arm/boot/dts/dra72-evm.dts b/arch/arm/boot/dts/dra72-evm.dts
index ba595b4a19a..22fc402ea6c 100644
--- a/arch/arm/boot/dts/dra72-evm.dts
+++ b/arch/arm/boot/dts/dra72-evm.dts
@@ -93,9 +93,9 @@
93 }; 93 };
94 }; 94 };
95 95
96 mmc2_3v3: fixedregulator-mmc2 { 96 evm_3v3: fixedregulator-evm_3v3 {
97 compatible = "regulator-fixed"; 97 compatible = "regulator-fixed";
98 regulator-name = "mmc2_3v3"; 98 regulator-name = "evm_3v3";
99 regulator-min-microvolt = <3300000>; 99 regulator-min-microvolt = <3300000>;
100 regulator-max-microvolt = <3300000>; 100 regulator-max-microvolt = <3300000>;
101 }; 101 };
@@ -458,7 +458,7 @@
458&mmc2 { 458&mmc2 {
459 /* Using default configured pins */ 459 /* Using default configured pins */
460 status = "okay"; 460 status = "okay";
461 vmmc-supply = <&mmc2_3v3>; 461 vmmc-supply = <&evm_3v3>;
462 bus-width = <8>; 462 bus-width = <8>;
463 ti,non-removable; 463 ti,non-removable;
464}; 464};
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 1d420ff275e..1f4d5fc99c2 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -750,6 +750,8 @@ int __init omap_clk_init(void)
750 750
751 of_clk_init(NULL); 751 of_clk_init(NULL);
752 752
753 ti_dt_clk_init_retry();
754
753 ti_dt_clockdomains_setup(); 755 ti_dt_clockdomains_setup();
754 756
755 ret = omap_clk_soc_init(); 757 ret = omap_clk_soc_init();
diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile
index ed4d0aaf891..88074d330c8 100644
--- a/drivers/clk/ti/Makefile
+++ b/drivers/clk/ti/Makefile
@@ -1,7 +1,7 @@
1ifneq ($(CONFIG_OF),) 1ifneq ($(CONFIG_OF),)
2obj-y += clk.o autoidle.o clockdomain.o 2obj-y += clk.o autoidle.o clockdomain.o
3clk-common = dpll.o composite.o divider.o gate.o \ 3clk-common = dpll.o composite.o divider.o gate.o \
4 fixed-factor.o mux.o apll.o 4 fixed-factor.o mux.o apll.o gpio.o
5obj-$(CONFIG_SOC_AM33XX) += $(clk-common) clk-33xx.o 5obj-$(CONFIG_SOC_AM33XX) += $(clk-common) clk-33xx.o
6obj-$(CONFIG_ARCH_OMAP2) += $(clk-common) interface.o clk-2xxx.o 6obj-$(CONFIG_ARCH_OMAP2) += $(clk-common) interface.o clk-2xxx.o
7obj-$(CONFIG_ARCH_OMAP3) += $(clk-common) interface.o clk-3xxx.o 7obj-$(CONFIG_ARCH_OMAP3) += $(clk-common) interface.o clk-3xxx.o
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index f7201d06e5f..94e78936d95 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -146,8 +146,6 @@ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
146void ti_dt_clk_init_provider(struct device_node *parent, int index) 146void ti_dt_clk_init_provider(struct device_node *parent, int index)
147{ 147{
148 struct device_node *clocks; 148 struct device_node *clocks;
149 struct clk_init_item *retry;
150 struct clk_init_item *tmp;
151 149
152 /* get clocks for this parent */ 150 /* get clocks for this parent */
153 clocks = of_get_child_by_name(parent, "clocks"); 151 clocks = of_get_child_by_name(parent, "clocks");
@@ -158,11 +156,21 @@ void ti_dt_clk_init_provider(struct device_node *parent, int index)
158 156
159 /* add clocks node info */ 157 /* add clocks node info */
160 clocks_node_ptr[index] = clocks; 158 clocks_node_ptr[index] = clocks;
159}
161 160
162 list_for_each_entry_safe(retry, tmp, &retry_list, link) { 161void ti_dt_clk_init_retry(void)
163 pr_debug("retry-init: %s\n", retry->node->name); 162{
164 retry->func(retry->hw, retry->node); 163 struct clk_init_item *retry;
165 list_del(&retry->link); 164 struct clk_init_item *tmp;
166 kfree(retry); 165 int retries = 5;
166
167 while (!list_empty(&retry_list) && retries) {
168 list_for_each_entry_safe(retry, tmp, &retry_list, link) {
169 pr_debug("retry-init: %s\n", retry->node->name);
170 retry->func(retry->hw, retry->node);
171 list_del(&retry->link);
172 kfree(retry);
173 }
174 retries--;
167 } 175 }
168} 176}
diff --git a/drivers/clk/ti/gpio.c b/drivers/clk/ti/gpio.c
new file mode 100644
index 00000000000..b9738013bd4
--- /dev/null
+++ b/drivers/clk/ti/gpio.c
@@ -0,0 +1,202 @@
1/*
2 * Copyright (C) 2012 - 2014 Texas Instruments Incorporated - http://www.ti.com
3 * Author: Jyri Sarha <jsarha@ti.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Gpio controlled clock implementation
10 */
11
12#include <linux/clk-provider.h>
13#include <linux/module.h>
14#include <linux/slab.h>
15#include <linux/gpio.h>
16#include <linux/of_gpio.h>
17#include <linux/err.h>
18#include <linux/device.h>
19
20struct clk_gpio {
21 struct clk_hw hw;
22 struct gpio_desc *gpiod;
23};
24
25/**
26 * DOC: basic gpio controlled clock which can be enabled and disabled
27 * with gpio output
28 * Traits of this clock:
29 * prepare - clk_(un)prepare only ensures parent is (un)prepared
30 * enable - clk_enable and clk_disable are functional & control gpio
31 * rate - inherits rate from parent. No clk_set_rate support
32 * parent - fixed parent. No clk_set_parent support
33 */
34
35#define to_clk_gpio(_hw) container_of(_hw, struct clk_gpio, hw)
36
37static int clk_gpio_enable(struct clk_hw *hw)
38{
39 struct clk_gpio *clk = to_clk_gpio(hw);
40
41 gpiod_set_value(clk->gpiod, 1);
42
43 return 0;
44}
45
46static void clk_gpio_disable(struct clk_hw *hw)
47{
48 struct clk_gpio *clk = to_clk_gpio(hw);
49
50 gpiod_set_value(clk->gpiod, 0);
51}
52
53static int clk_gpio_is_enabled(struct clk_hw *hw)
54{
55 struct clk_gpio *clk = to_clk_gpio(hw);
56
57 return gpiod_get_value(clk->gpiod);
58}
59
60static const struct clk_ops clk_gpio_ops = {
61 .enable = clk_gpio_enable,
62 .disable = clk_gpio_disable,
63 .is_enabled = clk_gpio_is_enabled,
64};
65
66/**
67 * clk_register_gpio - register a gpip clock with the clock framework
68 * @dev: device that is registering this clock
69 * @name: name of this clock
70 * @parent_name: name of this clock's parent
71 * @gpiod: gpio descriptor to control this clock
72 */
73static struct clk *clk_register_gpio(struct device *dev, const char *name,
74 const char *parent_name, struct gpio_desc *gpiod,
75 unsigned long flags)
76{
77 struct clk_gpio *clk_gpio = NULL;
78 struct clk *clk = ERR_PTR(-EINVAL);
79 struct clk_init_data init = { NULL };
80 unsigned long gpio_flags;
81 int err;
82
83 if (gpiod_is_active_low(gpiod))
84 gpio_flags = GPIOF_OUT_INIT_HIGH;
85 else
86 gpio_flags = GPIOF_OUT_INIT_LOW;
87
88 if (dev)
89 err = devm_gpio_request_one(dev, desc_to_gpio(gpiod),
90 gpio_flags, name);
91 else
92 err = gpio_request_one(desc_to_gpio(gpiod), gpio_flags, name);
93
94 if (err) {
95 pr_err("%s: %s: Error requesting clock control gpio %u\n",
96 __func__, name, desc_to_gpio(gpiod));
97 return ERR_PTR(err);
98 }
99
100 if (dev)
101 clk_gpio = devm_kzalloc(dev, sizeof(struct clk_gpio),
102 GFP_KERNEL);
103 else
104 clk_gpio = kzalloc(sizeof(struct clk_gpio), GFP_KERNEL);
105
106 if (!clk_gpio)
107 goto clk_register_gpio_err;
108
109 init.name = name;
110 init.ops = &clk_gpio_ops;
111 init.flags = flags | CLK_IS_BASIC;
112 init.parent_names = (parent_name ? &parent_name : NULL);
113 init.num_parents = (parent_name ? 1 : 0);
114
115 clk_gpio->gpiod = gpiod;
116 clk_gpio->hw.init = &init;
117
118 clk = clk_register(dev, &clk_gpio->hw);
119
120 if (!IS_ERR(clk))
121 return clk;
122
123 if (!dev)
124 kfree(clk_gpio);
125
126clk_register_gpio_err:
127 gpiod_put(gpiod);
128
129 return clk;
130}
131
132/**
133 * The clk_register_gpio has to be delayed, because the EPROBE_DEFER
134 * can not be handled properly at of_clk_init() call time.
135 */
136
137struct clk_gpio_delayed_register_data {
138 struct device_node *node;
139 struct mutex lock;
140 struct clk *clk;
141};
142
143static
144struct clk *of_clk_gpio_delayed_register_get(struct of_phandle_args *clkspec,
145 void *_data)
146{
147 struct clk_gpio_delayed_register_data *data = _data;
148 struct clk *clk;
149 const char *clk_name = data->node->name;
150 const char *parent_name;
151 struct gpio_desc *gpiod;
152 int gpio;
153
154 mutex_lock(&data->lock);
155
156 if (data->clk) {
157 mutex_unlock(&data->lock);
158 return data->clk;
159 }
160
161 gpio = of_get_named_gpio_flags(data->node, "enable-gpios", 0, NULL);
162 if (gpio < 0) {
163 mutex_unlock(&data->lock);
164 if (gpio != -EPROBE_DEFER)
165 pr_err("%s: %s: Can't get 'enable-gpios' DT property\n",
166 __func__, clk_name);
167 return ERR_PTR(gpio);
168 }
169 gpiod = gpio_to_desc(gpio);
170
171 parent_name = of_clk_get_parent_name(data->node, 0);
172
173 clk = clk_register_gpio(NULL, clk_name, parent_name, gpiod, 0);
174 if (IS_ERR(clk)) {
175 mutex_unlock(&data->lock);
176 return clk;
177 }
178
179 data->clk = clk;
180 mutex_unlock(&data->lock);
181
182 return clk;
183}
184
185/**
186 * of_gpio_clk_setup() - Setup function for gpio controlled clock
187 */
188static void __init of_gpio_clk_setup(struct device_node *node)
189{
190 struct clk_gpio_delayed_register_data *data;
191
192 data = kzalloc(sizeof(struct clk_gpio_delayed_register_data),
193 GFP_KERNEL);
194 if (!data)
195 return;
196
197 data->node = node;
198 mutex_init(&data->lock);
199
200 of_clk_add_provider(node, of_clk_gpio_delayed_register_get, data);
201}
202CLK_OF_DECLARE(gpio_clk, "ti,gpio-gate-clock", of_gpio_clk_setup);
diff --git a/drivers/clk/ti/mux.c b/drivers/clk/ti/mux.c
index 4348c71a92f..4525edd17e9 100644
--- a/drivers/clk/ti/mux.c
+++ b/drivers/clk/ti/mux.c
@@ -177,7 +177,7 @@ static void of_mux_clk_setup(struct device_node *node)
177 u8 clk_mux_flags = 0; 177 u8 clk_mux_flags = 0;
178 u32 mask = 0; 178 u32 mask = 0;
179 u32 shift = 0; 179 u32 shift = 0;
180 u32 flags = 0; 180 u32 flags = CLK_SET_RATE_NO_REPARENT;
181 181
182 num_parents = of_clk_get_parent_count(node); 182 num_parents = of_clk_get_parent_count(node);
183 if (num_parents < 2) { 183 if (num_parents < 2) {
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 7eaf665a2ba..1bd1fb5532a 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -293,6 +293,7 @@ void omap2xxx_clkt_vps_init(void);
293void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index); 293void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index);
294void ti_dt_clocks_register(struct ti_dt_clk *oclks); 294void ti_dt_clocks_register(struct ti_dt_clk *oclks);
295void ti_dt_clk_init_provider(struct device_node *np, int index); 295void ti_dt_clk_init_provider(struct device_node *np, int index);
296void ti_dt_clk_init_retry(void);
296void ti_dt_clockdomains_setup(void); 297void ti_dt_clockdomains_setup(void);
297int ti_clk_retry_init(struct device_node *node, struct clk_hw *hw, 298int ti_clk_retry_init(struct device_node *node, struct clk_hw *hw,
298 ti_of_clk_init_cb_t func); 299 ti_of_clk_init_cb_t func);