diff options
Diffstat (limited to 'drivers/clk/tegra/clk-periph.c')
-rw-r--r-- | drivers/clk/tegra/clk-periph.c | 72 |
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 | ||
114 | void 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 | } | ||
132 | EXPORT_SYMBOL(tegra_periph_reset_deassert); | ||
133 | |||
134 | void 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 | } | ||
152 | EXPORT_SYMBOL(tegra_periph_reset_assert); | ||
153 | |||
154 | const struct clk_ops tegra_clk_periph_ops = { | 114 | const 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 | ||
133 | const 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 | |||
173 | static struct clk *_tegra_clk_register_periph(const char *name, | 141 | static 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 | ||
215 | struct clk *tegra_clk_register_periph_nodiv(const char *name, | 198 | struct 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 | } |