linux/drivers/soc/xilinx/xlnx_vcu_clk.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Xilinx VCU clock driver
   4 *
   5 * Copyright (C) 2018 Xilinx, Inc.
   6 *
   7 * Rajan Vaja <rajan.vaja@xilinx.com>
   8 * Tejas Patel <tejas.patel@xilinx.com>
   9 */
  10
  11#include <linux/clk.h>
  12#include <linux/clk-provider.h>
  13#include <linux/device.h>
  14#include <linux/errno.h>
  15#include <linux/io.h>
  16#include <linux/iopoll.h>
  17#include <linux/module.h>
  18#include <linux/of.h>
  19#include <linux/of_address.h>
  20#include <linux/of_platform.h>
  21#include <linux/platform_device.h>
  22#include <linux/slab.h>
  23#include <soc/xilinx/xlnx_vcu.h>
  24
  25/* vcu slcr registers, bitmask and shift */
  26#define VCU_PLL_CTRL                    0x24
  27#define VCU_PLL_CTRL_RESET_MASK         BIT(0)
  28#define VCU_PLL_CTRL_RESET_SHIFT        0
  29#define VCU_PLL_CTRL_BYPASS_MASK        BIT(3)
  30#define VCU_PLL_CTRL_BYPASS_SHIFT       3
  31#define VCU_PLL_CTRL_FBDIV_MASK         0x7f
  32#define VCU_PLL_CTRL_FBDIV_SHIFT        8
  33#define VCU_PLL_CTRL_POR_IN_MASK        BIT(1)
  34#define VCU_PLL_CTRL_POR_IN_SHIFT       1
  35#define VCU_PLL_CTRL_PWR_POR_MASK       BIT(2)
  36#define VCU_PLL_CTRL_PWR_POR_SHIFT      2
  37#define VCU_PLL_CTRL_CLKOUTDIV_MASK     0x03
  38#define VCU_PLL_CTRL_CLKOUTDIV_SHIFT    16
  39#define VCU_PLL_CTRL_DEFAULT            0
  40
  41#define VCU_PLL_CFG                     0x28
  42#define VCU_PLL_CFG_RES_MASK            0x0f
  43#define VCU_PLL_CFG_RES_SHIFT           0
  44#define VCU_PLL_CFG_CP_MASK             0x0f
  45#define VCU_PLL_CFG_CP_SHIFT            5
  46#define VCU_PLL_CFG_LFHF_MASK           0x03
  47#define VCU_PLL_CFG_LFHF_SHIFT          10
  48#define VCU_PLL_CFG_LOCK_CNT_MASK       0x03ff
  49#define VCU_PLL_CFG_LOCK_CNT_SHIFT      13
  50#define VCU_PLL_CFG_LOCK_DLY_MASK       0x7f
  51#define VCU_PLL_CFG_LOCK_DLY_SHIFT      25
  52#define VCU_ENC_CORE_CTRL               0x30
  53#define VCU_ENC_MCU_CTRL                0x34
  54#define VCU_ENC_MCU_CTRL_GATE_BIT       BIT(12)
  55#define VCU_DEC_CORE_CTRL               0x38
  56#define VCU_DEC_MCU_CTRL                0x3c
  57#define VCU_PLL_DIVISOR_MASK            0x3f
  58#define VCU_PLL_DIVISOR_SHIFT           4
  59#define VCU_SRCSEL_MASK                 0x01
  60#define VCU_SRCSEL_SHIFT                0
  61#define VCU_SRCSEL_PLL                  1
  62
  63#define VCU_PLL_STATUS                  0x60
  64#define VCU_PLL_STATUS_LOCK_STATUS_MASK 0x01
  65#define VCU_PLL_LOCK_TIMEOUT            2000000
  66
  67#define PLL_FBDIV_MIN                   25
  68#define PLL_FBDIV_MAX                   125
  69
  70#define MHZ                             1000000
  71#define FVCO_MIN                        (1500U * MHZ)
  72#define FVCO_MAX                        (3000U * MHZ)
  73#define DIVISOR_MIN                     0
  74#define DIVISOR_MAX                     63
  75#define FRAC                            100
  76#define LIMIT                           (10 * MHZ)
  77
  78#define FRAC_OFFSET                     0x8
  79#define PLLFCFG_FRAC_EN                 BIT(31)
  80#define FRAC_DIV                        0x10000 /* 2^16 */
  81
  82#define to_vcu_pll(_hw) container_of(_hw, struct vcu_pll, hw)
  83#define div_mask(width) ((1 << (width)) - 1)
  84
  85enum pll_mode {
  86        PLL_MODE_INT,
  87        PLL_MODE_FRAC,
  88};
  89
  90enum vcu_clks {
  91        vcu_pll_half, vcu_core_enc, vcu_core_dec,
  92        mcu_core_enc, mcu_core_dec, clk_max
  93};
  94
  95/**
  96 * struct xvcu_pll_cfg - Helper data
  97 * @fbdiv: The integer portion of the feedback divider to the PLL
  98 * @cp: PLL charge pump control
  99 * @res: PLL loop filter resistor control
 100 * @lfhf: PLL loop filter high frequency capacitor control
 101 * @lock_dly: Lock circuit configuration settings for lock windowsize
 102 * @lock_cnt: Lock circuit counter setting
 103 */
 104struct xvcu_pll_cfg {
 105        u32 fbdiv;
 106        u32 cp;
 107        u32 res;
 108        u32 lfhf;
 109        u32 lock_dly;
 110        u32 lock_cnt;
 111};
 112
 113/**
 114 * struct vcu_pll - VCU PLL control/status data
 115 * @hw: Clock hardware
 116 * @pll_ctrl: PLL control register address
 117 * @pll_status: PLL status register address
 118 * @pll_cfg: PLL config register address
 119 * @lockbit: PLL lock status bit
 120 */
 121struct vcu_pll {
 122        struct clk_hw   hw;
 123        void __iomem    *pll_ctrl;
 124        void __iomem    *pll_status;
 125        void __iomem    *pll_cfg;
 126        u8              lockbit;
 127};
 128
 129static struct clk_hw_onecell_data *vcu_clk_data;
 130static const char * const vcu_mux_parents[] = {
 131        "dummy_name",
 132        "vcu_pll_half"
 133};
 134
 135static DEFINE_SPINLOCK(mcu_enc_lock);
 136static DEFINE_SPINLOCK(mcu_dec_lock);
 137static DEFINE_SPINLOCK(core_enc_lock);
 138static DEFINE_SPINLOCK(core_dec_lock);
 139
 140static const struct xvcu_pll_cfg xvcu_pll_cfg[] = {
 141        { 25, 3, 10, 3, 63, 1000 },
 142        { 26, 3, 10, 3, 63, 1000 },
 143        { 27, 4, 6, 3, 63, 1000 },
 144        { 28, 4, 6, 3, 63, 1000 },
 145        { 29, 4, 6, 3, 63, 1000 },
 146        { 30, 4, 6, 3, 63, 1000 },
 147        { 31, 6, 1, 3, 63, 1000 },
 148        { 32, 6, 1, 3, 63, 1000 },
 149        { 33, 4, 10, 3, 63, 1000 },
 150        { 34, 5, 6, 3, 63, 1000 },
 151        { 35, 5, 6, 3, 63, 1000 },
 152        { 36, 5, 6, 3, 63, 1000 },
 153        { 37, 5, 6, 3, 63, 1000 },
 154        { 38, 5, 6, 3, 63, 975 },
 155        { 39, 3, 12, 3, 63, 950 },
 156        { 40, 3, 12, 3, 63, 925 },
 157        { 41, 3, 12, 3, 63, 900 },
 158        { 42, 3, 12, 3, 63, 875 },
 159        { 43, 3, 12, 3, 63, 850 },
 160        { 44, 3, 12, 3, 63, 850 },
 161        { 45, 3, 12, 3, 63, 825 },
 162        { 46, 3, 12, 3, 63, 800 },
 163        { 47, 3, 12, 3, 63, 775 },
 164        { 48, 3, 12, 3, 63, 775 },
 165        { 49, 3, 12, 3, 63, 750 },
 166        { 50, 3, 12, 3, 63, 750 },
 167        { 51, 3, 2, 3, 63, 725 },
 168        { 52, 3, 2, 3, 63, 700 },
 169        { 53, 3, 2, 3, 63, 700 },
 170        { 54, 3, 2, 3, 63, 675 },
 171        { 55, 3, 2, 3, 63, 675 },
 172        { 56, 3, 2, 3, 63, 650 },
 173        { 57, 3, 2, 3, 63, 650 },
 174        { 58, 3, 2, 3, 63, 625 },
 175        { 59, 3, 2, 3, 63, 625 },
 176        { 60, 3, 2, 3, 63, 625 },
 177        { 61, 3, 2, 3, 63, 600 },
 178        { 62, 3, 2, 3, 63, 600 },
 179        { 63, 3, 2, 3, 63, 600 },
 180        { 64, 3, 2, 3, 63, 600 },
 181        { 65, 3, 2, 3, 63, 600 },
 182        { 66, 3, 2, 3, 63, 600 },
 183        { 67, 3, 2, 3, 63, 600 },
 184        { 68, 3, 2, 3, 63, 600 },
 185        { 69, 3, 2, 3, 63, 600 },
 186        { 70, 3, 2, 3, 63, 600 },
 187        { 71, 3, 2, 3, 63, 600 },
 188        { 72, 3, 2, 3, 63, 600 },
 189        { 73, 3, 2, 3, 63, 600 },
 190        { 74, 3, 2, 3, 63, 600 },
 191        { 75, 3, 2, 3, 63, 600 },
 192        { 76, 3, 2, 3, 63, 600 },
 193        { 77, 3, 2, 3, 63, 600 },
 194        { 78, 3, 2, 3, 63, 600 },
 195        { 79, 3, 2, 3, 63, 600 },
 196        { 80, 3, 2, 3, 63, 600 },
 197        { 81, 3, 2, 3, 63, 600 },
 198        { 82, 3, 2, 3, 63, 600 },
 199        { 83, 4, 2, 3, 63, 600 },
 200        { 84, 4, 2, 3, 63, 600 },
 201        { 85, 4, 2, 3, 63, 600 },
 202        { 86, 4, 2, 3, 63, 600 },
 203        { 87, 4, 2, 3, 63, 600 },
 204        { 88, 4, 2, 3, 63, 600 },
 205        { 89, 4, 2, 3, 63, 600 },
 206        { 90, 4, 2, 3, 63, 600 },
 207        { 91, 4, 2, 3, 63, 600 },
 208        { 92, 4, 2, 3, 63, 600 },
 209        { 93, 4, 2, 3, 63, 600 },
 210        { 94, 4, 2, 3, 63, 600 },
 211        { 95, 4, 2, 3, 63, 600 },
 212        { 96, 4, 2, 3, 63, 600 },
 213        { 97, 4, 2, 3, 63, 600 },
 214        { 98, 4, 2, 3, 63, 600 },
 215        { 99, 4, 2, 3, 63, 600 },
 216        { 100, 4, 2, 3, 63, 600 },
 217        { 101, 4, 2, 3, 63, 600 },
 218        { 102, 4, 2, 3, 63, 600 },
 219        { 103, 5, 2, 3, 63, 600 },
 220        { 104, 5, 2, 3, 63, 600 },
 221        { 105, 5, 2, 3, 63, 600 },
 222        { 106, 5, 2, 3, 63, 600 },
 223        { 107, 3, 4, 3, 63, 600 },
 224        { 108, 3, 4, 3, 63, 600 },
 225        { 109, 3, 4, 3, 63, 600 },
 226        { 110, 3, 4, 3, 63, 600 },
 227        { 111, 3, 4, 3, 63, 600 },
 228        { 112, 3, 4, 3, 63, 600 },
 229        { 113, 3, 4, 3, 63, 600 },
 230        { 114, 3, 4, 3, 63, 600 },
 231        { 115, 3, 4, 3, 63, 600 },
 232        { 116, 3, 4, 3, 63, 600 },
 233        { 117, 3, 4, 3, 63, 600 },
 234        { 118, 3, 4, 3, 63, 600 },
 235        { 119, 3, 4, 3, 63, 600 },
 236        { 120, 3, 4, 3, 63, 600 },
 237        { 121, 3, 4, 3, 63, 600 },
 238        { 122, 3, 4, 3, 63, 600 },
 239        { 123, 3, 4, 3, 63, 600 },
 240        { 124, 3, 4, 3, 63, 600 },
 241        { 125, 3, 4, 3, 63, 600 },
 242};
 243
 244static int xvcu_divider_get_val(unsigned long rate, unsigned long parent_rate,
 245                                const struct clk_div_table *table, u8 width,
 246                                unsigned long flags)
 247{
 248        unsigned int div;
 249
 250        if (flags & CLK_DIVIDER_ROUND_CLOSEST)
 251                div = DIV_ROUND_CLOSEST_ULL((u64)parent_rate, rate);
 252        else
 253                div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
 254
 255        return min_t(unsigned int, div, div_mask(width));
 256}
 257
 258static unsigned long xvcu_divider_recalc_rate(struct clk_hw *hw,
 259                                              unsigned long parent_rate)
 260{
 261        struct clk_divider *divider = to_clk_divider(hw);
 262        unsigned int val;
 263
 264        val = clk_readl(divider->reg) >> divider->shift;
 265        val &= div_mask(divider->width);
 266
 267        return divider_recalc_rate(hw, parent_rate, val, divider->table,
 268                                   divider->flags, divider->width);
 269}
 270
 271static long xvcu_divider_round_rate(struct clk_hw *hw, unsigned long rate,
 272                                    unsigned long *prate)
 273{
 274        struct clk_divider *divider = to_clk_divider(hw);
 275        int bestdiv;
 276
 277        bestdiv = xvcu_divider_get_val(rate, *prate, divider->table,
 278                                       divider->width, divider->flags);
 279
 280        *prate = rate * bestdiv;
 281
 282        return rate;
 283}
 284
 285static int xvcu_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 286                                 unsigned long parent_rate)
 287{
 288        struct clk_divider *divider = to_clk_divider(hw);
 289        int value;
 290        u32 val;
 291
 292        value = xvcu_divider_get_val(rate, parent_rate, divider->table,
 293                                     divider->width, divider->flags);
 294        if (value < 0)
 295                return value;
 296
 297        val = clk_readl(divider->reg);
 298        val &= ~(div_mask(divider->width) << divider->shift);
 299        val |= (u32)value << divider->shift;
 300        clk_writel(val, divider->reg);
 301
 302        return 0;
 303}
 304
 305static const struct clk_ops xvcu_divider_ops = {
 306        .recalc_rate = xvcu_divider_recalc_rate,
 307        .round_rate = xvcu_divider_round_rate,
 308        .set_rate = xvcu_divider_set_rate,
 309};
 310
 311/**
 312 * xvcu_register_divider - Register custom divider hardware
 313 * @dev:                VCU clock device
 314 * @name:               Divider name
 315 * @parent_name:        Divider parent name
 316 * @flags:              Clock flags
 317 * @reg:                Divider register base address
 318 * @shift:              Divider bits shift
 319 * @width:              Divider bits width
 320 * @clk_divider_flags:  Divider specific flags
 321 * @lock:               Shared register lock
 322 *
 323 * Register custom divider hardware to CCF.
 324 *
 325 * Return: Clock hardware for generated clock
 326 */
 327static struct clk_hw *xvcu_register_divider(struct device *dev,
 328                                            const char *name,
 329                                            const char *parent_name,
 330                                            unsigned long flags,
 331                                            void __iomem *reg, u8 shift,
 332                                            u8 width, u8 clk_divider_flags,
 333                                            spinlock_t *lock)
 334{
 335        struct clk_divider *div;
 336        struct clk_hw *hw;
 337        struct clk_init_data init;
 338        int ret;
 339
 340        /* allocate the divider */
 341        div = kzalloc(sizeof(*div), GFP_KERNEL);
 342        if (!div)
 343                return ERR_PTR(-ENOMEM);
 344
 345        init.name = name;
 346        init.ops = &xvcu_divider_ops;
 347        init.flags = flags | CLK_IS_BASIC;
 348        init.parent_names = (parent_name ? &parent_name : NULL);
 349        init.num_parents = (parent_name ? 1 : 0);
 350
 351        /* struct clk_divider assignments */
 352        div->reg = reg;
 353        div->shift = shift;
 354        div->width = width;
 355        div->flags = clk_divider_flags;
 356        div->lock = lock;
 357        div->hw.init = &init;
 358
 359        /* register the clock */
 360        hw = &div->hw;
 361        ret = clk_hw_register(dev, hw);
 362        if (ret) {
 363                kfree(div);
 364                hw = ERR_PTR(ret);
 365        }
 366
 367        return hw;
 368}
 369
 370/**
 371 * xvcu_pll_bypass_ctrl - Enable/Disable PLL bypass mode
 372 * @pll:        PLL data
 373 * @enable:     Enable/Disable flag
 374 *
 375 * Enable/Disable PLL bypass mode:
 376 *      0 - Disable
 377 *      1 - Enable
 378 */
 379static void xvcu_pll_bypass_ctrl(struct vcu_pll *pll, bool enable)
 380{
 381        u32 reg;
 382
 383        reg = clk_readl(pll->pll_ctrl);
 384        if (enable)
 385                reg |= VCU_PLL_CTRL_BYPASS_MASK;
 386        else
 387                reg &= ~VCU_PLL_CTRL_BYPASS_MASK;
 388        clk_writel(reg, pll->pll_ctrl);
 389}
 390
 391/**
 392 * xvcu_pll_config - Configure PLL based on FBDIV value
 393 * @pll:        PLL data
 394 *
 395 * PLL needs to be configured before taking out of reset. Configuration
 396 * data depends on the value of FBDIV for proper PLL locking.
 397 */
 398static void xvcu_pll_config(struct vcu_pll *pll)
 399{
 400        unsigned int fbdiv, reg;
 401        int i;
 402
 403        reg = clk_readl(pll->pll_ctrl);
 404        fbdiv = (reg >> VCU_PLL_CTRL_FBDIV_SHIFT) & VCU_PLL_CTRL_FBDIV_MASK;
 405
 406        for (i = ARRAY_SIZE(xvcu_pll_cfg) - 1; i >= 0; i--) {
 407                if (fbdiv != xvcu_pll_cfg[i].fbdiv)
 408                        continue;
 409
 410                /* Set RES, CP, LFHF, LOCK_CNT and LOCK_DLY cfg values */
 411                reg = (xvcu_pll_cfg[i].res << VCU_PLL_CFG_RES_SHIFT) |
 412                      (xvcu_pll_cfg[i].cp << VCU_PLL_CFG_CP_SHIFT) |
 413                      (xvcu_pll_cfg[i].lfhf << VCU_PLL_CFG_LFHF_SHIFT) |
 414                      (xvcu_pll_cfg[i].lock_cnt << VCU_PLL_CFG_LOCK_CNT_SHIFT) |
 415                      (xvcu_pll_cfg[i].lock_dly << VCU_PLL_CFG_LOCK_DLY_SHIFT);
 416                clk_writel(reg, pll->pll_cfg);
 417        }
 418}
 419
 420/**
 421 * xvcu_pll_enable_disable - Enable/Disable PLL
 422 * @pll:        PLL data
 423 * @enable:     Enable/Disable flag
 424 *
 425 * Enable/Disable PLL based on request:
 426 *      0 - Disable
 427 *      1 - Enable
 428 */
 429static void xvcu_pll_enable_disable(struct vcu_pll *pll, bool enable)
 430{
 431        u32 reg;
 432
 433        reg = clk_readl(pll->pll_ctrl);
 434        if (enable)
 435                reg &= ~(VCU_PLL_CTRL_RESET_MASK | VCU_PLL_CTRL_POR_IN_MASK |
 436                                VCU_PLL_CTRL_PWR_POR_MASK);
 437        else
 438                reg |= (VCU_PLL_CTRL_RESET_MASK | VCU_PLL_CTRL_POR_IN_MASK |
 439                                VCU_PLL_CTRL_PWR_POR_MASK);
 440        clk_writel(reg, pll->pll_ctrl);
 441}
 442
 443/**
 444 * xvcu_pll_is_enabled - Check if PLL is enabled or not
 445 * @hw:         Clock hardware
 446 *
 447 * Check if PLL is enabled or not. PLL enabled means PLL is not in
 448 * reset state.
 449 *
 450 * Return: PLL status (0 - Disabled, 1 - Enabled)
 451 */
 452static int xvcu_pll_is_enabled(struct clk_hw *hw)
 453{
 454        struct vcu_pll *pll = to_vcu_pll(hw);
 455        u32 reg;
 456
 457        reg = clk_readl(pll->pll_ctrl);
 458
 459        return !(reg & (VCU_PLL_CTRL_RESET_MASK | VCU_PLL_CTRL_POR_IN_MASK |
 460                 VCU_PLL_CTRL_PWR_POR_MASK));
 461}
 462
 463/**
 464 * xvcu_pll_enable - Enable PLL
 465 * @hw:         Clock hardware
 466 *
 467 * Enable PLL if it is not enabled. Configure PLL, enable and wait for
 468 * the PLL lock. Put PLL into bypass state during PLL configuration.
 469 *
 470 * Return: 0 on success else error code
 471 */
 472static int xvcu_pll_enable(struct clk_hw *hw)
 473{
 474        struct vcu_pll *pll = to_vcu_pll(hw);
 475        u32 reg;
 476        int ret;
 477
 478        if (xvcu_pll_is_enabled(hw))
 479                return 0;
 480
 481        pr_info("VCU PLL: enable\n");
 482
 483        xvcu_pll_bypass_ctrl(pll, 1);
 484
 485        xvcu_pll_config(pll);
 486
 487        xvcu_pll_enable_disable(pll, 1);
 488
 489        ret = readl_poll_timeout_atomic(pll->pll_status, reg,
 490                                        reg & VCU_PLL_STATUS_LOCK_STATUS_MASK,
 491                                        1, VCU_PLL_LOCK_TIMEOUT);
 492        if (ret) {
 493                pr_err("VCU PLL is not locked\n");
 494                return ret;
 495        }
 496
 497        xvcu_pll_bypass_ctrl(pll, 0);
 498
 499        return ret;
 500}
 501
 502/**
 503 * xvcu_pll_disable - Disable PLL
 504 * @hw:         Clock hardware
 505 *
 506 * Disable PLL if it is enabled.
 507 *
 508 * Return: 0 on success else error code
 509 */
 510static void xvcu_pll_disable(struct clk_hw *hw)
 511{
 512        struct vcu_pll *pll = to_vcu_pll(hw);
 513
 514        if (!xvcu_pll_is_enabled(hw))
 515                return;
 516
 517        pr_info("PLL: shutdown\n");
 518        xvcu_pll_enable_disable(pll, 0);
 519}
 520
 521/**
 522 * xvcu_pll_frac_get_mode - Get PLL fraction mode
 523 * @hw:         Clock hardware
 524 *
 525 * Check if PLL is configured for integer mode or fraction mode.
 526 *
 527 * Return: PLL mode:
 528 *      PLL_MODE_FRAC - Fraction mode
 529 *      PLL_MODE_INT - Integer mode
 530 */
 531static inline enum pll_mode xvcu_pll_frac_get_mode(struct clk_hw *hw)
 532{
 533        struct vcu_pll *clk = to_vcu_pll(hw);
 534        u32 reg;
 535
 536        reg = clk_readl(clk->pll_ctrl + FRAC_OFFSET);
 537
 538        reg = reg & PLLFCFG_FRAC_EN;
 539        return reg ? PLL_MODE_FRAC : PLL_MODE_INT;
 540}
 541
 542/**
 543 * xvcu_pll_frac_set_mode - Set PLL fraction mode
 544 * @hw:         Clock hardware
 545 * @on:         Enable/Disable flag
 546 *
 547 * Configure PLL for integer mode or fraction mode.
 548 *      1 - Fraction mode
 549 *      0 - Integer mode
 550 */
 551static inline void xvcu_pll_frac_set_mode(struct clk_hw *hw, bool on)
 552{
 553        struct vcu_pll *clk = to_vcu_pll(hw);
 554        u32 reg = 0;
 555
 556        if (on)
 557                reg = PLLFCFG_FRAC_EN;
 558
 559        reg = clk_readl(clk->pll_ctrl + FRAC_OFFSET);
 560        reg |= PLLFCFG_FRAC_EN;
 561        clk_writel(reg, (clk->pll_ctrl + FRAC_OFFSET));
 562}
 563
 564static long vcu_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 565                               unsigned long *prate)
 566{
 567        u32 fbdiv;
 568        long rate_div, f;
 569
 570        /* Enable the fractional mode if needed */
 571        rate_div = (rate * FRAC_DIV) / *prate;
 572        f = rate_div % FRAC_DIV;
 573        xvcu_pll_frac_set_mode(hw, !!f);
 574
 575        if (xvcu_pll_frac_get_mode(hw) == PLL_MODE_FRAC) {
 576                if (rate > FVCO_MAX) {
 577                        fbdiv = rate / FVCO_MAX;
 578                        rate = rate / (fbdiv + 1);
 579                }
 580                if (rate < FVCO_MIN) {
 581                        fbdiv = DIV_ROUND_UP(FVCO_MIN, rate);
 582                        rate = rate * fbdiv;
 583                }
 584                return rate;
 585        }
 586
 587        fbdiv = DIV_ROUND_CLOSEST(rate, *prate);
 588        fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX);
 589        return *prate * fbdiv;
 590}
 591
 592static unsigned long vcu_pll_recalc_rate(struct clk_hw *hw,
 593                                         unsigned long parent_rate)
 594{
 595        struct vcu_pll *pll = to_vcu_pll(hw);
 596        u32 fbdiv, data, reg;
 597        unsigned long rate, frac;
 598
 599        reg = clk_readl(pll->pll_ctrl);
 600        fbdiv = (reg >> VCU_PLL_CTRL_FBDIV_SHIFT) & VCU_PLL_CTRL_FBDIV_MASK;
 601
 602        rate = parent_rate * fbdiv;
 603        if (xvcu_pll_frac_get_mode(hw) == PLL_MODE_FRAC) {
 604                data = (clk_readl(pll->pll_ctrl + FRAC_OFFSET) & 0xFFFF);
 605                frac = (parent_rate * data) / FRAC_DIV;
 606                rate = rate + frac;
 607        }
 608
 609        return rate;
 610}
 611
 612static int vcu_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 613                            unsigned long parent_rate)
 614{
 615        struct vcu_pll *pll = to_vcu_pll(hw);
 616        u32 fbdiv, reg;
 617        long rate_div, frac, m, f;
 618
 619        if (xvcu_pll_frac_get_mode(hw) == PLL_MODE_FRAC) {
 620                rate_div = ((rate * FRAC_DIV) / parent_rate);
 621                m = rate_div / FRAC_DIV;
 622                f = rate_div % FRAC_DIV;
 623                m = clamp_t(u32, m, (PLL_FBDIV_MIN), (PLL_FBDIV_MAX));
 624                rate = parent_rate * m;
 625                frac = (parent_rate * f) / FRAC_DIV;
 626                reg = clk_readl(pll->pll_ctrl);
 627                reg &= ~(VCU_PLL_CTRL_FBDIV_MASK << VCU_PLL_CTRL_FBDIV_SHIFT);
 628                reg |= m << VCU_PLL_CTRL_FBDIV_SHIFT;
 629                clk_writel(reg, pll->pll_ctrl);
 630
 631                reg = clk_readl(pll->pll_ctrl + FRAC_OFFSET);
 632                reg &= ~0xFFFF;
 633                reg |= (f & 0xFFFF);
 634                clk_writel(reg, pll->pll_ctrl + FRAC_OFFSET);
 635
 636                return (rate + frac);
 637        }
 638
 639        fbdiv = DIV_ROUND_CLOSEST(rate, parent_rate);
 640        fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX);
 641        reg = clk_readl(pll->pll_ctrl);
 642        reg &= ~(VCU_PLL_CTRL_FBDIV_MASK << VCU_PLL_CTRL_FBDIV_SHIFT);
 643        reg |= fbdiv << VCU_PLL_CTRL_FBDIV_SHIFT;
 644        clk_writel(reg, pll->pll_ctrl);
 645
 646        return parent_rate * fbdiv;
 647}
 648
 649static const struct clk_ops vcu_pll_ops = {
 650        .enable = xvcu_pll_enable,
 651        .disable = xvcu_pll_disable,
 652        .is_enabled = xvcu_pll_is_enabled,
 653        .round_rate = vcu_pll_round_rate,
 654        .recalc_rate = vcu_pll_recalc_rate,
 655        .set_rate = vcu_pll_set_rate,
 656};
 657
 658/**
 659 * xvcu_register_pll - Register VCU PLL
 660 * @dev:        VCU clock device
 661 * @name:       PLL name
 662 * @parent:     PLL parent
 663 * @reg_base:   PLL register base address
 664 * @flags:      Hardware specific flags
 665 *
 666 * Register PLL to CCF.
 667 *
 668 * Return: Clock hardware for generated clock
 669 */
 670static struct clk_hw *xvcu_register_pll(struct device *dev, const char *name,
 671                                        const char *parent,
 672                                        void __iomem *reg_base,
 673                                        unsigned long flags)
 674{
 675        struct vcu_pll *pll;
 676        struct clk_hw *hw;
 677        struct clk_init_data init;
 678        int ret;
 679
 680        init.name = name;
 681        init.parent_names = &parent;
 682        init.ops = &vcu_pll_ops;
 683        init.num_parents = 1;
 684        init.flags = flags;
 685
 686        pll = devm_kmalloc(dev, sizeof(*pll), GFP_KERNEL);
 687        if (!pll)
 688                return ERR_PTR(-ENOMEM);
 689
 690        pll->hw.init = &init;
 691        pll->pll_ctrl = reg_base + VCU_PLL_CTRL;
 692        pll->pll_status = reg_base + VCU_PLL_STATUS;
 693        pll->pll_cfg = reg_base + VCU_PLL_CFG;
 694        pll->lockbit = VCU_PLL_STATUS_LOCK_STATUS_MASK;
 695
 696        hw = &pll->hw;
 697        ret = devm_clk_hw_register(dev, hw);
 698        if (ret)
 699                return ERR_PTR(ret);
 700
 701        clk_hw_set_rate_range(hw, FVCO_MIN, FVCO_MAX);
 702        if (ret < 0)
 703                pr_err("%s:ERROR clk_set_rate_range failed %d\n", name, ret);
 704
 705        return hw;
 706}
 707
 708/**
 709 * register_vcu_leaf_clocks - Register VCU leaf clocks
 710 * @dev:                VCU clock device
 711 * @name:               Clock name
 712 * @parents:            Clock parents
 713 * @nparents:           Clock parent count
 714 * @default_parent:     Default parent to set
 715 * @reg:                Clock control register address
 716 * @lock:               Clock register access lock
 717 *
 718 * Register VCU leaf clocks. These clocks are MCU/core
 719 * encoder and decoder clocks. Topology for these clocks
 720 * are Mux, Divisor and Gate.
 721 *
 722 * Return: Clock hardware for the generated gate clock
 723 */
 724static struct clk_hw *register_vcu_leaf_clocks(struct device *dev,
 725                                               const char *name,
 726                                               const char * const *parents,
 727                                               u8 nparents,
 728                                               struct clk *default_parent,
 729                                               void __iomem *reg,
 730                                               spinlock_t *lock)
 731{
 732        char *clk_mux, *clk_div;
 733        struct clk_hw *hw;
 734
 735        clk_mux = devm_kasprintf(dev, GFP_KERNEL, "%s%s", name, "_mux");
 736        hw = clk_hw_register_mux(dev, clk_mux, parents, nparents,
 737                                 CLK_SET_RATE_PARENT | CLK_IS_BASIC |
 738                                 CLK_SET_RATE_NO_REPARENT,
 739                                 reg, VCU_SRCSEL_SHIFT, 1, 0, lock);
 740
 741        if (default_parent)
 742                clk_set_parent(hw->clk, default_parent);
 743
 744        clk_div = devm_kasprintf(dev, GFP_KERNEL, "%s%s", name, "_div");
 745        xvcu_register_divider(dev, clk_div, clk_mux,
 746                              CLK_IS_BASIC | CLK_SET_RATE_PARENT |
 747                              CLK_SET_RATE_NO_REPARENT,
 748                              reg, VCU_PLL_DIVISOR_SHIFT, 6,
 749                              CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO |
 750                              CLK_DIVIDER_ROUND_CLOSEST,
 751                              lock);
 752
 753        return clk_hw_register_gate(dev, name, clk_div,
 754                                    CLK_SET_RATE_PARENT | CLK_IS_BASIC,
 755                                    reg, 12, 0, lock);
 756}
 757
 758/**
 759 * unregister_vcu_leaf_clocks - Unegister VCU leaf clocks
 760 * @hw:         VCU leaf clock hardware
 761 *
 762 * Unregister VCU leaf clocks. These clocks are MCU/core
 763 * encoder and decoder clocks. Unregister clocks in order
 764 * from gate, div and mux maintaining their parent dependency.
 765 *
 766 */
 767static void unregister_vcu_leaf_clocks(struct clk_hw *hw)
 768{
 769        struct clk_hw *parent;
 770
 771        parent = clk_hw_get_parent(hw);
 772        clk_hw_unregister_gate(hw);
 773        hw = parent;
 774
 775        parent = clk_hw_get_parent(hw);
 776        clk_hw_unregister_divider(hw);
 777        hw = parent;
 778
 779        clk_hw_unregister_mux(hw);
 780}
 781
 782/**
 783 * xvcu_clock_init - Initialize VCU clocks
 784 * @dev:        VCU clock device
 785 * @reg_base:   Clock register base address
 786 *
 787 * Register VCU PLL and clocks and add VCU to clock provider list.
 788 *
 789 * Return: 0 on success else error code.
 790 */
 791static int xvcu_clock_init(struct device *dev, void __iomem *reg_base)
 792{
 793        struct clk_hw *hw;
 794        struct clk *ref_clk;
 795        const char *parent;
 796        u32 vcu_pll_ctrl, clkoutdiv;
 797        int i;
 798
 799        ref_clk = devm_clk_get(dev, "pll_ref");
 800        if (IS_ERR(ref_clk)) {
 801                dev_err(dev, "failed to get pll_ref clock\n");
 802                return PTR_ERR(ref_clk);
 803        }
 804
 805        vcu_clk_data = devm_kzalloc(dev, sizeof(*vcu_clk_data) +
 806                                    sizeof(*vcu_clk_data->hws) * clk_max,
 807                                    GFP_KERNEL);
 808        if (!vcu_clk_data)
 809                return -ENOMEM;
 810
 811        parent = __clk_get_name(ref_clk);
 812        hw = xvcu_register_pll(dev, "vcu_pll", parent, reg_base,
 813                               CLK_SET_RATE_NO_REPARENT);
 814        if (IS_ERR(hw)) {
 815                dev_err(dev, "VCU PLL registration failed\n");
 816                return PTR_ERR(hw);
 817        }
 818
 819        /*
 820         * The divide-by-2 should be always enabled (== 1) to meet the timing
 821         * in the design. Otherwise, it's an error
 822         */
 823        vcu_pll_ctrl = clk_readl(reg_base + VCU_PLL_CTRL);
 824        clkoutdiv = vcu_pll_ctrl >> VCU_PLL_CTRL_CLKOUTDIV_SHIFT;
 825        clkoutdiv = clkoutdiv & VCU_PLL_CTRL_CLKOUTDIV_MASK;
 826        if (clkoutdiv != 1) {
 827                dev_err(dev, "clkoutdiv is invalid\n");
 828                return -EINVAL;
 829        }
 830
 831        vcu_clk_data->hws[vcu_pll_half] =
 832                clk_hw_register_fixed_factor(dev, "vcu_pll_half", "vcu_pll",
 833                                             CLK_SET_RATE_NO_REPARENT |
 834                                             CLK_SET_RATE_PARENT,
 835                                             1, 2);
 836
 837        vcu_clk_data->hws[vcu_core_enc] =
 838                register_vcu_leaf_clocks(dev, "vcu_core_enc_clk",
 839                                         vcu_mux_parents, 2,
 840                                         vcu_clk_data->hws[vcu_pll_half]->clk,
 841                                         reg_base + VCU_ENC_CORE_CTRL,
 842                                         &core_enc_lock);
 843        vcu_clk_data->hws[vcu_core_dec] =
 844                register_vcu_leaf_clocks(dev, "vcu_core_dec_clk",
 845                                         vcu_mux_parents, 2,
 846                                         vcu_clk_data->hws[vcu_pll_half]->clk,
 847                                         reg_base + VCU_DEC_CORE_CTRL,
 848                                         &core_dec_lock);
 849        vcu_clk_data->hws[mcu_core_enc] =
 850                register_vcu_leaf_clocks(dev, "mcu_core_enc_clk",
 851                                         vcu_mux_parents, 2,
 852                                         vcu_clk_data->hws[vcu_pll_half]->clk,
 853                                         reg_base + VCU_ENC_MCU_CTRL,
 854                                         &mcu_enc_lock);
 855        vcu_clk_data->hws[mcu_core_dec] =
 856                register_vcu_leaf_clocks(dev, "mcu_core_dec_clk",
 857                                         vcu_mux_parents, 2,
 858                                         vcu_clk_data->hws[vcu_pll_half]->clk,
 859                                         reg_base + VCU_DEC_MCU_CTRL,
 860                                         &mcu_dec_lock);
 861
 862        for (i = 0; i < clk_max; i++) {
 863                if (IS_ERR(vcu_clk_data->hws[i])) {
 864                        dev_err(dev, "clk %d: register failed with %ld\n",
 865                                i, PTR_ERR(vcu_clk_data->hws[i]));
 866                }
 867        }
 868
 869        vcu_clk_data->num = clk_max;
 870        return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
 871                                      vcu_clk_data);
 872}
 873
 874static int xvcu_clk_probe(struct platform_device *pdev)
 875{
 876        struct xvcu_device *xvcu = dev_get_drvdata(pdev->dev.parent);
 877        int ret;
 878
 879        ret = xvcu_clock_init(pdev->dev.parent, xvcu->vcu_slcr_ba);
 880        if (ret)
 881                dev_err(&pdev->dev, "clock init fail with error %d\n", ret);
 882        else
 883                dev_dbg(&pdev->dev, "clock init successful\n");
 884
 885        return ret;
 886}
 887
 888static int xvcu_clk_remove(struct platform_device *pdev)
 889{
 890        unregister_vcu_leaf_clocks(vcu_clk_data->hws[vcu_core_enc]);
 891        unregister_vcu_leaf_clocks(vcu_clk_data->hws[vcu_core_dec]);
 892        unregister_vcu_leaf_clocks(vcu_clk_data->hws[mcu_core_enc]);
 893        unregister_vcu_leaf_clocks(vcu_clk_data->hws[mcu_core_dec]);
 894        clk_hw_unregister(vcu_clk_data->hws[vcu_pll_half]);
 895        of_clk_del_provider(pdev->dev.parent->of_node);
 896
 897        devm_kfree(pdev->dev.parent, vcu_clk_data);
 898
 899        return 0;
 900}
 901
 902static struct platform_driver xvcu_clk_driver = {
 903        .driver = {
 904                .name = "xilinx-vcu-clk",
 905        },
 906        .probe = xvcu_clk_probe,
 907        .remove = xvcu_clk_remove,
 908};
 909
 910module_platform_driver(xvcu_clk_driver);
 911
 912MODULE_AUTHOR("Rajan Vaja <rajan.vaja@xilinx.com>");
 913MODULE_DESCRIPTION("Xilinx VCU clock Driver");
 914MODULE_LICENSE("GPL v2");
 915MODULE_ALIAS("platform:xilinx-vcu-clk");
 916