aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
authorTero Kristo <t-kristo@ti.com>2014-12-16 11:20:48 -0500
committerMichael Turquette <mturquette@linaro.org>2015-01-30 13:54:54 -0500
commitf187616b36edafff5a18d2b66fe7eed3bbb38bf0 (patch)
treeb200f7c83602177dc499e12cfab36e5c3f16dbba /drivers/clk
parent7c18a65cb5295484261274b931dd4a3da88695d2 (diff)
clk: ti: gate: add support for legacy gate init
Legacy clock data is initialialized 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>
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/ti/clk.c3
-rw-r--r--drivers/clk/ti/clock.h2
-rw-r--r--drivers/clk/ti/gate.c158
3 files changed, 133 insertions, 30 deletions
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index 215f681053d0..676dbf170b31 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -222,6 +222,9 @@ struct clk __init *ti_clk_register_clk(struct ti_clk *setup)
222 0, fixed_factor->mult, 222 0, fixed_factor->mult,
223 fixed_factor->div); 223 fixed_factor->div);
224 break; 224 break;
225 case TI_CLK_GATE:
226 clk = ti_clk_register_gate(setup);
227 break;
225 default: 228 default:
226 pr_err("bad type for %s!\n", setup->name); 229 pr_err("bad type for %s!\n", setup->name);
227 clk = ERR_PTR(-EINVAL); 230 clk = ERR_PTR(-EINVAL);
diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h
index c06bbf4c9f95..d0715bc029b6 100644
--- a/drivers/clk/ti/clock.h
+++ b/drivers/clk/ti/clock.h
@@ -153,8 +153,10 @@ struct ti_clk_dpll {
153 u8 recal_st_bit; 153 u8 recal_st_bit;
154}; 154};
155 155
156struct clk *ti_clk_register_gate(struct ti_clk *setup);
156struct clk *ti_clk_register_mux(struct ti_clk *setup); 157struct clk *ti_clk_register_mux(struct ti_clk *setup);
157 158
159struct clk_hw *ti_clk_build_component_gate(struct ti_clk_gate *setup);
158struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup); 160struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup);
159 161
160void ti_clk_patch_legacy_clks(struct ti_clk **patch); 162void ti_clk_patch_legacy_clks(struct ti_clk **patch);
diff --git a/drivers/clk/ti/gate.c b/drivers/clk/ti/gate.c
index b326d2797feb..ff3380ea3861 100644
--- a/drivers/clk/ti/gate.c
+++ b/drivers/clk/ti/gate.c
@@ -22,6 +22,8 @@
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 24
25#include "clock.h"
26
25#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw) 27#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
26 28
27#undef pr_fmt 29#undef pr_fmt
@@ -90,63 +92,159 @@ static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
90 return ret; 92 return ret;
91} 93}
92 94
93static void __init _of_ti_gate_clk_setup(struct device_node *node, 95static struct clk *_register_gate(struct device *dev, const char *name,
94 const struct clk_ops *ops, 96 const char *parent_name, unsigned long flags,
95 const struct clk_hw_omap_ops *hw_ops) 97 void __iomem *reg, u8 bit_idx,
98 u8 clk_gate_flags, const struct clk_ops *ops,
99 const struct clk_hw_omap_ops *hw_ops)
96{ 100{
97 struct clk *clk;
98 struct clk_init_data init = { NULL }; 101 struct clk_init_data init = { NULL };
99 struct clk_hw_omap *clk_hw; 102 struct clk_hw_omap *clk_hw;
100 const char *clk_name = node->name; 103 struct clk *clk;
101 const char *parent_name;
102 u32 val;
103 104
104 clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); 105 clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
105 if (!clk_hw) 106 if (!clk_hw)
106 return; 107 return ERR_PTR(-ENOMEM);
107 108
108 clk_hw->hw.init = &init; 109 clk_hw->hw.init = &init;
109 110
110 init.name = clk_name; 111 init.name = name;
111 init.ops = ops; 112 init.ops = ops;
112 113
113 if (ops != &omap_gate_clkdm_clk_ops) { 114 clk_hw->enable_reg = reg;
114 clk_hw->enable_reg = ti_clk_get_reg_addr(node, 0); 115 clk_hw->enable_bit = bit_idx;
115 if (!clk_hw->enable_reg) 116 clk_hw->ops = hw_ops;
116 goto cleanup;
117 117
118 if (!of_property_read_u32(node, "ti,bit-shift", &val)) 118 clk_hw->flags = MEMMAP_ADDRESSING | clk_gate_flags;
119 clk_hw->enable_bit = val; 119
120 init.parent_names = &parent_name;
121 init.num_parents = 1;
122
123 init.flags = flags;
124
125 clk = clk_register(NULL, &clk_hw->hw);
126
127 if (IS_ERR(clk))
128 kfree(clk_hw);
129
130 return clk;
131}
132
133struct clk *ti_clk_register_gate(struct ti_clk *setup)
134{
135 const struct clk_ops *ops = &omap_gate_clk_ops;
136 const struct clk_hw_omap_ops *hw_ops = NULL;
137 u32 reg;
138 struct clk_omap_reg *reg_setup;
139 u32 flags = 0;
140 u8 clk_gate_flags = 0;
141 struct ti_clk_gate *gate;
142
143 gate = setup->data;
144
145 reg_setup = (struct clk_omap_reg *)&reg;
146
147 if (gate->flags & CLKF_SET_RATE_PARENT)
148 flags |= CLK_SET_RATE_PARENT;
149
150 if (gate->flags & CLKF_SET_BIT_TO_DISABLE)
151 clk_gate_flags |= INVERT_ENABLE;
152
153 if (gate->flags & CLKF_HSDIV) {
154 ops = &omap_gate_clk_hsdiv_restore_ops;
155 hw_ops = &clkhwops_wait;
120 } 156 }
121 157
122 clk_hw->ops = hw_ops; 158 if (gate->flags & CLKF_DSS)
159 hw_ops = &clkhwops_omap3430es2_dss_usbhost_wait;
160
161 if (gate->flags & CLKF_WAIT)
162 hw_ops = &clkhwops_wait;
163
164 if (gate->flags & CLKF_CLKDM)
165 ops = &omap_gate_clkdm_clk_ops;
166
167 if (gate->flags & CLKF_AM35XX)
168 hw_ops = &clkhwops_am35xx_ipss_module_wait;
123 169
124 clk_hw->flags = MEMMAP_ADDRESSING; 170 reg_setup->index = gate->module;
171 reg_setup->offset = gate->reg;
172
173 return _register_gate(NULL, setup->name, gate->parent, flags,
174 (void __iomem *)reg, gate->bit_shift,
175 clk_gate_flags, ops, hw_ops);
176}
177
178struct clk_hw *ti_clk_build_component_gate(struct ti_clk_gate *setup)
179{
180 struct clk_hw_omap *gate;
181 struct clk_omap_reg *reg;
182 const struct clk_hw_omap_ops *ops = &clkhwops_wait;
183
184 if (!setup)
185 return NULL;
186
187 gate = kzalloc(sizeof(*gate), GFP_KERNEL);
188 if (!gate)
189 return ERR_PTR(-ENOMEM);
190
191 reg = (struct clk_omap_reg *)&gate->enable_reg;
192 reg->index = setup->module;
193 reg->offset = setup->reg;
194
195 gate->enable_bit = setup->bit_shift;
196
197 if (setup->flags & CLKF_NO_WAIT)
198 ops = NULL;
199
200 if (setup->flags & CLKF_INTERFACE)
201 ops = &clkhwops_iclk_wait;
202
203 gate->ops = ops;
204 gate->flags = MEMMAP_ADDRESSING;
205
206 return &gate->hw;
207}
208
209static void __init _of_ti_gate_clk_setup(struct device_node *node,
210 const struct clk_ops *ops,
211 const struct clk_hw_omap_ops *hw_ops)
212{
213 struct clk *clk;
214 const char *parent_name;
215 void __iomem *reg = NULL;
216 u8 enable_bit = 0;
217 u32 val;
218 u32 flags = 0;
219 u8 clk_gate_flags = 0;
220
221 if (ops != &omap_gate_clkdm_clk_ops) {
222 reg = ti_clk_get_reg_addr(node, 0);
223 if (!reg)
224 return;
225
226 if (!of_property_read_u32(node, "ti,bit-shift", &val))
227 enable_bit = val;
228 }
125 229
126 if (of_clk_get_parent_count(node) != 1) { 230 if (of_clk_get_parent_count(node) != 1) {
127 pr_err("%s must have 1 parent\n", clk_name); 231 pr_err("%s must have 1 parent\n", node->name);
128 goto cleanup; 232 return;
129 } 233 }
130 234
131 parent_name = of_clk_get_parent_name(node, 0); 235 parent_name = of_clk_get_parent_name(node, 0);
132 init.parent_names = &parent_name;
133 init.num_parents = 1;
134 236
135 if (of_property_read_bool(node, "ti,set-rate-parent")) 237 if (of_property_read_bool(node, "ti,set-rate-parent"))
136 init.flags |= CLK_SET_RATE_PARENT; 238 flags |= CLK_SET_RATE_PARENT;
137 239
138 if (of_property_read_bool(node, "ti,set-bit-to-disable")) 240 if (of_property_read_bool(node, "ti,set-bit-to-disable"))
139 clk_hw->flags |= INVERT_ENABLE; 241 clk_gate_flags |= INVERT_ENABLE;
140 242
141 clk = clk_register(NULL, &clk_hw->hw); 243 clk = _register_gate(NULL, node->name, parent_name, flags, reg,
244 enable_bit, clk_gate_flags, ops, hw_ops);
142 245
143 if (!IS_ERR(clk)) { 246 if (!IS_ERR(clk))
144 of_clk_add_provider(node, of_clk_src_simple_get, clk); 247 of_clk_add_provider(node, of_clk_src_simple_get, clk);
145 return;
146 }
147
148cleanup:
149 kfree(clk_hw);
150} 248}
151 249
152static void __init 250static void __init