aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/ti
diff options
context:
space:
mode:
authorTero Kristo <t-kristo@ti.com>2014-09-12 08:01:57 -0400
committerTero Kristo <t-kristo@ti.com>2014-09-29 04:51:13 -0400
commitc08ee14cc6634457948bc5e26584697208baa02a (patch)
tree67c01eedd8ea2c125ea462653e3d4ba8969f24c4 /drivers/clk/ti
parent7d1311b93e58ed55f3a31cc8f94c4b8fe988a2b9 (diff)
clk: ti: change clock init to use generic of_clk_init
Previously, the TI clock driver initialized all the clocks hierarchically under each separate clock provider node. Now, each clock that requires IO access will instead check their parent node to find out which IO range to use. This patch allows the TI clock driver to use a few new features provided by the generic of_clk_init, and also allows registration of clock nodes outside the clock hierarchy (for example, any external clocks.) Signed-off-by: Tero Kristo <t-kristo@ti.com> Cc: Mike Turquette <mturquette@linaro.org> Cc: Paul Walmsley <paul@pwsan.com> Cc: Tony Lindgren <tony@atomide.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Peter Ujfalusi <peter.ujfalusi@ti.com> Cc: Jyri Sarha <jsarha@ti.com> Cc: Stefan Assmann <sassmann@kpanic.de> Acked-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'drivers/clk/ti')
-rw-r--r--drivers/clk/ti/clk.c68
1 files changed, 43 insertions, 25 deletions
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index b1a6f7144f3f..337abe5909e1 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -25,8 +25,8 @@
25#undef pr_fmt 25#undef pr_fmt
26#define pr_fmt(fmt) "%s: " fmt, __func__ 26#define pr_fmt(fmt) "%s: " fmt, __func__
27 27
28static int ti_dt_clk_memmap_index;
29struct ti_clk_ll_ops *ti_clk_ll_ops; 28struct ti_clk_ll_ops *ti_clk_ll_ops;
29static struct device_node *clocks_node_ptr[CLK_MAX_MEMMAPS];
30 30
31/** 31/**
32 * ti_dt_clocks_register - register DT alias clocks during boot 32 * ti_dt_clocks_register - register DT alias clocks during boot
@@ -108,9 +108,21 @@ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
108 struct clk_omap_reg *reg; 108 struct clk_omap_reg *reg;
109 u32 val; 109 u32 val;
110 u32 tmp; 110 u32 tmp;
111 int i;
111 112
112 reg = (struct clk_omap_reg *)&tmp; 113 reg = (struct clk_omap_reg *)&tmp;
113 reg->index = ti_dt_clk_memmap_index; 114
115 for (i = 0; i < CLK_MAX_MEMMAPS; i++) {
116 if (clocks_node_ptr[i] == node->parent)
117 break;
118 }
119
120 if (i == CLK_MAX_MEMMAPS) {
121 pr_err("clk-provider not found for %s!\n", node->name);
122 return NULL;
123 }
124
125 reg->index = i;
114 126
115 if (of_property_read_u32_index(node, "reg", index, &val)) { 127 if (of_property_read_u32_index(node, "reg", index, &val)) {
116 pr_err("%s must have reg[%d]!\n", node->name, index); 128 pr_err("%s must have reg[%d]!\n", node->name, index);
@@ -127,20 +139,14 @@ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
127 * @parent: master node 139 * @parent: master node
128 * @index: internal index for clk_reg_ops 140 * @index: internal index for clk_reg_ops
129 * 141 *
130 * Initializes a master clock IP block and its child clock nodes. 142 * Initializes a master clock IP block. This basically sets up the
131 * Regmap is provided for accessing the register space for the 143 * mapping from clocks node to the memory map index. All the clocks
132 * IP block and all the clocks under it. 144 * are then initialized through the common of_clk_init call, and the
145 * clocks will access their memory maps based on the node layout.
133 */ 146 */
134void ti_dt_clk_init_provider(struct device_node *parent, int index) 147void ti_dt_clk_init_provider(struct device_node *parent, int index)
135{ 148{
136 const struct of_device_id *match;
137 struct device_node *np;
138 struct device_node *clocks; 149 struct device_node *clocks;
139 of_clk_init_cb_t clk_init_cb;
140 struct clk_init_item *retry;
141 struct clk_init_item *tmp;
142
143 ti_dt_clk_memmap_index = index;
144 150
145 /* get clocks for this parent */ 151 /* get clocks for this parent */
146 clocks = of_get_child_by_name(parent, "clocks"); 152 clocks = of_get_child_by_name(parent, "clocks");
@@ -149,19 +155,31 @@ void ti_dt_clk_init_provider(struct device_node *parent, int index)
149 return; 155 return;
150 } 156 }
151 157
152 for_each_child_of_node(clocks, np) { 158 /* add clocks node info */
153 match = of_match_node(&__clk_of_table, np); 159 clocks_node_ptr[index] = clocks;
154 if (!match) 160}
155 continue;
156 clk_init_cb = (of_clk_init_cb_t)match->data;
157 pr_debug("%s: initializing: %s\n", __func__, np->name);
158 clk_init_cb(np);
159 }
160 161
161 list_for_each_entry_safe(retry, tmp, &retry_list, link) { 162/**
162 pr_debug("retry-init: %s\n", retry->node->name); 163 * ti_dt_clk_init_retry_clks - init clocks from the retry list
163 retry->func(retry->hw, retry->node); 164 *
164 list_del(&retry->link); 165 * Initializes any clocks that have failed to initialize before,
165 kfree(retry); 166 * reasons being missing parent node(s) during earlier init. This
167 * typically happens only for DPLLs which need to have both of their
168 * parent clocks ready during init.
169 */
170void ti_dt_clk_init_retry_clks(void)
171{
172 struct clk_init_item *retry;
173 struct clk_init_item *tmp;
174 int retries = 5;
175
176 while (!list_empty(&retry_list) && retries) {
177 list_for_each_entry_safe(retry, tmp, &retry_list, link) {
178 pr_debug("retry-init: %s\n", retry->node->name);
179 retry->func(retry->hw, retry->node);
180 list_del(&retry->link);
181 kfree(retry);
182 }
183 retries--;
166 } 184 }
167} 185}