.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2013 NVIDIA CORPORATION. All rights reserved. |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or modify it |
---|
5 | | - * under the terms and conditions of the GNU General Public License, |
---|
6 | | - * version 2, as published by the Free Software Foundation. |
---|
7 | | - * |
---|
8 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
---|
9 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
10 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
11 | | - * more details. |
---|
12 | | - * |
---|
13 | | - * You should have received a copy of the GNU General Public License |
---|
14 | | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
---|
15 | 4 | */ |
---|
16 | 5 | |
---|
17 | | -#include <linux/clk.h> |
---|
18 | 6 | #include <linux/clk-provider.h> |
---|
19 | 7 | #include <linux/err.h> |
---|
20 | 8 | #include <linux/slab.h> |
---|
.. | .. |
---|
161 | 149 | const struct clk_ops *mux_ops = composite->mux_ops; |
---|
162 | 150 | struct clk_hw *rate_hw = composite->rate_hw; |
---|
163 | 151 | struct clk_hw *mux_hw = composite->mux_hw; |
---|
164 | | - struct clk_hw *brother_hw = composite->brother_hw; |
---|
165 | 152 | unsigned long temp_rate; |
---|
166 | | - |
---|
167 | | - if (brother_hw) { |
---|
168 | | - struct clk_composite *bcomposite = to_clk_composite(brother_hw); |
---|
169 | | - const struct clk_ops *brate_ops = bcomposite->rate_ops; |
---|
170 | | - struct clk_hw *brate_hw = bcomposite->rate_hw; |
---|
171 | | - struct clk_hw *parent_hw = clk_hw_get_parent(brother_hw); |
---|
172 | | - struct clk_hw *new_parent_hw = clk_hw_get_parent(hw); |
---|
173 | | - |
---|
174 | | - __clk_hw_set_clk(brate_hw, brother_hw); |
---|
175 | | - |
---|
176 | | - temp_rate = brate_ops->recalc_rate(brate_hw, parent_rate); |
---|
177 | | - if (temp_rate > rate) |
---|
178 | | - brate_ops->set_rate(brate_hw, rate, parent_rate); |
---|
179 | | - if (clk_hw_is_prepared(brother_hw)) { |
---|
180 | | - clk_prepare_enable(new_parent_hw->clk); |
---|
181 | | - clk_enable(brother_hw->clk); |
---|
182 | | - } |
---|
183 | | - clk_hw_reparent(brother_hw, new_parent_hw); |
---|
184 | | - if (clk_hw_is_prepared(brother_hw)) { |
---|
185 | | - clk_disable(brother_hw->clk); |
---|
186 | | - clk_disable_unprepare(parent_hw->clk); |
---|
187 | | - } |
---|
188 | | - } |
---|
189 | 153 | |
---|
190 | 154 | __clk_hw_set_clk(rate_hw, hw); |
---|
191 | 155 | __clk_hw_set_clk(mux_hw, hw); |
---|
.. | .. |
---|
235 | 199 | gate_ops->disable(gate_hw); |
---|
236 | 200 | } |
---|
237 | 201 | |
---|
238 | | -struct clk_hw *clk_hw_register_composite(struct device *dev, const char *name, |
---|
239 | | - const char * const *parent_names, int num_parents, |
---|
| 202 | +static struct clk_hw *__clk_hw_register_composite(struct device *dev, |
---|
| 203 | + const char *name, const char * const *parent_names, |
---|
| 204 | + const struct clk_parent_data *pdata, int num_parents, |
---|
240 | 205 | struct clk_hw *mux_hw, const struct clk_ops *mux_ops, |
---|
241 | 206 | struct clk_hw *rate_hw, const struct clk_ops *rate_ops, |
---|
242 | 207 | struct clk_hw *gate_hw, const struct clk_ops *gate_ops, |
---|
.. | .. |
---|
253 | 218 | return ERR_PTR(-ENOMEM); |
---|
254 | 219 | |
---|
255 | 220 | init.name = name; |
---|
256 | | - init.flags = flags | CLK_IS_BASIC; |
---|
257 | | - init.parent_names = parent_names; |
---|
| 221 | + init.flags = flags; |
---|
| 222 | + if (parent_names) |
---|
| 223 | + init.parent_names = parent_names; |
---|
| 224 | + else |
---|
| 225 | + init.parent_data = pdata; |
---|
258 | 226 | init.num_parents = num_parents; |
---|
259 | 227 | hw = &composite->hw; |
---|
260 | 228 | |
---|
.. | .. |
---|
348 | 316 | return hw; |
---|
349 | 317 | } |
---|
350 | 318 | |
---|
| 319 | +struct clk_hw *clk_hw_register_composite(struct device *dev, const char *name, |
---|
| 320 | + const char * const *parent_names, int num_parents, |
---|
| 321 | + struct clk_hw *mux_hw, const struct clk_ops *mux_ops, |
---|
| 322 | + struct clk_hw *rate_hw, const struct clk_ops *rate_ops, |
---|
| 323 | + struct clk_hw *gate_hw, const struct clk_ops *gate_ops, |
---|
| 324 | + unsigned long flags) |
---|
| 325 | +{ |
---|
| 326 | + return __clk_hw_register_composite(dev, name, parent_names, NULL, |
---|
| 327 | + num_parents, mux_hw, mux_ops, |
---|
| 328 | + rate_hw, rate_ops, gate_hw, |
---|
| 329 | + gate_ops, flags); |
---|
| 330 | +} |
---|
| 331 | +EXPORT_SYMBOL_GPL(clk_hw_register_composite); |
---|
| 332 | + |
---|
| 333 | +struct clk_hw *clk_hw_register_composite_pdata(struct device *dev, |
---|
| 334 | + const char *name, |
---|
| 335 | + const struct clk_parent_data *parent_data, |
---|
| 336 | + int num_parents, |
---|
| 337 | + struct clk_hw *mux_hw, const struct clk_ops *mux_ops, |
---|
| 338 | + struct clk_hw *rate_hw, const struct clk_ops *rate_ops, |
---|
| 339 | + struct clk_hw *gate_hw, const struct clk_ops *gate_ops, |
---|
| 340 | + unsigned long flags) |
---|
| 341 | +{ |
---|
| 342 | + return __clk_hw_register_composite(dev, name, NULL, parent_data, |
---|
| 343 | + num_parents, mux_hw, mux_ops, |
---|
| 344 | + rate_hw, rate_ops, gate_hw, |
---|
| 345 | + gate_ops, flags); |
---|
| 346 | +} |
---|
| 347 | + |
---|
351 | 348 | struct clk *clk_register_composite(struct device *dev, const char *name, |
---|
352 | 349 | const char * const *parent_names, int num_parents, |
---|
353 | 350 | struct clk_hw *mux_hw, const struct clk_ops *mux_ops, |
---|
.. | .. |
---|
360 | 357 | hw = clk_hw_register_composite(dev, name, parent_names, num_parents, |
---|
361 | 358 | mux_hw, mux_ops, rate_hw, rate_ops, gate_hw, gate_ops, |
---|
362 | 359 | flags); |
---|
| 360 | + if (IS_ERR(hw)) |
---|
| 361 | + return ERR_CAST(hw); |
---|
| 362 | + return hw->clk; |
---|
| 363 | +} |
---|
| 364 | +EXPORT_SYMBOL_GPL(clk_register_composite); |
---|
| 365 | + |
---|
| 366 | +struct clk *clk_register_composite_pdata(struct device *dev, const char *name, |
---|
| 367 | + const struct clk_parent_data *parent_data, |
---|
| 368 | + int num_parents, |
---|
| 369 | + struct clk_hw *mux_hw, const struct clk_ops *mux_ops, |
---|
| 370 | + struct clk_hw *rate_hw, const struct clk_ops *rate_ops, |
---|
| 371 | + struct clk_hw *gate_hw, const struct clk_ops *gate_ops, |
---|
| 372 | + unsigned long flags) |
---|
| 373 | +{ |
---|
| 374 | + struct clk_hw *hw; |
---|
| 375 | + |
---|
| 376 | + hw = clk_hw_register_composite_pdata(dev, name, parent_data, |
---|
| 377 | + num_parents, mux_hw, mux_ops, rate_hw, rate_ops, |
---|
| 378 | + gate_hw, gate_ops, flags); |
---|
363 | 379 | if (IS_ERR(hw)) |
---|
364 | 380 | return ERR_CAST(hw); |
---|
365 | 381 | return hw->clk; |
---|
.. | .. |
---|
379 | 395 | clk_unregister(clk); |
---|
380 | 396 | kfree(composite); |
---|
381 | 397 | } |
---|
| 398 | + |
---|
| 399 | +void clk_hw_unregister_composite(struct clk_hw *hw) |
---|
| 400 | +{ |
---|
| 401 | + struct clk_composite *composite; |
---|
| 402 | + |
---|
| 403 | + composite = to_clk_composite(hw); |
---|
| 404 | + |
---|
| 405 | + clk_hw_unregister(hw); |
---|
| 406 | + kfree(composite); |
---|
| 407 | +} |
---|
| 408 | +EXPORT_SYMBOL_GPL(clk_hw_unregister_composite); |
---|