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