linux/drivers/clk/zte/clk.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright 2014 Linaro Ltd.
   4 * Copyright (C) 2014 ZTE Corporation.
   5 */
   6
   7#include <linux/clk-provider.h>
   8#include <linux/err.h>
   9#include <linux/gcd.h>
  10#include <linux/io.h>
  11#include <linux/iopoll.h>
  12#include <linux/slab.h>
  13#include <linux/spinlock.h>
  14#include <asm/div64.h>
  15
  16#include "clk.h"
  17
  18#define to_clk_zx_pll(_hw) container_of(_hw, struct clk_zx_pll, hw)
  19#define to_clk_zx_audio(_hw) container_of(_hw, struct clk_zx_audio, hw)
  20
  21#define CFG0_CFG1_OFFSET 4
  22#define LOCK_FLAG 30
  23#define POWER_DOWN 31
  24
  25static int rate_to_idx(struct clk_zx_pll *zx_pll, unsigned long rate)
  26{
  27        const struct zx_pll_config *config = zx_pll->lookup_table;
  28        int i;
  29
  30        for (i = 0; i < zx_pll->count; i++) {
  31                if (config[i].rate > rate)
  32                        return i > 0 ? i - 1 : 0;
  33
  34                if (config[i].rate == rate)
  35                        return i;
  36        }
  37
  38        return i - 1;
  39}
  40
  41static int hw_to_idx(struct clk_zx_pll *zx_pll)
  42{
  43        const struct zx_pll_config *config = zx_pll->lookup_table;
  44        u32 hw_cfg0, hw_cfg1;
  45        int i;
  46
  47        hw_cfg0 = readl_relaxed(zx_pll->reg_base);
  48        hw_cfg1 = readl_relaxed(zx_pll->reg_base + CFG0_CFG1_OFFSET);
  49
  50        /* For matching the value in lookup table */
  51        hw_cfg0 &= ~BIT(zx_pll->lock_bit);
  52
  53        /* Check availability of pd_bit */
  54        if (zx_pll->pd_bit < 32)
  55                hw_cfg0 |= BIT(zx_pll->pd_bit);
  56
  57        for (i = 0; i < zx_pll->count; i++) {
  58                if (hw_cfg0 == config[i].cfg0 && hw_cfg1 == config[i].cfg1)
  59                        return i;
  60        }
  61
  62        return -EINVAL;
  63}
  64
  65static unsigned long zx_pll_recalc_rate(struct clk_hw *hw,
  66                                        unsigned long parent_rate)
  67{
  68        struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
  69        int idx;
  70
  71        idx = hw_to_idx(zx_pll);
  72        if (unlikely(idx == -EINVAL))
  73                return 0;
  74
  75        return zx_pll->lookup_table[idx].rate;
  76}
  77
  78static long zx_pll_round_rate(struct clk_hw *hw, unsigned long rate,
  79                              unsigned long *prate)
  80{
  81        struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
  82        int idx;
  83
  84        idx = rate_to_idx(zx_pll, rate);
  85
  86        return zx_pll->lookup_table[idx].rate;
  87}
  88
  89static int zx_pll_set_rate(struct clk_hw *hw, unsigned long rate,
  90                           unsigned long parent_rate)
  91{
  92        /* Assume current cpu is not running on current PLL */
  93        struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
  94        const struct zx_pll_config *config;
  95        int idx;
  96
  97        idx = rate_to_idx(zx_pll, rate);
  98        config = &zx_pll->lookup_table[idx];
  99
 100        writel_relaxed(config->cfg0, zx_pll->reg_base);
 101        writel_relaxed(config->cfg1, zx_pll->reg_base + CFG0_CFG1_OFFSET);
 102
 103        return 0;
 104}
 105
 106static int zx_pll_enable(struct clk_hw *hw)
 107{
 108        struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
 109        u32 reg;
 110
 111        /* If pd_bit is not available, simply return success. */
 112        if (zx_pll->pd_bit > 31)
 113                return 0;
 114
 115        reg = readl_relaxed(zx_pll->reg_base);
 116        writel_relaxed(reg & ~BIT(zx_pll->pd_bit), zx_pll->reg_base);
 117
 118        return readl_relaxed_poll_timeout(zx_pll->reg_base, reg,
 119                                          reg & BIT(zx_pll->lock_bit), 0, 100);
 120}
 121
 122static void zx_pll_disable(struct clk_hw *hw)
 123{
 124        struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
 125        u32 reg;
 126
 127        if (zx_pll->pd_bit > 31)
 128                return;
 129
 130        reg = readl_relaxed(zx_pll->reg_base);
 131        writel_relaxed(reg | BIT(zx_pll->pd_bit), zx_pll->reg_base);
 132}
 133
 134static int zx_pll_is_enabled(struct clk_hw *hw)
 135{
 136        struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
 137        u32 reg;
 138
 139        reg = readl_relaxed(zx_pll->reg_base);
 140
 141        return !(reg & BIT(zx_pll->pd_bit));
 142}
 143
 144const struct clk_ops zx_pll_ops = {
 145        .recalc_rate = zx_pll_recalc_rate,
 146        .round_rate = zx_pll_round_rate,
 147        .set_rate = zx_pll_set_rate,
 148        .enable = zx_pll_enable,
 149        .disable = zx_pll_disable,
 150        .is_enabled = zx_pll_is_enabled,
 151};
 152EXPORT_SYMBOL(zx_pll_ops);
 153
 154struct clk *clk_register_zx_pll(const char *name, const char *parent_name,
 155                                unsigned long flags, void __iomem *reg_base,
 156                                const struct zx_pll_config *lookup_table,
 157                                int count, spinlock_t *lock)
 158{
 159        struct clk_zx_pll *zx_pll;
 160        struct clk *clk;
 161        struct clk_init_data init;
 162
 163        zx_pll = kzalloc(sizeof(*zx_pll), GFP_KERNEL);
 164        if (!zx_pll)
 165                return ERR_PTR(-ENOMEM);
 166
 167        init.name = name;
 168        init.ops = &zx_pll_ops;
 169        init.flags = flags;
 170        init.parent_names = parent_name ? &parent_name : NULL;
 171        init.num_parents = parent_name ? 1 : 0;
 172
 173        zx_pll->reg_base = reg_base;
 174        zx_pll->lookup_table = lookup_table;
 175        zx_pll->count = count;
 176        zx_pll->lock_bit = LOCK_FLAG;
 177        zx_pll->pd_bit = POWER_DOWN;
 178        zx_pll->lock = lock;
 179        zx_pll->hw.init = &init;
 180
 181        clk = clk_register(NULL, &zx_pll->hw);
 182        if (IS_ERR(clk))
 183                kfree(zx_pll);
 184
 185        return clk;
 186}
 187
 188#define BPAR 1000000
 189static u32 calc_reg(u32 parent_rate, u32 rate)
 190{
 191        u32 sel, integ, fra_div, tmp;
 192        u64 tmp64 = (u64)parent_rate * BPAR;
 193
 194        do_div(tmp64, rate);
 195        integ = (u32)tmp64 / BPAR;
 196        integ = integ >> 1;
 197
 198        tmp = (u32)tmp64 % BPAR;
 199        sel = tmp / BPAR;
 200
 201        tmp = tmp % BPAR;
 202        fra_div = tmp * 0xff / BPAR;
 203        tmp = (sel << 24) | (integ << 16) | (0xff << 8) | fra_div;
 204
 205        /* Set I2S integer divider as 1. This bit is reserved for SPDIF
 206         * and do no harm.
 207         */
 208        tmp |= BIT(28);
 209        return tmp;
 210}
 211
 212static u32 calc_rate(u32 reg, u32 parent_rate)
 213{
 214        u32 sel, integ, fra_div, tmp;
 215        u64 tmp64 = (u64)parent_rate * BPAR;
 216
 217        tmp = reg;
 218        sel = (tmp >> 24) & BIT(0);
 219        integ = (tmp >> 16) & 0xff;
 220        fra_div = tmp & 0xff;
 221
 222        tmp = fra_div * BPAR;
 223        tmp = tmp / 0xff;
 224        tmp += sel * BPAR;
 225        tmp += 2 * integ * BPAR;
 226        do_div(tmp64, tmp);
 227
 228        return (u32)tmp64;
 229}
 230
 231static unsigned long zx_audio_recalc_rate(struct clk_hw *hw,
 232                                          unsigned long parent_rate)
 233{
 234        struct clk_zx_audio *zx_audio = to_clk_zx_audio(hw);
 235        u32 reg;
 236
 237        reg = readl_relaxed(zx_audio->reg_base);
 238        return calc_rate(reg, parent_rate);
 239}
 240
 241static long zx_audio_round_rate(struct clk_hw *hw, unsigned long rate,
 242                                unsigned long *prate)
 243{
 244        u32 reg;
 245
 246        if (rate * 2 > *prate)
 247                return -EINVAL;
 248
 249        reg = calc_reg(*prate, rate);
 250        return calc_rate(reg, *prate);
 251}
 252
 253static int zx_audio_set_rate(struct clk_hw *hw, unsigned long rate,
 254                             unsigned long parent_rate)
 255{
 256        struct clk_zx_audio *zx_audio = to_clk_zx_audio(hw);
 257        u32 reg;
 258
 259        reg = calc_reg(parent_rate, rate);
 260        writel_relaxed(reg, zx_audio->reg_base);
 261
 262        return 0;
 263}
 264
 265#define ZX_AUDIO_EN BIT(25)
 266static int zx_audio_enable(struct clk_hw *hw)
 267{
 268        struct clk_zx_audio *zx_audio = to_clk_zx_audio(hw);
 269        u32 reg;
 270
 271        reg = readl_relaxed(zx_audio->reg_base);
 272        writel_relaxed(reg & ~ZX_AUDIO_EN, zx_audio->reg_base);
 273        return 0;
 274}
 275
 276static void zx_audio_disable(struct clk_hw *hw)
 277{
 278        struct clk_zx_audio *zx_audio = to_clk_zx_audio(hw);
 279        u32 reg;
 280
 281        reg = readl_relaxed(zx_audio->reg_base);
 282        writel_relaxed(reg | ZX_AUDIO_EN, zx_audio->reg_base);
 283}
 284
 285static const struct clk_ops zx_audio_ops = {
 286        .recalc_rate = zx_audio_recalc_rate,
 287        .round_rate = zx_audio_round_rate,
 288        .set_rate = zx_audio_set_rate,
 289        .enable = zx_audio_enable,
 290        .disable = zx_audio_disable,
 291};
 292
 293struct clk *clk_register_zx_audio(const char *name,
 294                                  const char * const parent_name,
 295                                  unsigned long flags,
 296                                  void __iomem *reg_base)
 297{
 298        struct clk_zx_audio *zx_audio;
 299        struct clk *clk;
 300        struct clk_init_data init;
 301
 302        zx_audio = kzalloc(sizeof(*zx_audio), GFP_KERNEL);
 303        if (!zx_audio)
 304                return ERR_PTR(-ENOMEM);
 305
 306        init.name = name;
 307        init.ops = &zx_audio_ops;
 308        init.flags = flags;
 309        init.parent_names = parent_name ? &parent_name : NULL;
 310        init.num_parents = parent_name ? 1 : 0;
 311
 312        zx_audio->reg_base = reg_base;
 313        zx_audio->hw.init = &init;
 314
 315        clk = clk_register(NULL, &zx_audio->hw);
 316        if (IS_ERR(clk))
 317                kfree(zx_audio);
 318
 319        return clk;
 320}
 321
 322#define CLK_AUDIO_DIV_FRAC      BIT(0)
 323#define CLK_AUDIO_DIV_INT       BIT(1)
 324#define CLK_AUDIO_DIV_UNCOMMON  BIT(1)
 325
 326#define CLK_AUDIO_DIV_FRAC_NSHIFT       16
 327#define CLK_AUDIO_DIV_INT_FRAC_RE       BIT(16)
 328#define CLK_AUDIO_DIV_INT_FRAC_MAX      (0xffff)
 329#define CLK_AUDIO_DIV_INT_FRAC_MIN      (0x2)
 330#define CLK_AUDIO_DIV_INT_INT_SHIFT     24
 331#define CLK_AUDIO_DIV_INT_INT_WIDTH     4
 332
 333struct zx_clk_audio_div_table {
 334        unsigned long rate;
 335        unsigned int int_reg;
 336        unsigned int frac_reg;
 337};
 338
 339#define to_clk_zx_audio_div(_hw) container_of(_hw, struct clk_zx_audio_divider, hw)
 340
 341static unsigned long audio_calc_rate(struct clk_zx_audio_divider *audio_div,
 342                                     u32 reg_frac, u32 reg_int,
 343                                     unsigned long parent_rate)
 344{
 345        unsigned long rate, m, n;
 346
 347        m = reg_frac & 0xffff;
 348        n = (reg_frac >> 16) & 0xffff;
 349
 350        m = (reg_int & 0xffff) * n + m;
 351        rate = (parent_rate * n) / m;
 352
 353        return rate;
 354}
 355
 356static void audio_calc_reg(struct clk_zx_audio_divider *audio_div,
 357                           struct zx_clk_audio_div_table *div_table,
 358                           unsigned long rate, unsigned long parent_rate)
 359{
 360        unsigned int reg_int, reg_frac;
 361        unsigned long m, n, div;
 362
 363        reg_int = parent_rate / rate;
 364
 365        if (reg_int > CLK_AUDIO_DIV_INT_FRAC_MAX)
 366                reg_int = CLK_AUDIO_DIV_INT_FRAC_MAX;
 367        else if (reg_int < CLK_AUDIO_DIV_INT_FRAC_MIN)
 368                reg_int = 0;
 369        m = parent_rate - rate * reg_int;
 370        n = rate;
 371
 372        div = gcd(m, n);
 373        m = m / div;
 374        n = n / div;
 375
 376        if ((m >> 16) || (n >> 16)) {
 377                if (m > n) {
 378                        n = n * 0xffff / m;
 379                        m = 0xffff;
 380                } else {
 381                        m = m * 0xffff / n;
 382                        n = 0xffff;
 383                }
 384        }
 385        reg_frac = m | (n << 16);
 386
 387        div_table->rate = parent_rate * n / (reg_int * n + m);
 388        div_table->int_reg = reg_int;
 389        div_table->frac_reg = reg_frac;
 390}
 391
 392static unsigned long zx_audio_div_recalc_rate(struct clk_hw *hw,
 393                                          unsigned long parent_rate)
 394{
 395        struct clk_zx_audio_divider *zx_audio_div = to_clk_zx_audio_div(hw);
 396        u32 reg_frac, reg_int;
 397
 398        reg_frac = readl_relaxed(zx_audio_div->reg_base);
 399        reg_int = readl_relaxed(zx_audio_div->reg_base + 0x4);
 400
 401        return audio_calc_rate(zx_audio_div, reg_frac, reg_int, parent_rate);
 402}
 403
 404static long zx_audio_div_round_rate(struct clk_hw *hw, unsigned long rate,
 405                                unsigned long *prate)
 406{
 407        struct clk_zx_audio_divider *zx_audio_div = to_clk_zx_audio_div(hw);
 408        struct zx_clk_audio_div_table divt;
 409
 410        audio_calc_reg(zx_audio_div, &divt, rate, *prate);
 411
 412        return audio_calc_rate(zx_audio_div, divt.frac_reg, divt.int_reg, *prate);
 413}
 414
 415static int zx_audio_div_set_rate(struct clk_hw *hw, unsigned long rate,
 416                                    unsigned long parent_rate)
 417{
 418        struct clk_zx_audio_divider *zx_audio_div = to_clk_zx_audio_div(hw);
 419        struct zx_clk_audio_div_table divt;
 420        unsigned int val;
 421
 422        audio_calc_reg(zx_audio_div, &divt, rate, parent_rate);
 423        if (divt.rate != rate)
 424                pr_debug("the real rate is:%ld", divt.rate);
 425
 426        writel_relaxed(divt.frac_reg, zx_audio_div->reg_base);
 427
 428        val = readl_relaxed(zx_audio_div->reg_base + 0x4);
 429        val &= ~0xffff;
 430        val |= divt.int_reg | CLK_AUDIO_DIV_INT_FRAC_RE;
 431        writel_relaxed(val, zx_audio_div->reg_base + 0x4);
 432
 433        mdelay(1);
 434
 435        val = readl_relaxed(zx_audio_div->reg_base + 0x4);
 436        val &= ~CLK_AUDIO_DIV_INT_FRAC_RE;
 437        writel_relaxed(val, zx_audio_div->reg_base + 0x4);
 438
 439        return 0;
 440}
 441
 442const struct clk_ops zx_audio_div_ops = {
 443        .recalc_rate = zx_audio_div_recalc_rate,
 444        .round_rate = zx_audio_div_round_rate,
 445        .set_rate = zx_audio_div_set_rate,
 446};
 447