aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/tegra/clk-periph.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/tegra/clk-periph.c')
-rw-r--r--drivers/clk/tegra/clk-periph.c72
1 files changed, 28 insertions, 44 deletions
diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c
index b2309d37a963..c534043c0481 100644
--- a/drivers/clk/tegra/clk-periph.c
+++ b/drivers/clk/tegra/clk-periph.c
@@ -111,46 +111,6 @@ static void clk_periph_disable(struct clk_hw *hw)
111 gate_ops->disable(gate_hw); 111 gate_ops->disable(gate_hw);
112} 112}
113 113
114void tegra_periph_reset_deassert(struct clk *c)
115{
116 struct clk_hw *hw = __clk_get_hw(c);
117 struct tegra_clk_periph *periph = to_clk_periph(hw);
118 struct tegra_clk_periph_gate *gate;
119
120 if (periph->magic != TEGRA_CLK_PERIPH_MAGIC) {
121 gate = to_clk_periph_gate(hw);
122 if (gate->magic != TEGRA_CLK_PERIPH_GATE_MAGIC) {
123 WARN_ON(1);
124 return;
125 }
126 } else {
127 gate = &periph->gate;
128 }
129
130 tegra_periph_reset(gate, 0);
131}
132EXPORT_SYMBOL(tegra_periph_reset_deassert);
133
134void tegra_periph_reset_assert(struct clk *c)
135{
136 struct clk_hw *hw = __clk_get_hw(c);
137 struct tegra_clk_periph *periph = to_clk_periph(hw);
138 struct tegra_clk_periph_gate *gate;
139
140 if (periph->magic != TEGRA_CLK_PERIPH_MAGIC) {
141 gate = to_clk_periph_gate(hw);
142 if (gate->magic != TEGRA_CLK_PERIPH_GATE_MAGIC) {
143 WARN_ON(1);
144 return;
145 }
146 } else {
147 gate = &periph->gate;
148 }
149
150 tegra_periph_reset(gate, 1);
151}
152EXPORT_SYMBOL(tegra_periph_reset_assert);
153
154const struct clk_ops tegra_clk_periph_ops = { 114const struct clk_ops tegra_clk_periph_ops = {
155 .get_parent = clk_periph_get_parent, 115 .get_parent = clk_periph_get_parent,
156 .set_parent = clk_periph_set_parent, 116 .set_parent = clk_periph_set_parent,
@@ -170,27 +130,50 @@ const struct clk_ops tegra_clk_periph_nodiv_ops = {
170 .disable = clk_periph_disable, 130 .disable = clk_periph_disable,
171}; 131};
172 132
133const struct clk_ops tegra_clk_periph_no_gate_ops = {
134 .get_parent = clk_periph_get_parent,
135 .set_parent = clk_periph_set_parent,
136 .recalc_rate = clk_periph_recalc_rate,
137 .round_rate = clk_periph_round_rate,
138 .set_rate = clk_periph_set_rate,
139};
140
173static struct clk *_tegra_clk_register_periph(const char *name, 141static struct clk *_tegra_clk_register_periph(const char *name,
174 const char **parent_names, int num_parents, 142 const char **parent_names, int num_parents,
175 struct tegra_clk_periph *periph, 143 struct tegra_clk_periph *periph,
176 void __iomem *clk_base, u32 offset, bool div, 144 void __iomem *clk_base, u32 offset,
177 unsigned long flags) 145 unsigned long flags)
178{ 146{
179 struct clk *clk; 147 struct clk *clk;
180 struct clk_init_data init; 148 struct clk_init_data init;
149 struct tegra_clk_periph_regs *bank;
150 bool div = !(periph->gate.flags & TEGRA_PERIPH_NO_DIV);
151
152 if (periph->gate.flags & TEGRA_PERIPH_NO_DIV) {
153 flags |= CLK_SET_RATE_PARENT;
154 init.ops = &tegra_clk_periph_nodiv_ops;
155 } else if (periph->gate.flags & TEGRA_PERIPH_NO_GATE)
156 init.ops = &tegra_clk_periph_no_gate_ops;
157 else
158 init.ops = &tegra_clk_periph_ops;
181 159
182 init.name = name; 160 init.name = name;
183 init.ops = div ? &tegra_clk_periph_ops : &tegra_clk_periph_nodiv_ops;
184 init.flags = flags; 161 init.flags = flags;
185 init.parent_names = parent_names; 162 init.parent_names = parent_names;
186 init.num_parents = num_parents; 163 init.num_parents = num_parents;
187 164
165 bank = get_reg_bank(periph->gate.clk_num);
166 if (!bank)
167 return ERR_PTR(-EINVAL);
168
188 /* Data in .init is copied by clk_register(), so stack variable OK */ 169 /* Data in .init is copied by clk_register(), so stack variable OK */
189 periph->hw.init = &init; 170 periph->hw.init = &init;
190 periph->magic = TEGRA_CLK_PERIPH_MAGIC; 171 periph->magic = TEGRA_CLK_PERIPH_MAGIC;
191 periph->mux.reg = clk_base + offset; 172 periph->mux.reg = clk_base + offset;
192 periph->divider.reg = div ? (clk_base + offset) : NULL; 173 periph->divider.reg = div ? (clk_base + offset) : NULL;
193 periph->gate.clk_base = clk_base; 174 periph->gate.clk_base = clk_base;
175 periph->gate.regs = bank;
176 periph->gate.enable_refcnt = periph_clk_enb_refcnt;
194 177
195 clk = clk_register(NULL, &periph->hw); 178 clk = clk_register(NULL, &periph->hw);
196 if (IS_ERR(clk)) 179 if (IS_ERR(clk))
@@ -209,7 +192,7 @@ struct clk *tegra_clk_register_periph(const char *name,
209 u32 offset, unsigned long flags) 192 u32 offset, unsigned long flags)
210{ 193{
211 return _tegra_clk_register_periph(name, parent_names, num_parents, 194 return _tegra_clk_register_periph(name, parent_names, num_parents,
212 periph, clk_base, offset, true, flags); 195 periph, clk_base, offset, flags);
213} 196}
214 197
215struct clk *tegra_clk_register_periph_nodiv(const char *name, 198struct clk *tegra_clk_register_periph_nodiv(const char *name,
@@ -217,6 +200,7 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name,
217 struct tegra_clk_periph *periph, void __iomem *clk_base, 200 struct tegra_clk_periph *periph, void __iomem *clk_base,
218 u32 offset) 201 u32 offset)
219{ 202{
203 periph->gate.flags |= TEGRA_PERIPH_NO_DIV;
220 return _tegra_clk_register_periph(name, parent_names, num_parents, 204 return _tegra_clk_register_periph(name, parent_names, num_parents,
221 periph, clk_base, offset, false, CLK_SET_RATE_PARENT); 205 periph, clk_base, offset, CLK_SET_RATE_PARENT);
222} 206}