linux/drivers/clk/qcom/clk-rcg2.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
   3 *
   4 * This software is licensed under the terms of the GNU General Public
   5 * License version 2, as published by the Free Software Foundation, and
   6 * may be copied, distributed, and modified under those terms.
   7 *
   8 * This program is distributed in the hope that it will be useful,
   9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11 * GNU General Public License for more details.
  12 */
  13
  14#include <linux/kernel.h>
  15#include <linux/bitops.h>
  16#include <linux/err.h>
  17#include <linux/bug.h>
  18#include <linux/export.h>
  19#include <linux/clk-provider.h>
  20#include <linux/delay.h>
  21#include <linux/regmap.h>
  22#include <linux/math64.h>
  23
  24#include <asm/div64.h>
  25
  26#include "clk-rcg.h"
  27
  28#define CMD_REG                 0x0
  29#define CMD_UPDATE              BIT(0)
  30#define CMD_ROOT_EN             BIT(1)
  31#define CMD_DIRTY_CFG           BIT(4)
  32#define CMD_DIRTY_N             BIT(5)
  33#define CMD_DIRTY_M             BIT(6)
  34#define CMD_DIRTY_D             BIT(7)
  35#define CMD_ROOT_OFF            BIT(31)
  36
  37#define CFG_REG                 0x4
  38#define CFG_SRC_DIV_SHIFT       0
  39#define CFG_SRC_SEL_SHIFT       8
  40#define CFG_SRC_SEL_MASK        (0x7 << CFG_SRC_SEL_SHIFT)
  41#define CFG_MODE_SHIFT          12
  42#define CFG_MODE_MASK           (0x3 << CFG_MODE_SHIFT)
  43#define CFG_MODE_DUAL_EDGE      (0x2 << CFG_MODE_SHIFT)
  44
  45#define M_REG                   0x8
  46#define N_REG                   0xc
  47#define D_REG                   0x10
  48
  49static int clk_rcg2_is_enabled(struct clk_hw *hw)
  50{
  51        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
  52        u32 cmd;
  53        int ret;
  54
  55        ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG, &cmd);
  56        if (ret)
  57                return ret;
  58
  59        return (cmd & CMD_ROOT_OFF) == 0;
  60}
  61
  62static u8 clk_rcg2_get_parent(struct clk_hw *hw)
  63{
  64        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
  65        int num_parents = __clk_get_num_parents(hw->clk);
  66        u32 cfg;
  67        int i, ret;
  68
  69        ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
  70        if (ret)
  71                return ret;
  72
  73        cfg &= CFG_SRC_SEL_MASK;
  74        cfg >>= CFG_SRC_SEL_SHIFT;
  75
  76        for (i = 0; i < num_parents; i++)
  77                if (cfg == rcg->parent_map[i])
  78                        return i;
  79
  80        return -EINVAL;
  81}
  82
  83static int update_config(struct clk_rcg2 *rcg)
  84{
  85        int count, ret;
  86        u32 cmd;
  87        struct clk_hw *hw = &rcg->clkr.hw;
  88        const char *name = __clk_get_name(hw->clk);
  89
  90        ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
  91                                 CMD_UPDATE, CMD_UPDATE);
  92        if (ret)
  93                return ret;
  94
  95        /* Wait for update to take effect */
  96        for (count = 500; count > 0; count--) {
  97                ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG, &cmd);
  98                if (ret)
  99                        return ret;
 100                if (!(cmd & CMD_UPDATE))
 101                        return 0;
 102                udelay(1);
 103        }
 104
 105        WARN(1, "%s: rcg didn't update its configuration.", name);
 106        return 0;
 107}
 108
 109static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)
 110{
 111        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 112        int ret;
 113
 114        ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
 115                                 CFG_SRC_SEL_MASK,
 116                                 rcg->parent_map[index] << CFG_SRC_SEL_SHIFT);
 117        if (ret)
 118                return ret;
 119
 120        return update_config(rcg);
 121}
 122
 123/*
 124 * Calculate m/n:d rate
 125 *
 126 *          parent_rate     m
 127 *   rate = ----------- x  ---
 128 *            hid_div       n
 129 */
 130static unsigned long
 131calc_rate(unsigned long rate, u32 m, u32 n, u32 mode, u32 hid_div)
 132{
 133        if (hid_div) {
 134                rate *= 2;
 135                rate /= hid_div + 1;
 136        }
 137
 138        if (mode) {
 139                u64 tmp = rate;
 140                tmp *= m;
 141                do_div(tmp, n);
 142                rate = tmp;
 143        }
 144
 145        return rate;
 146}
 147
 148static unsigned long
 149clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
 150{
 151        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 152        u32 cfg, hid_div, m = 0, n = 0, mode = 0, mask;
 153
 154        regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
 155
 156        if (rcg->mnd_width) {
 157                mask = BIT(rcg->mnd_width) - 1;
 158                regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + M_REG, &m);
 159                m &= mask;
 160                regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + N_REG, &n);
 161                n =  ~n;
 162                n &= mask;
 163                n += m;
 164                mode = cfg & CFG_MODE_MASK;
 165                mode >>= CFG_MODE_SHIFT;
 166        }
 167
 168        mask = BIT(rcg->hid_width) - 1;
 169        hid_div = cfg >> CFG_SRC_DIV_SHIFT;
 170        hid_div &= mask;
 171
 172        return calc_rate(parent_rate, m, n, mode, hid_div);
 173}
 174
 175static const
 176struct freq_tbl *find_freq(const struct freq_tbl *f, unsigned long rate)
 177{
 178        if (!f)
 179                return NULL;
 180
 181        for (; f->freq; f++)
 182                if (rate <= f->freq)
 183                        return f;
 184
 185        /* Default to our fastest rate */
 186        return f - 1;
 187}
 188
 189static long _freq_tbl_determine_rate(struct clk_hw *hw,
 190                const struct freq_tbl *f, unsigned long rate,
 191                unsigned long *p_rate, struct clk **p)
 192{
 193        unsigned long clk_flags;
 194
 195        f = find_freq(f, rate);
 196        if (!f)
 197                return -EINVAL;
 198
 199        clk_flags = __clk_get_flags(hw->clk);
 200        *p = clk_get_parent_by_index(hw->clk, f->src);
 201        if (clk_flags & CLK_SET_RATE_PARENT) {
 202                if (f->pre_div) {
 203                        rate /= 2;
 204                        rate *= f->pre_div + 1;
 205                }
 206
 207                if (f->n) {
 208                        u64 tmp = rate;
 209                        tmp = tmp * f->n;
 210                        do_div(tmp, f->m);
 211                        rate = tmp;
 212                }
 213        } else {
 214                rate =  __clk_get_rate(*p);
 215        }
 216        *p_rate = rate;
 217
 218        return f->freq;
 219}
 220
 221static long clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long rate,
 222                unsigned long *p_rate, struct clk **p)
 223{
 224        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 225
 226        return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
 227}
 228
 229static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
 230{
 231        u32 cfg, mask;
 232        int ret;
 233
 234        if (rcg->mnd_width && f->n) {
 235                mask = BIT(rcg->mnd_width) - 1;
 236                ret = regmap_update_bits(rcg->clkr.regmap,
 237                                rcg->cmd_rcgr + M_REG, mask, f->m);
 238                if (ret)
 239                        return ret;
 240
 241                ret = regmap_update_bits(rcg->clkr.regmap,
 242                                rcg->cmd_rcgr + N_REG, mask, ~(f->n - f->m));
 243                if (ret)
 244                        return ret;
 245
 246                ret = regmap_update_bits(rcg->clkr.regmap,
 247                                rcg->cmd_rcgr + D_REG, mask, ~f->n);
 248                if (ret)
 249                        return ret;
 250        }
 251
 252        mask = BIT(rcg->hid_width) - 1;
 253        mask |= CFG_SRC_SEL_MASK | CFG_MODE_MASK;
 254        cfg = f->pre_div << CFG_SRC_DIV_SHIFT;
 255        cfg |= rcg->parent_map[f->src] << CFG_SRC_SEL_SHIFT;
 256        if (rcg->mnd_width && f->n)
 257                cfg |= CFG_MODE_DUAL_EDGE;
 258        ret = regmap_update_bits(rcg->clkr.regmap,
 259                        rcg->cmd_rcgr + CFG_REG, mask, cfg);
 260        if (ret)
 261                return ret;
 262
 263        return update_config(rcg);
 264}
 265
 266static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate)
 267{
 268        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 269        const struct freq_tbl *f;
 270
 271        f = find_freq(rcg->freq_tbl, rate);
 272        if (!f)
 273                return -EINVAL;
 274
 275        return clk_rcg2_configure(rcg, f);
 276}
 277
 278static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate,
 279                            unsigned long parent_rate)
 280{
 281        return __clk_rcg2_set_rate(hw, rate);
 282}
 283
 284static int clk_rcg2_set_rate_and_parent(struct clk_hw *hw,
 285                unsigned long rate, unsigned long parent_rate, u8 index)
 286{
 287        return __clk_rcg2_set_rate(hw, rate);
 288}
 289
 290const struct clk_ops clk_rcg2_ops = {
 291        .is_enabled = clk_rcg2_is_enabled,
 292        .get_parent = clk_rcg2_get_parent,
 293        .set_parent = clk_rcg2_set_parent,
 294        .recalc_rate = clk_rcg2_recalc_rate,
 295        .determine_rate = clk_rcg2_determine_rate,
 296        .set_rate = clk_rcg2_set_rate,
 297        .set_rate_and_parent = clk_rcg2_set_rate_and_parent,
 298};
 299EXPORT_SYMBOL_GPL(clk_rcg2_ops);
 300
 301struct frac_entry {
 302        int num;
 303        int den;
 304};
 305
 306static const struct frac_entry frac_table_675m[] = {    /* link rate of 270M */
 307        { 52, 295 },    /* 119 M */
 308        { 11, 57 },     /* 130.25 M */
 309        { 63, 307 },    /* 138.50 M */
 310        { 11, 50 },     /* 148.50 M */
 311        { 47, 206 },    /* 154 M */
 312        { 31, 100 },    /* 205.25 M */
 313        { 107, 269 },   /* 268.50 M */
 314        { },
 315};
 316
 317static struct frac_entry frac_table_810m[] = { /* Link rate of 162M */
 318        { 31, 211 },    /* 119 M */
 319        { 32, 199 },    /* 130.25 M */
 320        { 63, 307 },    /* 138.50 M */
 321        { 11, 60 },     /* 148.50 M */
 322        { 50, 263 },    /* 154 M */
 323        { 31, 120 },    /* 205.25 M */
 324        { 119, 359 },   /* 268.50 M */
 325        { },
 326};
 327
 328static int clk_edp_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
 329                              unsigned long parent_rate)
 330{
 331        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 332        struct freq_tbl f = *rcg->freq_tbl;
 333        const struct frac_entry *frac;
 334        int delta = 100000;
 335        s64 src_rate = parent_rate;
 336        s64 request;
 337        u32 mask = BIT(rcg->hid_width) - 1;
 338        u32 hid_div;
 339
 340        if (src_rate == 810000000)
 341                frac = frac_table_810m;
 342        else
 343                frac = frac_table_675m;
 344
 345        for (; frac->num; frac++) {
 346                request = rate;
 347                request *= frac->den;
 348                request = div_s64(request, frac->num);
 349                if ((src_rate < (request - delta)) ||
 350                    (src_rate > (request + delta)))
 351                        continue;
 352
 353                regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
 354                                &hid_div);
 355                f.pre_div = hid_div;
 356                f.pre_div >>= CFG_SRC_DIV_SHIFT;
 357                f.pre_div &= mask;
 358                f.m = frac->num;
 359                f.n = frac->den;
 360
 361                return clk_rcg2_configure(rcg, &f);
 362        }
 363
 364        return -EINVAL;
 365}
 366
 367static int clk_edp_pixel_set_rate_and_parent(struct clk_hw *hw,
 368                unsigned long rate, unsigned long parent_rate, u8 index)
 369{
 370        /* Parent index is set statically in frequency table */
 371        return clk_edp_pixel_set_rate(hw, rate, parent_rate);
 372}
 373
 374static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
 375                                 unsigned long *p_rate, struct clk **p)
 376{
 377        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 378        const struct freq_tbl *f = rcg->freq_tbl;
 379        const struct frac_entry *frac;
 380        int delta = 100000;
 381        s64 src_rate = *p_rate;
 382        s64 request;
 383        u32 mask = BIT(rcg->hid_width) - 1;
 384        u32 hid_div;
 385
 386        /* Force the correct parent */
 387        *p = clk_get_parent_by_index(hw->clk, f->src);
 388
 389        if (src_rate == 810000000)
 390                frac = frac_table_810m;
 391        else
 392                frac = frac_table_675m;
 393
 394        for (; frac->num; frac++) {
 395                request = rate;
 396                request *= frac->den;
 397                request = div_s64(request, frac->num);
 398                if ((src_rate < (request - delta)) ||
 399                    (src_rate > (request + delta)))
 400                        continue;
 401
 402                regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
 403                                &hid_div);
 404                hid_div >>= CFG_SRC_DIV_SHIFT;
 405                hid_div &= mask;
 406
 407                return calc_rate(src_rate, frac->num, frac->den, !!frac->den,
 408                                 hid_div);
 409        }
 410
 411        return -EINVAL;
 412}
 413
 414const struct clk_ops clk_edp_pixel_ops = {
 415        .is_enabled = clk_rcg2_is_enabled,
 416        .get_parent = clk_rcg2_get_parent,
 417        .set_parent = clk_rcg2_set_parent,
 418        .recalc_rate = clk_rcg2_recalc_rate,
 419        .set_rate = clk_edp_pixel_set_rate,
 420        .set_rate_and_parent = clk_edp_pixel_set_rate_and_parent,
 421        .determine_rate = clk_edp_pixel_determine_rate,
 422};
 423EXPORT_SYMBOL_GPL(clk_edp_pixel_ops);
 424
 425static long clk_byte_determine_rate(struct clk_hw *hw, unsigned long rate,
 426                         unsigned long *p_rate, struct clk **p)
 427{
 428        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 429        const struct freq_tbl *f = rcg->freq_tbl;
 430        unsigned long parent_rate, div;
 431        u32 mask = BIT(rcg->hid_width) - 1;
 432
 433        if (rate == 0)
 434                return -EINVAL;
 435
 436        *p = clk_get_parent_by_index(hw->clk, f->src);
 437        *p_rate = parent_rate = __clk_round_rate(*p, rate);
 438
 439        div = DIV_ROUND_UP((2 * parent_rate), rate) - 1;
 440        div = min_t(u32, div, mask);
 441
 442        return calc_rate(parent_rate, 0, 0, 0, div);
 443}
 444
 445static int clk_byte_set_rate(struct clk_hw *hw, unsigned long rate,
 446                         unsigned long parent_rate)
 447{
 448        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 449        struct freq_tbl f = *rcg->freq_tbl;
 450        unsigned long div;
 451        u32 mask = BIT(rcg->hid_width) - 1;
 452
 453        div = DIV_ROUND_UP((2 * parent_rate), rate) - 1;
 454        div = min_t(u32, div, mask);
 455
 456        f.pre_div = div;
 457
 458        return clk_rcg2_configure(rcg, &f);
 459}
 460
 461static int clk_byte_set_rate_and_parent(struct clk_hw *hw,
 462                unsigned long rate, unsigned long parent_rate, u8 index)
 463{
 464        /* Parent index is set statically in frequency table */
 465        return clk_byte_set_rate(hw, rate, parent_rate);
 466}
 467
 468const struct clk_ops clk_byte_ops = {
 469        .is_enabled = clk_rcg2_is_enabled,
 470        .get_parent = clk_rcg2_get_parent,
 471        .set_parent = clk_rcg2_set_parent,
 472        .recalc_rate = clk_rcg2_recalc_rate,
 473        .set_rate = clk_byte_set_rate,
 474        .set_rate_and_parent = clk_byte_set_rate_and_parent,
 475        .determine_rate = clk_byte_determine_rate,
 476};
 477EXPORT_SYMBOL_GPL(clk_byte_ops);
 478
 479static const struct frac_entry frac_table_pixel[] = {
 480        { 3, 8 },
 481        { 2, 9 },
 482        { 4, 9 },
 483        { 1, 1 },
 484        { }
 485};
 486
 487static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
 488                                 unsigned long *p_rate, struct clk **p)
 489{
 490        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 491        unsigned long request, src_rate;
 492        int delta = 100000;
 493        const struct freq_tbl *f = rcg->freq_tbl;
 494        const struct frac_entry *frac = frac_table_pixel;
 495        struct clk *parent = *p = clk_get_parent_by_index(hw->clk, f->src);
 496
 497        for (; frac->num; frac++) {
 498                request = (rate * frac->den) / frac->num;
 499
 500                src_rate = __clk_round_rate(parent, request);
 501                if ((src_rate < (request - delta)) ||
 502                        (src_rate > (request + delta)))
 503                        continue;
 504
 505                *p_rate = src_rate;
 506                return (src_rate * frac->num) / frac->den;
 507        }
 508
 509        return -EINVAL;
 510}
 511
 512static int clk_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
 513                unsigned long parent_rate)
 514{
 515        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 516        struct freq_tbl f = *rcg->freq_tbl;
 517        const struct frac_entry *frac = frac_table_pixel;
 518        unsigned long request, src_rate;
 519        int delta = 100000;
 520        u32 mask = BIT(rcg->hid_width) - 1;
 521        u32 hid_div;
 522        struct clk *parent = clk_get_parent_by_index(hw->clk, f.src);
 523
 524        for (; frac->num; frac++) {
 525                request = (rate * frac->den) / frac->num;
 526
 527                src_rate = __clk_round_rate(parent, request);
 528                if ((src_rate < (request - delta)) ||
 529                        (src_rate > (request + delta)))
 530                        continue;
 531
 532                regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
 533                                &hid_div);
 534                f.pre_div = hid_div;
 535                f.pre_div >>= CFG_SRC_DIV_SHIFT;
 536                f.pre_div &= mask;
 537                f.m = frac->num;
 538                f.n = frac->den;
 539
 540                return clk_rcg2_configure(rcg, &f);
 541        }
 542        return -EINVAL;
 543}
 544
 545static int clk_pixel_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
 546                unsigned long parent_rate, u8 index)
 547{
 548        /* Parent index is set statically in frequency table */
 549        return clk_pixel_set_rate(hw, rate, parent_rate);
 550}
 551
 552const struct clk_ops clk_pixel_ops = {
 553        .is_enabled = clk_rcg2_is_enabled,
 554        .get_parent = clk_rcg2_get_parent,
 555        .set_parent = clk_rcg2_set_parent,
 556        .recalc_rate = clk_rcg2_recalc_rate,
 557        .set_rate = clk_pixel_set_rate,
 558        .set_rate_and_parent = clk_pixel_set_rate_and_parent,
 559        .determine_rate = clk_pixel_determine_rate,
 560};
 561EXPORT_SYMBOL_GPL(clk_pixel_ops);
 562