root/drivers/clk/clk-divider.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. clk_div_readl
  2. clk_div_writel
  3. _get_table_maxdiv
  4. _get_table_mindiv
  5. _get_maxdiv
  6. _get_table_div
  7. _get_div
  8. _get_table_val
  9. _get_val
  10. divider_recalc_rate
  11. clk_divider_recalc_rate
  12. _is_valid_table_div
  13. _is_valid_div
  14. _round_up_table
  15. _round_down_table
  16. _div_round_up
  17. _div_round_closest
  18. _div_round
  19. _is_best_div
  20. _next_div
  21. clk_divider_bestdiv
  22. divider_round_rate_parent
  23. divider_ro_round_rate_parent
  24. clk_divider_round_rate
  25. divider_get_val
  26. clk_divider_set_rate
  27. _register_divider
  28. clk_register_divider
  29. clk_hw_register_divider
  30. clk_register_divider_table
  31. clk_hw_register_divider_table
  32. clk_unregister_divider
  33. clk_hw_unregister_divider

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
   4  * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org>
   5  * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
   6  *
   7  * Adjustable divider clock implementation
   8  */
   9 
  10 #include <linux/clk-provider.h>
  11 #include <linux/module.h>
  12 #include <linux/slab.h>
  13 #include <linux/io.h>
  14 #include <linux/err.h>
  15 #include <linux/string.h>
  16 #include <linux/log2.h>
  17 
  18 /*
  19  * DOC: basic adjustable divider clock that cannot gate
  20  *
  21  * Traits of this clock:
  22  * prepare - clk_prepare only ensures that parents are prepared
  23  * enable - clk_enable only ensures that parents are enabled
  24  * rate - rate is adjustable.  clk->rate = ceiling(parent->rate / divisor)
  25  * parent - fixed parent.  No clk_set_parent support
  26  */
  27 
  28 static inline u32 clk_div_readl(struct clk_divider *divider)
  29 {
  30         if (divider->flags & CLK_DIVIDER_BIG_ENDIAN)
  31                 return ioread32be(divider->reg);
  32 
  33         return readl(divider->reg);
  34 }
  35 
  36 static inline void clk_div_writel(struct clk_divider *divider, u32 val)
  37 {
  38         if (divider->flags & CLK_DIVIDER_BIG_ENDIAN)
  39                 iowrite32be(val, divider->reg);
  40         else
  41                 writel(val, divider->reg);
  42 }
  43 
  44 static unsigned int _get_table_maxdiv(const struct clk_div_table *table,
  45                                       u8 width)
  46 {
  47         unsigned int maxdiv = 0, mask = clk_div_mask(width);
  48         const struct clk_div_table *clkt;
  49 
  50         for (clkt = table; clkt->div; clkt++)
  51                 if (clkt->div > maxdiv && clkt->val <= mask)
  52                         maxdiv = clkt->div;
  53         return maxdiv;
  54 }
  55 
  56 static unsigned int _get_table_mindiv(const struct clk_div_table *table)
  57 {
  58         unsigned int mindiv = UINT_MAX;
  59         const struct clk_div_table *clkt;
  60 
  61         for (clkt = table; clkt->div; clkt++)
  62                 if (clkt->div < mindiv)
  63                         mindiv = clkt->div;
  64         return mindiv;
  65 }
  66 
  67 static unsigned int _get_maxdiv(const struct clk_div_table *table, u8 width,
  68                                 unsigned long flags)
  69 {
  70         if (flags & CLK_DIVIDER_ONE_BASED)
  71                 return clk_div_mask(width);
  72         if (flags & CLK_DIVIDER_POWER_OF_TWO)
  73                 return 1 << clk_div_mask(width);
  74         if (table)
  75                 return _get_table_maxdiv(table, width);
  76         return clk_div_mask(width) + 1;
  77 }
  78 
  79 static unsigned int _get_table_div(const struct clk_div_table *table,
  80                                                         unsigned int val)
  81 {
  82         const struct clk_div_table *clkt;
  83 
  84         for (clkt = table; clkt->div; clkt++)
  85                 if (clkt->val == val)
  86                         return clkt->div;
  87         return 0;
  88 }
  89 
  90 static unsigned int _get_div(const struct clk_div_table *table,
  91                              unsigned int val, unsigned long flags, u8 width)
  92 {
  93         if (flags & CLK_DIVIDER_ONE_BASED)
  94                 return val;
  95         if (flags & CLK_DIVIDER_POWER_OF_TWO)
  96                 return 1 << val;
  97         if (flags & CLK_DIVIDER_MAX_AT_ZERO)
  98                 return val ? val : clk_div_mask(width) + 1;
  99         if (table)
 100                 return _get_table_div(table, val);
 101         return val + 1;
 102 }
 103 
 104 static unsigned int _get_table_val(const struct clk_div_table *table,
 105                                                         unsigned int div)
 106 {
 107         const struct clk_div_table *clkt;
 108 
 109         for (clkt = table; clkt->div; clkt++)
 110                 if (clkt->div == div)
 111                         return clkt->val;
 112         return 0;
 113 }
 114 
 115 static unsigned int _get_val(const struct clk_div_table *table,
 116                              unsigned int div, unsigned long flags, u8 width)
 117 {
 118         if (flags & CLK_DIVIDER_ONE_BASED)
 119                 return div;
 120         if (flags & CLK_DIVIDER_POWER_OF_TWO)
 121                 return __ffs(div);
 122         if (flags & CLK_DIVIDER_MAX_AT_ZERO)
 123                 return (div == clk_div_mask(width) + 1) ? 0 : div;
 124         if (table)
 125                 return  _get_table_val(table, div);
 126         return div - 1;
 127 }
 128 
 129 unsigned long divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate,
 130                                   unsigned int val,
 131                                   const struct clk_div_table *table,
 132                                   unsigned long flags, unsigned long width)
 133 {
 134         unsigned int div;
 135 
 136         div = _get_div(table, val, flags, width);
 137         if (!div) {
 138                 WARN(!(flags & CLK_DIVIDER_ALLOW_ZERO),
 139                         "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
 140                         clk_hw_get_name(hw));
 141                 return parent_rate;
 142         }
 143 
 144         return DIV_ROUND_UP_ULL((u64)parent_rate, div);
 145 }
 146 EXPORT_SYMBOL_GPL(divider_recalc_rate);
 147 
 148 static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
 149                 unsigned long parent_rate)
 150 {
 151         struct clk_divider *divider = to_clk_divider(hw);
 152         unsigned int val;
 153 
 154         val = clk_div_readl(divider) >> divider->shift;
 155         val &= clk_div_mask(divider->width);
 156 
 157         return divider_recalc_rate(hw, parent_rate, val, divider->table,
 158                                    divider->flags, divider->width);
 159 }
 160 
 161 static bool _is_valid_table_div(const struct clk_div_table *table,
 162                                                          unsigned int div)
 163 {
 164         const struct clk_div_table *clkt;
 165 
 166         for (clkt = table; clkt->div; clkt++)
 167                 if (clkt->div == div)
 168                         return true;
 169         return false;
 170 }
 171 
 172 static bool _is_valid_div(const struct clk_div_table *table, unsigned int div,
 173                           unsigned long flags)
 174 {
 175         if (flags & CLK_DIVIDER_POWER_OF_TWO)
 176                 return is_power_of_2(div);
 177         if (table)
 178                 return _is_valid_table_div(table, div);
 179         return true;
 180 }
 181 
 182 static int _round_up_table(const struct clk_div_table *table, int div)
 183 {
 184         const struct clk_div_table *clkt;
 185         int up = INT_MAX;
 186 
 187         for (clkt = table; clkt->div; clkt++) {
 188                 if (clkt->div == div)
 189                         return clkt->div;
 190                 else if (clkt->div < div)
 191                         continue;
 192 
 193                 if ((clkt->div - div) < (up - div))
 194                         up = clkt->div;
 195         }
 196 
 197         return up;
 198 }
 199 
 200 static int _round_down_table(const struct clk_div_table *table, int div)
 201 {
 202         const struct clk_div_table *clkt;
 203         int down = _get_table_mindiv(table);
 204 
 205         for (clkt = table; clkt->div; clkt++) {
 206                 if (clkt->div == div)
 207                         return clkt->div;
 208                 else if (clkt->div > div)
 209                         continue;
 210 
 211                 if ((div - clkt->div) < (div - down))
 212                         down = clkt->div;
 213         }
 214 
 215         return down;
 216 }
 217 
 218 static int _div_round_up(const struct clk_div_table *table,
 219                          unsigned long parent_rate, unsigned long rate,
 220                          unsigned long flags)
 221 {
 222         int div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
 223 
 224         if (flags & CLK_DIVIDER_POWER_OF_TWO)
 225                 div = __roundup_pow_of_two(div);
 226         if (table)
 227                 div = _round_up_table(table, div);
 228 
 229         return div;
 230 }
 231 
 232 static int _div_round_closest(const struct clk_div_table *table,
 233                               unsigned long parent_rate, unsigned long rate,
 234                               unsigned long flags)
 235 {
 236         int up, down;
 237         unsigned long up_rate, down_rate;
 238 
 239         up = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
 240         down = parent_rate / rate;
 241 
 242         if (flags & CLK_DIVIDER_POWER_OF_TWO) {
 243                 up = __roundup_pow_of_two(up);
 244                 down = __rounddown_pow_of_two(down);
 245         } else if (table) {
 246                 up = _round_up_table(table, up);
 247                 down = _round_down_table(table, down);
 248         }
 249 
 250         up_rate = DIV_ROUND_UP_ULL((u64)parent_rate, up);
 251         down_rate = DIV_ROUND_UP_ULL((u64)parent_rate, down);
 252 
 253         return (rate - up_rate) <= (down_rate - rate) ? up : down;
 254 }
 255 
 256 static int _div_round(const struct clk_div_table *table,
 257                       unsigned long parent_rate, unsigned long rate,
 258                       unsigned long flags)
 259 {
 260         if (flags & CLK_DIVIDER_ROUND_CLOSEST)
 261                 return _div_round_closest(table, parent_rate, rate, flags);
 262 
 263         return _div_round_up(table, parent_rate, rate, flags);
 264 }
 265 
 266 static bool _is_best_div(unsigned long rate, unsigned long now,
 267                          unsigned long best, unsigned long flags)
 268 {
 269         if (flags & CLK_DIVIDER_ROUND_CLOSEST)
 270                 return abs(rate - now) < abs(rate - best);
 271 
 272         return now <= rate && now > best;
 273 }
 274 
 275 static int _next_div(const struct clk_div_table *table, int div,
 276                      unsigned long flags)
 277 {
 278         div++;
 279 
 280         if (flags & CLK_DIVIDER_POWER_OF_TWO)
 281                 return __roundup_pow_of_two(div);
 282         if (table)
 283                 return _round_up_table(table, div);
 284 
 285         return div;
 286 }
 287 
 288 static int clk_divider_bestdiv(struct clk_hw *hw, struct clk_hw *parent,
 289                                unsigned long rate,
 290                                unsigned long *best_parent_rate,
 291                                const struct clk_div_table *table, u8 width,
 292                                unsigned long flags)
 293 {
 294         int i, bestdiv = 0;
 295         unsigned long parent_rate, best = 0, now, maxdiv;
 296         unsigned long parent_rate_saved = *best_parent_rate;
 297 
 298         if (!rate)
 299                 rate = 1;
 300 
 301         maxdiv = _get_maxdiv(table, width, flags);
 302 
 303         if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
 304                 parent_rate = *best_parent_rate;
 305                 bestdiv = _div_round(table, parent_rate, rate, flags);
 306                 bestdiv = bestdiv == 0 ? 1 : bestdiv;
 307                 bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
 308                 return bestdiv;
 309         }
 310 
 311         /*
 312          * The maximum divider we can use without overflowing
 313          * unsigned long in rate * i below
 314          */
 315         maxdiv = min(ULONG_MAX / rate, maxdiv);
 316 
 317         for (i = _next_div(table, 0, flags); i <= maxdiv;
 318                                              i = _next_div(table, i, flags)) {
 319                 if (rate * i == parent_rate_saved) {
 320                         /*
 321                          * It's the most ideal case if the requested rate can be
 322                          * divided from parent clock without needing to change
 323                          * parent rate, so return the divider immediately.
 324                          */
 325                         *best_parent_rate = parent_rate_saved;
 326                         return i;
 327                 }
 328                 parent_rate = clk_hw_round_rate(parent, rate * i);
 329                 now = DIV_ROUND_UP_ULL((u64)parent_rate, i);
 330                 if (_is_best_div(rate, now, best, flags)) {
 331                         bestdiv = i;
 332                         best = now;
 333                         *best_parent_rate = parent_rate;
 334                 }
 335         }
 336 
 337         if (!bestdiv) {
 338                 bestdiv = _get_maxdiv(table, width, flags);
 339                 *best_parent_rate = clk_hw_round_rate(parent, 1);
 340         }
 341 
 342         return bestdiv;
 343 }
 344 
 345 long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
 346                                unsigned long rate, unsigned long *prate,
 347                                const struct clk_div_table *table,
 348                                u8 width, unsigned long flags)
 349 {
 350         int div;
 351 
 352         div = clk_divider_bestdiv(hw, parent, rate, prate, table, width, flags);
 353 
 354         return DIV_ROUND_UP_ULL((u64)*prate, div);
 355 }
 356 EXPORT_SYMBOL_GPL(divider_round_rate_parent);
 357 
 358 long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
 359                                   unsigned long rate, unsigned long *prate,
 360                                   const struct clk_div_table *table, u8 width,
 361                                   unsigned long flags, unsigned int val)
 362 {
 363         int div;
 364 
 365         div = _get_div(table, val, flags, width);
 366 
 367         /* Even a read-only clock can propagate a rate change */
 368         if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
 369                 if (!parent)
 370                         return -EINVAL;
 371 
 372                 *prate = clk_hw_round_rate(parent, rate * div);
 373         }
 374 
 375         return DIV_ROUND_UP_ULL((u64)*prate, div);
 376 }
 377 EXPORT_SYMBOL_GPL(divider_ro_round_rate_parent);
 378 
 379 
 380 static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
 381                                 unsigned long *prate)
 382 {
 383         struct clk_divider *divider = to_clk_divider(hw);
 384 
 385         /* if read only, just return current value */
 386         if (divider->flags & CLK_DIVIDER_READ_ONLY) {
 387                 u32 val;
 388 
 389                 val = clk_div_readl(divider) >> divider->shift;
 390                 val &= clk_div_mask(divider->width);
 391 
 392                 return divider_ro_round_rate(hw, rate, prate, divider->table,
 393                                              divider->width, divider->flags,
 394                                              val);
 395         }
 396 
 397         return divider_round_rate(hw, rate, prate, divider->table,
 398                                   divider->width, divider->flags);
 399 }
 400 
 401 int divider_get_val(unsigned long rate, unsigned long parent_rate,
 402                     const struct clk_div_table *table, u8 width,
 403                     unsigned long flags)
 404 {
 405         unsigned int div, value;
 406 
 407         div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
 408 
 409         if (!_is_valid_div(table, div, flags))
 410                 return -EINVAL;
 411 
 412         value = _get_val(table, div, flags, width);
 413 
 414         return min_t(unsigned int, value, clk_div_mask(width));
 415 }
 416 EXPORT_SYMBOL_GPL(divider_get_val);
 417 
 418 static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 419                                 unsigned long parent_rate)
 420 {
 421         struct clk_divider *divider = to_clk_divider(hw);
 422         int value;
 423         unsigned long flags = 0;
 424         u32 val;
 425 
 426         value = divider_get_val(rate, parent_rate, divider->table,
 427                                 divider->width, divider->flags);
 428         if (value < 0)
 429                 return value;
 430 
 431         if (divider->lock)
 432                 spin_lock_irqsave(divider->lock, flags);
 433         else
 434                 __acquire(divider->lock);
 435 
 436         if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
 437                 val = clk_div_mask(divider->width) << (divider->shift + 16);
 438         } else {
 439                 val = clk_div_readl(divider);
 440                 val &= ~(clk_div_mask(divider->width) << divider->shift);
 441         }
 442         val |= (u32)value << divider->shift;
 443         clk_div_writel(divider, val);
 444 
 445         if (divider->lock)
 446                 spin_unlock_irqrestore(divider->lock, flags);
 447         else
 448                 __release(divider->lock);
 449 
 450         return 0;
 451 }
 452 
 453 const struct clk_ops clk_divider_ops = {
 454         .recalc_rate = clk_divider_recalc_rate,
 455         .round_rate = clk_divider_round_rate,
 456         .set_rate = clk_divider_set_rate,
 457 };
 458 EXPORT_SYMBOL_GPL(clk_divider_ops);
 459 
 460 const struct clk_ops clk_divider_ro_ops = {
 461         .recalc_rate = clk_divider_recalc_rate,
 462         .round_rate = clk_divider_round_rate,
 463 };
 464 EXPORT_SYMBOL_GPL(clk_divider_ro_ops);
 465 
 466 static struct clk_hw *_register_divider(struct device *dev, const char *name,
 467                 const char *parent_name, unsigned long flags,
 468                 void __iomem *reg, u8 shift, u8 width,
 469                 u8 clk_divider_flags, const struct clk_div_table *table,
 470                 spinlock_t *lock)
 471 {
 472         struct clk_divider *div;
 473         struct clk_hw *hw;
 474         struct clk_init_data init;
 475         int ret;
 476 
 477         if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) {
 478                 if (width + shift > 16) {
 479                         pr_warn("divider value exceeds LOWORD field\n");
 480                         return ERR_PTR(-EINVAL);
 481                 }
 482         }
 483 
 484         /* allocate the divider */
 485         div = kzalloc(sizeof(*div), GFP_KERNEL);
 486         if (!div)
 487                 return ERR_PTR(-ENOMEM);
 488 
 489         init.name = name;
 490         if (clk_divider_flags & CLK_DIVIDER_READ_ONLY)
 491                 init.ops = &clk_divider_ro_ops;
 492         else
 493                 init.ops = &clk_divider_ops;
 494         init.flags = flags;
 495         init.parent_names = (parent_name ? &parent_name: NULL);
 496         init.num_parents = (parent_name ? 1 : 0);
 497 
 498         /* struct clk_divider assignments */
 499         div->reg = reg;
 500         div->shift = shift;
 501         div->width = width;
 502         div->flags = clk_divider_flags;
 503         div->lock = lock;
 504         div->hw.init = &init;
 505         div->table = table;
 506 
 507         /* register the clock */
 508         hw = &div->hw;
 509         ret = clk_hw_register(dev, hw);
 510         if (ret) {
 511                 kfree(div);
 512                 hw = ERR_PTR(ret);
 513         }
 514 
 515         return hw;
 516 }
 517 
 518 /**
 519  * clk_register_divider - register a divider clock with the clock framework
 520  * @dev: device registering this clock
 521  * @name: name of this clock
 522  * @parent_name: name of clock's parent
 523  * @flags: framework-specific flags
 524  * @reg: register address to adjust divider
 525  * @shift: number of bits to shift the bitfield
 526  * @width: width of the bitfield
 527  * @clk_divider_flags: divider-specific flags for this clock
 528  * @lock: shared register lock for this clock
 529  */
 530 struct clk *clk_register_divider(struct device *dev, const char *name,
 531                 const char *parent_name, unsigned long flags,
 532                 void __iomem *reg, u8 shift, u8 width,
 533                 u8 clk_divider_flags, spinlock_t *lock)
 534 {
 535         struct clk_hw *hw;
 536 
 537         hw =  _register_divider(dev, name, parent_name, flags, reg, shift,
 538                         width, clk_divider_flags, NULL, lock);
 539         if (IS_ERR(hw))
 540                 return ERR_CAST(hw);
 541         return hw->clk;
 542 }
 543 EXPORT_SYMBOL_GPL(clk_register_divider);
 544 
 545 /**
 546  * clk_hw_register_divider - register a divider clock with the clock framework
 547  * @dev: device registering this clock
 548  * @name: name of this clock
 549  * @parent_name: name of clock's parent
 550  * @flags: framework-specific flags
 551  * @reg: register address to adjust divider
 552  * @shift: number of bits to shift the bitfield
 553  * @width: width of the bitfield
 554  * @clk_divider_flags: divider-specific flags for this clock
 555  * @lock: shared register lock for this clock
 556  */
 557 struct clk_hw *clk_hw_register_divider(struct device *dev, const char *name,
 558                 const char *parent_name, unsigned long flags,
 559                 void __iomem *reg, u8 shift, u8 width,
 560                 u8 clk_divider_flags, spinlock_t *lock)
 561 {
 562         return _register_divider(dev, name, parent_name, flags, reg, shift,
 563                         width, clk_divider_flags, NULL, lock);
 564 }
 565 EXPORT_SYMBOL_GPL(clk_hw_register_divider);
 566 
 567 /**
 568  * clk_register_divider_table - register a table based divider clock with
 569  * the clock framework
 570  * @dev: device registering this clock
 571  * @name: name of this clock
 572  * @parent_name: name of clock's parent
 573  * @flags: framework-specific flags
 574  * @reg: register address to adjust divider
 575  * @shift: number of bits to shift the bitfield
 576  * @width: width of the bitfield
 577  * @clk_divider_flags: divider-specific flags for this clock
 578  * @table: array of divider/value pairs ending with a div set to 0
 579  * @lock: shared register lock for this clock
 580  */
 581 struct clk *clk_register_divider_table(struct device *dev, const char *name,
 582                 const char *parent_name, unsigned long flags,
 583                 void __iomem *reg, u8 shift, u8 width,
 584                 u8 clk_divider_flags, const struct clk_div_table *table,
 585                 spinlock_t *lock)
 586 {
 587         struct clk_hw *hw;
 588 
 589         hw =  _register_divider(dev, name, parent_name, flags, reg, shift,
 590                         width, clk_divider_flags, table, lock);
 591         if (IS_ERR(hw))
 592                 return ERR_CAST(hw);
 593         return hw->clk;
 594 }
 595 EXPORT_SYMBOL_GPL(clk_register_divider_table);
 596 
 597 /**
 598  * clk_hw_register_divider_table - register a table based divider clock with
 599  * the clock framework
 600  * @dev: device registering this clock
 601  * @name: name of this clock
 602  * @parent_name: name of clock's parent
 603  * @flags: framework-specific flags
 604  * @reg: register address to adjust divider
 605  * @shift: number of bits to shift the bitfield
 606  * @width: width of the bitfield
 607  * @clk_divider_flags: divider-specific flags for this clock
 608  * @table: array of divider/value pairs ending with a div set to 0
 609  * @lock: shared register lock for this clock
 610  */
 611 struct clk_hw *clk_hw_register_divider_table(struct device *dev,
 612                 const char *name, const char *parent_name, unsigned long flags,
 613                 void __iomem *reg, u8 shift, u8 width,
 614                 u8 clk_divider_flags, const struct clk_div_table *table,
 615                 spinlock_t *lock)
 616 {
 617         return _register_divider(dev, name, parent_name, flags, reg, shift,
 618                         width, clk_divider_flags, table, lock);
 619 }
 620 EXPORT_SYMBOL_GPL(clk_hw_register_divider_table);
 621 
 622 void clk_unregister_divider(struct clk *clk)
 623 {
 624         struct clk_divider *div;
 625         struct clk_hw *hw;
 626 
 627         hw = __clk_get_hw(clk);
 628         if (!hw)
 629                 return;
 630 
 631         div = to_clk_divider(hw);
 632 
 633         clk_unregister(clk);
 634         kfree(div);
 635 }
 636 EXPORT_SYMBOL_GPL(clk_unregister_divider);
 637 
 638 /**
 639  * clk_hw_unregister_divider - unregister a clk divider
 640  * @hw: hardware-specific clock data to unregister
 641  */
 642 void clk_hw_unregister_divider(struct clk_hw *hw)
 643 {
 644         struct clk_divider *div;
 645 
 646         div = to_clk_divider(hw);
 647 
 648         clk_hw_unregister(hw);
 649         kfree(div);
 650 }
 651 EXPORT_SYMBOL_GPL(clk_hw_unregister_divider);

/* [<][>][^][v][top][bottom][index][help] */