root/drivers/clk/ti/divider.c

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

DEFINITIONS

This source file includes following definitions.
  1. _get_table_maxdiv
  2. _get_maxdiv
  3. _get_table_div
  4. _get_div
  5. _get_table_val
  6. _get_val
  7. ti_clk_divider_recalc_rate
  8. _is_valid_table_div
  9. _is_valid_div
  10. _div_round_up
  11. _div_round
  12. ti_clk_divider_bestdiv
  13. ti_clk_divider_round_rate
  14. ti_clk_divider_set_rate
  15. clk_divider_save_context
  16. clk_divider_restore_context
  17. _register_divider
  18. ti_clk_parse_divider_data
  19. ti_clk_get_div_table
  20. _get_divider_width
  21. ti_clk_divider_populate
  22. of_ti_divider_clk_setup
  23. of_ti_composite_divider_clk_setup

   1 /*
   2  * TI Divider Clock
   3  *
   4  * Copyright (C) 2013 Texas Instruments, Inc.
   5  *
   6  * Tero Kristo <t-kristo@ti.com>
   7  *
   8  * This program is free software; you can redistribute it and/or modify
   9  * it under the terms of the GNU General Public License version 2 as
  10  * published by the Free Software Foundation.
  11  *
  12  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
  13  * kind, whether express or implied; without even the implied warranty
  14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15  * GNU General Public License for more details.
  16  */
  17 
  18 #include <linux/clk-provider.h>
  19 #include <linux/slab.h>
  20 #include <linux/err.h>
  21 #include <linux/of.h>
  22 #include <linux/of_address.h>
  23 #include <linux/clk/ti.h>
  24 #include "clock.h"
  25 
  26 #undef pr_fmt
  27 #define pr_fmt(fmt) "%s: " fmt, __func__
  28 
  29 #define div_mask(d)     ((1 << ((d)->width)) - 1)
  30 
  31 static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
  32 {
  33         unsigned int maxdiv = 0;
  34         const struct clk_div_table *clkt;
  35 
  36         for (clkt = table; clkt->div; clkt++)
  37                 if (clkt->div > maxdiv)
  38                         maxdiv = clkt->div;
  39         return maxdiv;
  40 }
  41 
  42 static unsigned int _get_maxdiv(struct clk_omap_divider *divider)
  43 {
  44         if (divider->flags & CLK_DIVIDER_ONE_BASED)
  45                 return div_mask(divider);
  46         if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
  47                 return 1 << div_mask(divider);
  48         if (divider->table)
  49                 return _get_table_maxdiv(divider->table);
  50         return div_mask(divider) + 1;
  51 }
  52 
  53 static unsigned int _get_table_div(const struct clk_div_table *table,
  54                                    unsigned int val)
  55 {
  56         const struct clk_div_table *clkt;
  57 
  58         for (clkt = table; clkt->div; clkt++)
  59                 if (clkt->val == val)
  60                         return clkt->div;
  61         return 0;
  62 }
  63 
  64 static unsigned int _get_div(struct clk_omap_divider *divider, unsigned int val)
  65 {
  66         if (divider->flags & CLK_DIVIDER_ONE_BASED)
  67                 return val;
  68         if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
  69                 return 1 << val;
  70         if (divider->table)
  71                 return _get_table_div(divider->table, val);
  72         return val + 1;
  73 }
  74 
  75 static unsigned int _get_table_val(const struct clk_div_table *table,
  76                                    unsigned int div)
  77 {
  78         const struct clk_div_table *clkt;
  79 
  80         for (clkt = table; clkt->div; clkt++)
  81                 if (clkt->div == div)
  82                         return clkt->val;
  83         return 0;
  84 }
  85 
  86 static unsigned int _get_val(struct clk_omap_divider *divider, u8 div)
  87 {
  88         if (divider->flags & CLK_DIVIDER_ONE_BASED)
  89                 return div;
  90         if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
  91                 return __ffs(div);
  92         if (divider->table)
  93                 return  _get_table_val(divider->table, div);
  94         return div - 1;
  95 }
  96 
  97 static unsigned long ti_clk_divider_recalc_rate(struct clk_hw *hw,
  98                                                 unsigned long parent_rate)
  99 {
 100         struct clk_omap_divider *divider = to_clk_omap_divider(hw);
 101         unsigned int div, val;
 102 
 103         val = ti_clk_ll_ops->clk_readl(&divider->reg) >> divider->shift;
 104         val &= div_mask(divider);
 105 
 106         div = _get_div(divider, val);
 107         if (!div) {
 108                 WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO),
 109                      "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
 110                      clk_hw_get_name(hw));
 111                 return parent_rate;
 112         }
 113 
 114         return DIV_ROUND_UP(parent_rate, div);
 115 }
 116 
 117 /*
 118  * The reverse of DIV_ROUND_UP: The maximum number which
 119  * divided by m is r
 120  */
 121 #define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
 122 
 123 static bool _is_valid_table_div(const struct clk_div_table *table,
 124                                 unsigned int div)
 125 {
 126         const struct clk_div_table *clkt;
 127 
 128         for (clkt = table; clkt->div; clkt++)
 129                 if (clkt->div == div)
 130                         return true;
 131         return false;
 132 }
 133 
 134 static bool _is_valid_div(struct clk_omap_divider *divider, unsigned int div)
 135 {
 136         if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
 137                 return is_power_of_2(div);
 138         if (divider->table)
 139                 return _is_valid_table_div(divider->table, div);
 140         return true;
 141 }
 142 
 143 static int _div_round_up(const struct clk_div_table *table,
 144                          unsigned long parent_rate, unsigned long rate)
 145 {
 146         const struct clk_div_table *clkt;
 147         int up = INT_MAX;
 148         int div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
 149 
 150         for (clkt = table; clkt->div; clkt++) {
 151                 if (clkt->div == div)
 152                         return clkt->div;
 153                 else if (clkt->div < div)
 154                         continue;
 155 
 156                 if ((clkt->div - div) < (up - div))
 157                         up = clkt->div;
 158         }
 159 
 160         return up;
 161 }
 162 
 163 static int _div_round(const struct clk_div_table *table,
 164                       unsigned long parent_rate, unsigned long rate)
 165 {
 166         if (!table)
 167                 return DIV_ROUND_UP(parent_rate, rate);
 168 
 169         return _div_round_up(table, parent_rate, rate);
 170 }
 171 
 172 static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
 173                                   unsigned long *best_parent_rate)
 174 {
 175         struct clk_omap_divider *divider = to_clk_omap_divider(hw);
 176         int i, bestdiv = 0;
 177         unsigned long parent_rate, best = 0, now, maxdiv;
 178         unsigned long parent_rate_saved = *best_parent_rate;
 179 
 180         if (!rate)
 181                 rate = 1;
 182 
 183         maxdiv = _get_maxdiv(divider);
 184 
 185         if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
 186                 parent_rate = *best_parent_rate;
 187                 bestdiv = _div_round(divider->table, parent_rate, rate);
 188                 bestdiv = bestdiv == 0 ? 1 : bestdiv;
 189                 bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
 190                 return bestdiv;
 191         }
 192 
 193         /*
 194          * The maximum divider we can use without overflowing
 195          * unsigned long in rate * i below
 196          */
 197         maxdiv = min(ULONG_MAX / rate, maxdiv);
 198 
 199         for (i = 1; i <= maxdiv; i++) {
 200                 if (!_is_valid_div(divider, i))
 201                         continue;
 202                 if (rate * i == parent_rate_saved) {
 203                         /*
 204                          * It's the most ideal case if the requested rate can be
 205                          * divided from parent clock without needing to change
 206                          * parent rate, so return the divider immediately.
 207                          */
 208                         *best_parent_rate = parent_rate_saved;
 209                         return i;
 210                 }
 211                 parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
 212                                 MULT_ROUND_UP(rate, i));
 213                 now = DIV_ROUND_UP(parent_rate, i);
 214                 if (now <= rate && now > best) {
 215                         bestdiv = i;
 216                         best = now;
 217                         *best_parent_rate = parent_rate;
 218                 }
 219         }
 220 
 221         if (!bestdiv) {
 222                 bestdiv = _get_maxdiv(divider);
 223                 *best_parent_rate =
 224                         clk_hw_round_rate(clk_hw_get_parent(hw), 1);
 225         }
 226 
 227         return bestdiv;
 228 }
 229 
 230 static long ti_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
 231                                       unsigned long *prate)
 232 {
 233         int div;
 234         div = ti_clk_divider_bestdiv(hw, rate, prate);
 235 
 236         return DIV_ROUND_UP(*prate, div);
 237 }
 238 
 239 static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 240                                    unsigned long parent_rate)
 241 {
 242         struct clk_omap_divider *divider;
 243         unsigned int div, value;
 244         u32 val;
 245 
 246         if (!hw || !rate)
 247                 return -EINVAL;
 248 
 249         divider = to_clk_omap_divider(hw);
 250 
 251         div = DIV_ROUND_UP(parent_rate, rate);
 252         value = _get_val(divider, div);
 253 
 254         if (value > div_mask(divider))
 255                 value = div_mask(divider);
 256 
 257         if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
 258                 val = div_mask(divider) << (divider->shift + 16);
 259         } else {
 260                 val = ti_clk_ll_ops->clk_readl(&divider->reg);
 261                 val &= ~(div_mask(divider) << divider->shift);
 262         }
 263         val |= value << divider->shift;
 264         ti_clk_ll_ops->clk_writel(val, &divider->reg);
 265 
 266         ti_clk_latch(&divider->reg, divider->latch);
 267 
 268         return 0;
 269 }
 270 
 271 /**
 272  * clk_divider_save_context - Save the divider value
 273  * @hw: pointer  struct clk_hw
 274  *
 275  * Save the divider value
 276  */
 277 static int clk_divider_save_context(struct clk_hw *hw)
 278 {
 279         struct clk_omap_divider *divider = to_clk_omap_divider(hw);
 280         u32 val;
 281 
 282         val = ti_clk_ll_ops->clk_readl(&divider->reg) >> divider->shift;
 283         divider->context = val & div_mask(divider);
 284 
 285         return 0;
 286 }
 287 
 288 /**
 289  * clk_divider_restore_context - restore the saved the divider value
 290  * @hw: pointer  struct clk_hw
 291  *
 292  * Restore the saved the divider value
 293  */
 294 static void clk_divider_restore_context(struct clk_hw *hw)
 295 {
 296         struct clk_omap_divider *divider = to_clk_omap_divider(hw);
 297         u32 val;
 298 
 299         val = ti_clk_ll_ops->clk_readl(&divider->reg);
 300         val &= ~(div_mask(divider) << divider->shift);
 301         val |= divider->context << divider->shift;
 302         ti_clk_ll_ops->clk_writel(val, &divider->reg);
 303 }
 304 
 305 const struct clk_ops ti_clk_divider_ops = {
 306         .recalc_rate = ti_clk_divider_recalc_rate,
 307         .round_rate = ti_clk_divider_round_rate,
 308         .set_rate = ti_clk_divider_set_rate,
 309         .save_context = clk_divider_save_context,
 310         .restore_context = clk_divider_restore_context,
 311 };
 312 
 313 static struct clk *_register_divider(struct device *dev, const char *name,
 314                                      const char *parent_name,
 315                                      unsigned long flags,
 316                                      struct clk_omap_reg *reg,
 317                                      u8 shift, u8 width, s8 latch,
 318                                      u8 clk_divider_flags,
 319                                      const struct clk_div_table *table)
 320 {
 321         struct clk_omap_divider *div;
 322         struct clk *clk;
 323         struct clk_init_data init;
 324 
 325         if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) {
 326                 if (width + shift > 16) {
 327                         pr_warn("divider value exceeds LOWORD field\n");
 328                         return ERR_PTR(-EINVAL);
 329                 }
 330         }
 331 
 332         /* allocate the divider */
 333         div = kzalloc(sizeof(*div), GFP_KERNEL);
 334         if (!div)
 335                 return ERR_PTR(-ENOMEM);
 336 
 337         init.name = name;
 338         init.ops = &ti_clk_divider_ops;
 339         init.flags = flags;
 340         init.parent_names = (parent_name ? &parent_name : NULL);
 341         init.num_parents = (parent_name ? 1 : 0);
 342 
 343         /* struct clk_divider assignments */
 344         memcpy(&div->reg, reg, sizeof(*reg));
 345         div->shift = shift;
 346         div->width = width;
 347         div->latch = latch;
 348         div->flags = clk_divider_flags;
 349         div->hw.init = &init;
 350         div->table = table;
 351 
 352         /* register the clock */
 353         clk = ti_clk_register(dev, &div->hw, name);
 354 
 355         if (IS_ERR(clk))
 356                 kfree(div);
 357 
 358         return clk;
 359 }
 360 
 361 int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
 362                               u8 flags, u8 *width,
 363                               const struct clk_div_table **table)
 364 {
 365         int valid_div = 0;
 366         u32 val;
 367         int div;
 368         int i;
 369         struct clk_div_table *tmp;
 370 
 371         if (!div_table) {
 372                 if (flags & CLKF_INDEX_STARTS_AT_ONE)
 373                         val = 1;
 374                 else
 375                         val = 0;
 376 
 377                 div = 1;
 378 
 379                 while (div < max_div) {
 380                         if (flags & CLKF_INDEX_POWER_OF_TWO)
 381                                 div <<= 1;
 382                         else
 383                                 div++;
 384                         val++;
 385                 }
 386 
 387                 *width = fls(val);
 388                 *table = NULL;
 389 
 390                 return 0;
 391         }
 392 
 393         i = 0;
 394 
 395         while (!num_dividers || i < num_dividers) {
 396                 if (div_table[i] == -1)
 397                         break;
 398                 if (div_table[i])
 399                         valid_div++;
 400                 i++;
 401         }
 402 
 403         num_dividers = i;
 404 
 405         tmp = kcalloc(valid_div + 1, sizeof(*tmp), GFP_KERNEL);
 406         if (!tmp) {
 407                 *table = ERR_PTR(-ENOMEM);
 408                 return -ENOMEM;
 409         }
 410 
 411         valid_div = 0;
 412         *width = 0;
 413 
 414         for (i = 0; i < num_dividers; i++)
 415                 if (div_table[i] > 0) {
 416                         tmp[valid_div].div = div_table[i];
 417                         tmp[valid_div].val = i;
 418                         valid_div++;
 419                         *width = i;
 420                 }
 421 
 422         *width = fls(*width);
 423         *table = tmp;
 424 
 425         return 0;
 426 }
 427 
 428 static struct clk_div_table *
 429 __init ti_clk_get_div_table(struct device_node *node)
 430 {
 431         struct clk_div_table *table;
 432         const __be32 *divspec;
 433         u32 val;
 434         u32 num_div;
 435         u32 valid_div;
 436         int i;
 437 
 438         divspec = of_get_property(node, "ti,dividers", &num_div);
 439 
 440         if (!divspec)
 441                 return NULL;
 442 
 443         num_div /= 4;
 444 
 445         valid_div = 0;
 446 
 447         /* Determine required size for divider table */
 448         for (i = 0; i < num_div; i++) {
 449                 of_property_read_u32_index(node, "ti,dividers", i, &val);
 450                 if (val)
 451                         valid_div++;
 452         }
 453 
 454         if (!valid_div) {
 455                 pr_err("no valid dividers for %pOFn table\n", node);
 456                 return ERR_PTR(-EINVAL);
 457         }
 458 
 459         table = kcalloc(valid_div + 1, sizeof(*table), GFP_KERNEL);
 460 
 461         if (!table)
 462                 return ERR_PTR(-ENOMEM);
 463 
 464         valid_div = 0;
 465 
 466         for (i = 0; i < num_div; i++) {
 467                 of_property_read_u32_index(node, "ti,dividers", i, &val);
 468                 if (val) {
 469                         table[valid_div].div = val;
 470                         table[valid_div].val = i;
 471                         valid_div++;
 472                 }
 473         }
 474 
 475         return table;
 476 }
 477 
 478 static int _get_divider_width(struct device_node *node,
 479                               const struct clk_div_table *table,
 480                               u8 flags)
 481 {
 482         u32 min_div;
 483         u32 max_div;
 484         u32 val = 0;
 485         u32 div;
 486 
 487         if (!table) {
 488                 /* Clk divider table not provided, determine min/max divs */
 489                 if (of_property_read_u32(node, "ti,min-div", &min_div))
 490                         min_div = 1;
 491 
 492                 if (of_property_read_u32(node, "ti,max-div", &max_div)) {
 493                         pr_err("no max-div for %pOFn!\n", node);
 494                         return -EINVAL;
 495                 }
 496 
 497                 /* Determine bit width for the field */
 498                 if (flags & CLK_DIVIDER_ONE_BASED)
 499                         val = 1;
 500 
 501                 div = min_div;
 502 
 503                 while (div < max_div) {
 504                         if (flags & CLK_DIVIDER_POWER_OF_TWO)
 505                                 div <<= 1;
 506                         else
 507                                 div++;
 508                         val++;
 509                 }
 510         } else {
 511                 div = 0;
 512 
 513                 while (table[div].div) {
 514                         val = table[div].val;
 515                         div++;
 516                 }
 517         }
 518 
 519         return fls(val);
 520 }
 521 
 522 static int __init ti_clk_divider_populate(struct device_node *node,
 523         struct clk_omap_reg *reg, const struct clk_div_table **table,
 524         u32 *flags, u8 *div_flags, u8 *width, u8 *shift, s8 *latch)
 525 {
 526         u32 val;
 527         int ret;
 528 
 529         ret = ti_clk_get_reg_addr(node, 0, reg);
 530         if (ret)
 531                 return ret;
 532 
 533         if (!of_property_read_u32(node, "ti,bit-shift", &val))
 534                 *shift = val;
 535         else
 536                 *shift = 0;
 537 
 538         if (latch) {
 539                 if (!of_property_read_u32(node, "ti,latch-bit", &val))
 540                         *latch = val;
 541                 else
 542                         *latch = -EINVAL;
 543         }
 544 
 545         *flags = 0;
 546         *div_flags = 0;
 547 
 548         if (of_property_read_bool(node, "ti,index-starts-at-one"))
 549                 *div_flags |= CLK_DIVIDER_ONE_BASED;
 550 
 551         if (of_property_read_bool(node, "ti,index-power-of-two"))
 552                 *div_flags |= CLK_DIVIDER_POWER_OF_TWO;
 553 
 554         if (of_property_read_bool(node, "ti,set-rate-parent"))
 555                 *flags |= CLK_SET_RATE_PARENT;
 556 
 557         *table = ti_clk_get_div_table(node);
 558 
 559         if (IS_ERR(*table))
 560                 return PTR_ERR(*table);
 561 
 562         *width = _get_divider_width(node, *table, *div_flags);
 563 
 564         return 0;
 565 }
 566 
 567 /**
 568  * of_ti_divider_clk_setup - Setup function for simple div rate clock
 569  * @node: device node for this clock
 570  *
 571  * Sets up a basic divider clock.
 572  */
 573 static void __init of_ti_divider_clk_setup(struct device_node *node)
 574 {
 575         struct clk *clk;
 576         const char *parent_name;
 577         struct clk_omap_reg reg;
 578         u8 clk_divider_flags = 0;
 579         u8 width = 0;
 580         u8 shift = 0;
 581         s8 latch = -EINVAL;
 582         const struct clk_div_table *table = NULL;
 583         u32 flags = 0;
 584 
 585         parent_name = of_clk_get_parent_name(node, 0);
 586 
 587         if (ti_clk_divider_populate(node, &reg, &table, &flags,
 588                                     &clk_divider_flags, &width, &shift, &latch))
 589                 goto cleanup;
 590 
 591         clk = _register_divider(NULL, node->name, parent_name, flags, &reg,
 592                                 shift, width, latch, clk_divider_flags, table);
 593 
 594         if (!IS_ERR(clk)) {
 595                 of_clk_add_provider(node, of_clk_src_simple_get, clk);
 596                 of_ti_clk_autoidle_setup(node);
 597                 return;
 598         }
 599 
 600 cleanup:
 601         kfree(table);
 602 }
 603 CLK_OF_DECLARE(divider_clk, "ti,divider-clock", of_ti_divider_clk_setup);
 604 
 605 static void __init of_ti_composite_divider_clk_setup(struct device_node *node)
 606 {
 607         struct clk_omap_divider *div;
 608         u32 val;
 609 
 610         div = kzalloc(sizeof(*div), GFP_KERNEL);
 611         if (!div)
 612                 return;
 613 
 614         if (ti_clk_divider_populate(node, &div->reg, &div->table, &val,
 615                                     &div->flags, &div->width, &div->shift,
 616                                     NULL) < 0)
 617                 goto cleanup;
 618 
 619         if (!ti_clk_add_component(node, &div->hw, CLK_COMPONENT_TYPE_DIVIDER))
 620                 return;
 621 
 622 cleanup:
 623         kfree(div->table);
 624         kfree(div);
 625 }
 626 CLK_OF_DECLARE(ti_composite_divider_clk, "ti,composite-divider-clock",
 627                of_ti_composite_divider_clk_setup);

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