linux/drivers/clk/ti/divider.c
<<
>>
Prefs
   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
  31static 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
  42static 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
  53static 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
  64static 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
  75static 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
  86static 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
  97static 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
 123static 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
 134static 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
 143static 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
 163static 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
 172static 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
 230static 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
 239static 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
 271const struct clk_ops ti_clk_divider_ops = {
 272        .recalc_rate = ti_clk_divider_recalc_rate,
 273        .round_rate = ti_clk_divider_round_rate,
 274        .set_rate = ti_clk_divider_set_rate,
 275};
 276
 277static struct clk *_register_divider(struct device *dev, const char *name,
 278                                     const char *parent_name,
 279                                     unsigned long flags,
 280                                     struct clk_omap_reg *reg,
 281                                     u8 shift, u8 width, s8 latch,
 282                                     u8 clk_divider_flags,
 283                                     const struct clk_div_table *table)
 284{
 285        struct clk_omap_divider *div;
 286        struct clk *clk;
 287        struct clk_init_data init;
 288
 289        if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) {
 290                if (width + shift > 16) {
 291                        pr_warn("divider value exceeds LOWORD field\n");
 292                        return ERR_PTR(-EINVAL);
 293                }
 294        }
 295
 296        /* allocate the divider */
 297        div = kzalloc(sizeof(*div), GFP_KERNEL);
 298        if (!div)
 299                return ERR_PTR(-ENOMEM);
 300
 301        init.name = name;
 302        init.ops = &ti_clk_divider_ops;
 303        init.flags = flags | CLK_IS_BASIC;
 304        init.parent_names = (parent_name ? &parent_name : NULL);
 305        init.num_parents = (parent_name ? 1 : 0);
 306
 307        /* struct clk_divider assignments */
 308        memcpy(&div->reg, reg, sizeof(*reg));
 309        div->shift = shift;
 310        div->width = width;
 311        div->latch = latch;
 312        div->flags = clk_divider_flags;
 313        div->hw.init = &init;
 314        div->table = table;
 315
 316        /* register the clock */
 317        clk = ti_clk_register(dev, &div->hw, name);
 318
 319        if (IS_ERR(clk))
 320                kfree(div);
 321
 322        return clk;
 323}
 324
 325int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
 326                              u8 flags, u8 *width,
 327                              const struct clk_div_table **table)
 328{
 329        int valid_div = 0;
 330        u32 val;
 331        int div;
 332        int i;
 333        struct clk_div_table *tmp;
 334
 335        if (!div_table) {
 336                if (flags & CLKF_INDEX_STARTS_AT_ONE)
 337                        val = 1;
 338                else
 339                        val = 0;
 340
 341                div = 1;
 342
 343                while (div < max_div) {
 344                        if (flags & CLKF_INDEX_POWER_OF_TWO)
 345                                div <<= 1;
 346                        else
 347                                div++;
 348                        val++;
 349                }
 350
 351                *width = fls(val);
 352                *table = NULL;
 353
 354                return 0;
 355        }
 356
 357        i = 0;
 358
 359        while (!num_dividers || i < num_dividers) {
 360                if (div_table[i] == -1)
 361                        break;
 362                if (div_table[i])
 363                        valid_div++;
 364                i++;
 365        }
 366
 367        num_dividers = i;
 368
 369        tmp = kcalloc(valid_div + 1, sizeof(*tmp), GFP_KERNEL);
 370        if (!tmp)
 371                return -ENOMEM;
 372
 373        valid_div = 0;
 374        *width = 0;
 375
 376        for (i = 0; i < num_dividers; i++)
 377                if (div_table[i] > 0) {
 378                        tmp[valid_div].div = div_table[i];
 379                        tmp[valid_div].val = i;
 380                        valid_div++;
 381                        *width = i;
 382                }
 383
 384        *width = fls(*width);
 385        *table = tmp;
 386
 387        return 0;
 388}
 389
 390static const struct clk_div_table *
 391_get_div_table_from_setup(struct ti_clk_divider *setup, u8 *width)
 392{
 393        const struct clk_div_table *table = NULL;
 394
 395        ti_clk_parse_divider_data(setup->dividers, setup->num_dividers,
 396                                  setup->max_div, setup->flags, width,
 397                                  &table);
 398
 399        return table;
 400}
 401
 402struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup)
 403{
 404        struct clk_omap_divider *div;
 405        struct clk_omap_reg *reg;
 406
 407        if (!setup)
 408                return NULL;
 409
 410        div = kzalloc(sizeof(*div), GFP_KERNEL);
 411        if (!div)
 412                return ERR_PTR(-ENOMEM);
 413
 414        reg = (struct clk_omap_reg *)&div->reg;
 415        reg->index = setup->module;
 416        reg->offset = setup->reg;
 417
 418        if (setup->flags & CLKF_INDEX_STARTS_AT_ONE)
 419                div->flags |= CLK_DIVIDER_ONE_BASED;
 420
 421        if (setup->flags & CLKF_INDEX_POWER_OF_TWO)
 422                div->flags |= CLK_DIVIDER_POWER_OF_TWO;
 423
 424        div->table = _get_div_table_from_setup(setup, &div->width);
 425
 426        div->shift = setup->bit_shift;
 427        div->latch = -EINVAL;
 428
 429        return &div->hw;
 430}
 431
 432struct clk *ti_clk_register_divider(struct ti_clk *setup)
 433{
 434        struct ti_clk_divider *div = setup->data;
 435        struct clk_omap_reg reg = {
 436                .index = div->module,
 437                .offset = div->reg,
 438        };
 439        u8 width;
 440        u32 flags = 0;
 441        u8 div_flags = 0;
 442        const struct clk_div_table *table;
 443        struct clk *clk;
 444
 445        if (div->flags & CLKF_INDEX_STARTS_AT_ONE)
 446                div_flags |= CLK_DIVIDER_ONE_BASED;
 447
 448        if (div->flags & CLKF_INDEX_POWER_OF_TWO)
 449                div_flags |= CLK_DIVIDER_POWER_OF_TWO;
 450
 451        if (div->flags & CLKF_SET_RATE_PARENT)
 452                flags |= CLK_SET_RATE_PARENT;
 453
 454        table = _get_div_table_from_setup(div, &width);
 455        if (IS_ERR(table))
 456                return (struct clk *)table;
 457
 458        clk = _register_divider(NULL, setup->name, div->parent,
 459                                flags, &reg, div->bit_shift,
 460                                width, -EINVAL, div_flags, table);
 461
 462        if (IS_ERR(clk))
 463                kfree(table);
 464
 465        return clk;
 466}
 467
 468static struct clk_div_table *
 469__init ti_clk_get_div_table(struct device_node *node)
 470{
 471        struct clk_div_table *table;
 472        const __be32 *divspec;
 473        u32 val;
 474        u32 num_div;
 475        u32 valid_div;
 476        int i;
 477
 478        divspec = of_get_property(node, "ti,dividers", &num_div);
 479
 480        if (!divspec)
 481                return NULL;
 482
 483        num_div /= 4;
 484
 485        valid_div = 0;
 486
 487        /* Determine required size for divider table */
 488        for (i = 0; i < num_div; i++) {
 489                of_property_read_u32_index(node, "ti,dividers", i, &val);
 490                if (val)
 491                        valid_div++;
 492        }
 493
 494        if (!valid_div) {
 495                pr_err("no valid dividers for %s table\n", node->name);
 496                return ERR_PTR(-EINVAL);
 497        }
 498
 499        table = kcalloc(valid_div + 1, sizeof(*table), GFP_KERNEL);
 500
 501        if (!table)
 502                return ERR_PTR(-ENOMEM);
 503
 504        valid_div = 0;
 505
 506        for (i = 0; i < num_div; i++) {
 507                of_property_read_u32_index(node, "ti,dividers", i, &val);
 508                if (val) {
 509                        table[valid_div].div = val;
 510                        table[valid_div].val = i;
 511                        valid_div++;
 512                }
 513        }
 514
 515        return table;
 516}
 517
 518static int _get_divider_width(struct device_node *node,
 519                              const struct clk_div_table *table,
 520                              u8 flags)
 521{
 522        u32 min_div;
 523        u32 max_div;
 524        u32 val = 0;
 525        u32 div;
 526
 527        if (!table) {
 528                /* Clk divider table not provided, determine min/max divs */
 529                if (of_property_read_u32(node, "ti,min-div", &min_div))
 530                        min_div = 1;
 531
 532                if (of_property_read_u32(node, "ti,max-div", &max_div)) {
 533                        pr_err("no max-div for %s!\n", node->name);
 534                        return -EINVAL;
 535                }
 536
 537                /* Determine bit width for the field */
 538                if (flags & CLK_DIVIDER_ONE_BASED)
 539                        val = 1;
 540
 541                div = min_div;
 542
 543                while (div < max_div) {
 544                        if (flags & CLK_DIVIDER_POWER_OF_TWO)
 545                                div <<= 1;
 546                        else
 547                                div++;
 548                        val++;
 549                }
 550        } else {
 551                div = 0;
 552
 553                while (table[div].div) {
 554                        val = table[div].val;
 555                        div++;
 556                }
 557        }
 558
 559        return fls(val);
 560}
 561
 562static int __init ti_clk_divider_populate(struct device_node *node,
 563        struct clk_omap_reg *reg, const struct clk_div_table **table,
 564        u32 *flags, u8 *div_flags, u8 *width, u8 *shift, s8 *latch)
 565{
 566        u32 val;
 567        int ret;
 568
 569        ret = ti_clk_get_reg_addr(node, 0, reg);
 570        if (ret)
 571                return ret;
 572
 573        if (!of_property_read_u32(node, "ti,bit-shift", &val))
 574                *shift = val;
 575        else
 576                *shift = 0;
 577
 578        if (latch) {
 579                if (!of_property_read_u32(node, "ti,latch-bit", &val))
 580                        *latch = val;
 581                else
 582                        *latch = -EINVAL;
 583        }
 584
 585        *flags = 0;
 586        *div_flags = 0;
 587
 588        if (of_property_read_bool(node, "ti,index-starts-at-one"))
 589                *div_flags |= CLK_DIVIDER_ONE_BASED;
 590
 591        if (of_property_read_bool(node, "ti,index-power-of-two"))
 592                *div_flags |= CLK_DIVIDER_POWER_OF_TWO;
 593
 594        if (of_property_read_bool(node, "ti,set-rate-parent"))
 595                *flags |= CLK_SET_RATE_PARENT;
 596
 597        *table = ti_clk_get_div_table(node);
 598
 599        if (IS_ERR(*table))
 600                return PTR_ERR(*table);
 601
 602        *width = _get_divider_width(node, *table, *div_flags);
 603
 604        return 0;
 605}
 606
 607/**
 608 * of_ti_divider_clk_setup - Setup function for simple div rate clock
 609 * @node: device node for this clock
 610 *
 611 * Sets up a basic divider clock.
 612 */
 613static void __init of_ti_divider_clk_setup(struct device_node *node)
 614{
 615        struct clk *clk;
 616        const char *parent_name;
 617        struct clk_omap_reg reg;
 618        u8 clk_divider_flags = 0;
 619        u8 width = 0;
 620        u8 shift = 0;
 621        s8 latch = -EINVAL;
 622        const struct clk_div_table *table = NULL;
 623        u32 flags = 0;
 624
 625        parent_name = of_clk_get_parent_name(node, 0);
 626
 627        if (ti_clk_divider_populate(node, &reg, &table, &flags,
 628                                    &clk_divider_flags, &width, &shift, &latch))
 629                goto cleanup;
 630
 631        clk = _register_divider(NULL, node->name, parent_name, flags, &reg,
 632                                shift, width, latch, clk_divider_flags, table);
 633
 634        if (!IS_ERR(clk)) {
 635                of_clk_add_provider(node, of_clk_src_simple_get, clk);
 636                of_ti_clk_autoidle_setup(node);
 637                return;
 638        }
 639
 640cleanup:
 641        kfree(table);
 642}
 643CLK_OF_DECLARE(divider_clk, "ti,divider-clock", of_ti_divider_clk_setup);
 644
 645static void __init of_ti_composite_divider_clk_setup(struct device_node *node)
 646{
 647        struct clk_omap_divider *div;
 648        u32 val;
 649
 650        div = kzalloc(sizeof(*div), GFP_KERNEL);
 651        if (!div)
 652                return;
 653
 654        if (ti_clk_divider_populate(node, &div->reg, &div->table, &val,
 655                                    &div->flags, &div->width, &div->shift,
 656                                    NULL) < 0)
 657                goto cleanup;
 658
 659        if (!ti_clk_add_component(node, &div->hw, CLK_COMPONENT_TYPE_DIVIDER))
 660                return;
 661
 662cleanup:
 663        kfree(div->table);
 664        kfree(div);
 665}
 666CLK_OF_DECLARE(ti_composite_divider_clk, "ti,composite-divider-clock",
 667               of_ti_composite_divider_clk_setup);
 668