aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTero Kristo <t-kristo@ti.com>2015-01-29 15:24:28 -0500
committerMichael Turquette <mturquette@linaro.org>2015-01-30 13:55:09 -0500
commited405a2350646a940966f471ae705fa2d81eee65 (patch)
treee35f9ce7fa7d0bb91f90580093a2b0e488d6c4a7
parentd96f774b25386a7a71c799bbf55b69c27129e454 (diff)
clk: ti: dpll: add support for legacy DPLL init
Legacy clock data is initialized slightly differently compared to DT clocks, thus add support for this. Signed-off-by: Tero Kristo <t-kristo@ti.com> Acked-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Michael Turquette <mturquette@linaro.org>
-rw-r--r--drivers/clk/ti/clk.c3
-rw-r--r--drivers/clk/ti/clock.h2
-rw-r--r--drivers/clk/ti/dpll.c119
3 files changed, 113 insertions, 11 deletions
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index a0475e23881d..f41a7576a3ff 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -228,6 +228,9 @@ struct clk __init *ti_clk_register_clk(struct ti_clk *setup)
228 case TI_CLK_GATE: 228 case TI_CLK_GATE:
229 clk = ti_clk_register_gate(setup); 229 clk = ti_clk_register_gate(setup);
230 break; 230 break;
231 case TI_CLK_DPLL:
232 clk = ti_clk_register_dpll(setup);
233 break;
231 default: 234 default:
232 pr_err("bad type for %s!\n", setup->name); 235 pr_err("bad type for %s!\n", setup->name);
233 clk = ERR_PTR(-EINVAL); 236 clk = ERR_PTR(-EINVAL);
diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h
index fe709412514c..578b73b2edf1 100644
--- a/drivers/clk/ti/clock.h
+++ b/drivers/clk/ti/clock.h
@@ -148,6 +148,7 @@ struct ti_clk_dpll {
148 u32 sddiv_mask; 148 u32 sddiv_mask;
149 u16 max_multiplier; 149 u16 max_multiplier;
150 u16 max_divider; 150 u16 max_divider;
151 u8 min_divider;
151 u8 auto_recal_bit; 152 u8 auto_recal_bit;
152 u8 recal_en_bit; 153 u8 recal_en_bit;
153 u8 recal_st_bit; 154 u8 recal_st_bit;
@@ -157,6 +158,7 @@ struct clk *ti_clk_register_gate(struct ti_clk *setup);
157struct clk *ti_clk_register_interface(struct ti_clk *setup); 158struct clk *ti_clk_register_interface(struct ti_clk *setup);
158struct clk *ti_clk_register_mux(struct ti_clk *setup); 159struct clk *ti_clk_register_mux(struct ti_clk *setup);
159struct clk *ti_clk_register_divider(struct ti_clk *setup); 160struct clk *ti_clk_register_divider(struct ti_clk *setup);
161struct clk *ti_clk_register_dpll(struct ti_clk *setup);
160 162
161struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup); 163struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup);
162struct clk_hw *ti_clk_build_component_gate(struct ti_clk_gate *setup); 164struct clk_hw *ti_clk_build_component_gate(struct ti_clk_gate *setup);
diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c
index 85ac0dd501de..47ebff772b13 100644
--- a/drivers/clk/ti/dpll.c
+++ b/drivers/clk/ti/dpll.c
@@ -21,6 +21,7 @@
21#include <linux/of.h> 21#include <linux/of.h>
22#include <linux/of_address.h> 22#include <linux/of_address.h>
23#include <linux/clk/ti.h> 23#include <linux/clk/ti.h>
24#include "clock.h"
24 25
25#undef pr_fmt 26#undef pr_fmt
26#define pr_fmt(fmt) "%s: " fmt, __func__ 27#define pr_fmt(fmt) "%s: " fmt, __func__
@@ -130,7 +131,7 @@ static const struct clk_ops dpll_x2_ck_ops = {
130}; 131};
131 132
132/** 133/**
133 * ti_clk_register_dpll - low level registration of a DPLL clock 134 * _register_dpll - low level registration of a DPLL clock
134 * @hw: hardware clock definition for the clock 135 * @hw: hardware clock definition for the clock
135 * @node: device node for the clock 136 * @node: device node for the clock
136 * 137 *
@@ -138,8 +139,8 @@ static const struct clk_ops dpll_x2_ck_ops = {
138 * clk-bypass is missing), the clock is added to retry list and 139 * clk-bypass is missing), the clock is added to retry list and
139 * the initialization is retried on later stage. 140 * the initialization is retried on later stage.
140 */ 141 */
141static void __init ti_clk_register_dpll(struct clk_hw *hw, 142static void __init _register_dpll(struct clk_hw *hw,
142 struct device_node *node) 143 struct device_node *node)
143{ 144{
144 struct clk_hw_omap *clk_hw = to_clk_hw_omap(hw); 145 struct clk_hw_omap *clk_hw = to_clk_hw_omap(hw);
145 struct dpll_data *dd = clk_hw->dpll_data; 146 struct dpll_data *dd = clk_hw->dpll_data;
@@ -151,7 +152,7 @@ static void __init ti_clk_register_dpll(struct clk_hw *hw,
151 if (IS_ERR(dd->clk_ref) || IS_ERR(dd->clk_bypass)) { 152 if (IS_ERR(dd->clk_ref) || IS_ERR(dd->clk_bypass)) {
152 pr_debug("clk-ref or clk-bypass missing for %s, retry later\n", 153 pr_debug("clk-ref or clk-bypass missing for %s, retry later\n",
153 node->name); 154 node->name);
154 if (!ti_clk_retry_init(node, hw, ti_clk_register_dpll)) 155 if (!ti_clk_retry_init(node, hw, _register_dpll))
155 return; 156 return;
156 157
157 goto cleanup; 158 goto cleanup;
@@ -175,20 +176,116 @@ cleanup:
175 kfree(clk_hw); 176 kfree(clk_hw);
176} 177}
177 178
179void __iomem *_get_reg(u8 module, u16 offset)
180{
181 u32 reg;
182 struct clk_omap_reg *reg_setup;
183
184 reg_setup = (struct clk_omap_reg *)&reg;
185
186 reg_setup->index = module;
187 reg_setup->offset = offset;
188
189 return (void __iomem *)reg;
190}
191
192struct clk *ti_clk_register_dpll(struct ti_clk *setup)
193{
194 struct clk_hw_omap *clk_hw;
195 struct clk_init_data init = { NULL };
196 struct dpll_data *dd;
197 struct clk *clk;
198 struct ti_clk_dpll *dpll;
199 const struct clk_ops *ops = &omap3_dpll_ck_ops;
200 struct clk *clk_ref;
201 struct clk *clk_bypass;
202
203 dpll = setup->data;
204
205 if (dpll->num_parents < 2)
206 return ERR_PTR(-EINVAL);
207
208 clk_ref = clk_get_sys(NULL, dpll->parents[0]);
209 clk_bypass = clk_get_sys(NULL, dpll->parents[1]);
210
211 if (IS_ERR_OR_NULL(clk_ref) || IS_ERR_OR_NULL(clk_bypass))
212 return ERR_PTR(-EAGAIN);
213
214 dd = kzalloc(sizeof(*dd), GFP_KERNEL);
215 clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
216 if (!dd || !clk_hw) {
217 clk = ERR_PTR(-ENOMEM);
218 goto cleanup;
219 }
220
221 clk_hw->dpll_data = dd;
222 clk_hw->ops = &clkhwops_omap3_dpll;
223 clk_hw->hw.init = &init;
224 clk_hw->flags = MEMMAP_ADDRESSING;
225
226 init.name = setup->name;
227 init.ops = ops;
228
229 init.num_parents = dpll->num_parents;
230 init.parent_names = dpll->parents;
231
232 dd->control_reg = _get_reg(dpll->module, dpll->control_reg);
233 dd->idlest_reg = _get_reg(dpll->module, dpll->idlest_reg);
234 dd->mult_div1_reg = _get_reg(dpll->module, dpll->mult_div1_reg);
235 dd->autoidle_reg = _get_reg(dpll->module, dpll->autoidle_reg);
236
237 dd->modes = dpll->modes;
238 dd->div1_mask = dpll->div1_mask;
239 dd->idlest_mask = dpll->idlest_mask;
240 dd->mult_mask = dpll->mult_mask;
241 dd->autoidle_mask = dpll->autoidle_mask;
242 dd->enable_mask = dpll->enable_mask;
243 dd->sddiv_mask = dpll->sddiv_mask;
244 dd->dco_mask = dpll->dco_mask;
245 dd->max_divider = dpll->max_divider;
246 dd->min_divider = dpll->min_divider;
247 dd->max_multiplier = dpll->max_multiplier;
248 dd->auto_recal_bit = dpll->auto_recal_bit;
249 dd->recal_en_bit = dpll->recal_en_bit;
250 dd->recal_st_bit = dpll->recal_st_bit;
251
252 dd->clk_ref = clk_ref;
253 dd->clk_bypass = clk_bypass;
254
255 if (dpll->flags & CLKF_CORE)
256 ops = &omap3_dpll_core_ck_ops;
257
258 if (dpll->flags & CLKF_PER)
259 ops = &omap3_dpll_per_ck_ops;
260
261 if (dpll->flags & CLKF_J_TYPE)
262 dd->flags |= DPLL_J_TYPE;
263
264 clk = clk_register(NULL, &clk_hw->hw);
265
266 if (!IS_ERR(clk))
267 return clk;
268
269cleanup:
270 kfree(dd);
271 kfree(clk_hw);
272 return clk;
273}
274
178#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \ 275#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
179 defined(CONFIG_SOC_DRA7XX) || defined(CONFIG_SOC_AM33XX) || \ 276 defined(CONFIG_SOC_DRA7XX) || defined(CONFIG_SOC_AM33XX) || \
180 defined(CONFIG_SOC_AM43XX) 277 defined(CONFIG_SOC_AM43XX)
181/** 278/**
182 * ti_clk_register_dpll_x2 - Registers a DPLLx2 clock 279 * _register_dpll_x2 - Registers a DPLLx2 clock
183 * @node: device node for this clock 280 * @node: device node for this clock
184 * @ops: clk_ops for this clock 281 * @ops: clk_ops for this clock
185 * @hw_ops: clk_hw_ops for this clock 282 * @hw_ops: clk_hw_ops for this clock
186 * 283 *
187 * Initializes a DPLL x 2 clock from device tree data. 284 * Initializes a DPLL x 2 clock from device tree data.
188 */ 285 */
189static void ti_clk_register_dpll_x2(struct device_node *node, 286static void _register_dpll_x2(struct device_node *node,
190 const struct clk_ops *ops, 287 const struct clk_ops *ops,
191 const struct clk_hw_omap_ops *hw_ops) 288 const struct clk_hw_omap_ops *hw_ops)
192{ 289{
193 struct clk *clk; 290 struct clk *clk;
194 struct clk_init_data init = { NULL }; 291 struct clk_init_data init = { NULL };
@@ -318,7 +415,7 @@ static void __init of_ti_dpll_setup(struct device_node *node,
318 if (dpll_mode) 415 if (dpll_mode)
319 dd->modes = dpll_mode; 416 dd->modes = dpll_mode;
320 417
321 ti_clk_register_dpll(&clk_hw->hw, node); 418 _register_dpll(&clk_hw->hw, node);
322 return; 419 return;
323 420
324cleanup: 421cleanup:
@@ -332,7 +429,7 @@ cleanup:
332 defined(CONFIG_SOC_DRA7XX) 429 defined(CONFIG_SOC_DRA7XX)
333static void __init of_ti_omap4_dpll_x2_setup(struct device_node *node) 430static void __init of_ti_omap4_dpll_x2_setup(struct device_node *node)
334{ 431{
335 ti_clk_register_dpll_x2(node, &dpll_x2_ck_ops, &clkhwops_omap4_dpllmx); 432 _register_dpll_x2(node, &dpll_x2_ck_ops, &clkhwops_omap4_dpllmx);
336} 433}
337CLK_OF_DECLARE(ti_omap4_dpll_x2_clock, "ti,omap4-dpll-x2-clock", 434CLK_OF_DECLARE(ti_omap4_dpll_x2_clock, "ti,omap4-dpll-x2-clock",
338 of_ti_omap4_dpll_x2_setup); 435 of_ti_omap4_dpll_x2_setup);
@@ -341,7 +438,7 @@ CLK_OF_DECLARE(ti_omap4_dpll_x2_clock, "ti,omap4-dpll-x2-clock",
341#if defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_AM43XX) 438#if defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_AM43XX)
342static void __init of_ti_am3_dpll_x2_setup(struct device_node *node) 439static void __init of_ti_am3_dpll_x2_setup(struct device_node *node)
343{ 440{
344 ti_clk_register_dpll_x2(node, &dpll_x2_ck_ops, NULL); 441 _register_dpll_x2(node, &dpll_x2_ck_ops, NULL);
345} 442}
346CLK_OF_DECLARE(ti_am3_dpll_x2_clock, "ti,am3-dpll-x2-clock", 443CLK_OF_DECLARE(ti_am3_dpll_x2_clock, "ti,am3-dpll-x2-clock",
347 of_ti_am3_dpll_x2_setup); 444 of_ti_am3_dpll_x2_setup);