linux/drivers/clk/zynq/pll.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Zynq PLL driver
   4 *
   5 *  Copyright (C) 2013 Xilinx
   6 *
   7 *  Sören Brinkmann <soren.brinkmann@xilinx.com>
   8 */
   9#include <linux/clk/zynq.h>
  10#include <linux/clk-provider.h>
  11#include <linux/slab.h>
  12#include <linux/io.h>
  13
  14/**
  15 * struct zynq_pll
  16 * @hw:         Handle between common and hardware-specific interfaces
  17 * @pll_ctrl:   PLL control register
  18 * @pll_status: PLL status register
  19 * @lock:       Register lock
  20 * @lockbit:    Indicates the associated PLL_LOCKED bit in the PLL status
  21 *              register.
  22 */
  23struct zynq_pll {
  24        struct clk_hw   hw;
  25        void __iomem    *pll_ctrl;
  26        void __iomem    *pll_status;
  27        spinlock_t      *lock;
  28        u8              lockbit;
  29};
  30#define to_zynq_pll(_hw)        container_of(_hw, struct zynq_pll, hw)
  31
  32/* Register bitfield defines */
  33#define PLLCTRL_FBDIV_MASK      0x7f000
  34#define PLLCTRL_FBDIV_SHIFT     12
  35#define PLLCTRL_BPQUAL_MASK     (1 << 3)
  36#define PLLCTRL_PWRDWN_MASK     2
  37#define PLLCTRL_PWRDWN_SHIFT    1
  38#define PLLCTRL_RESET_MASK      1
  39#define PLLCTRL_RESET_SHIFT     0
  40
  41#define PLL_FBDIV_MIN   13
  42#define PLL_FBDIV_MAX   66
  43
  44/**
  45 * zynq_pll_round_rate() - Round a clock frequency
  46 * @hw:         Handle between common and hardware-specific interfaces
  47 * @rate:       Desired clock frequency
  48 * @prate:      Clock frequency of parent clock
  49 * Returns frequency closest to @rate the hardware can generate.
  50 */
  51static long zynq_pll_round_rate(struct clk_hw *hw, unsigned long rate,
  52                unsigned long *prate)
  53{
  54        u32 fbdiv;
  55
  56        fbdiv = DIV_ROUND_CLOSEST(rate, *prate);
  57        if (fbdiv < PLL_FBDIV_MIN)
  58                fbdiv = PLL_FBDIV_MIN;
  59        else if (fbdiv > PLL_FBDIV_MAX)
  60                fbdiv = PLL_FBDIV_MAX;
  61
  62        return *prate * fbdiv;
  63}
  64
  65/**
  66 * zynq_pll_recalc_rate() - Recalculate clock frequency
  67 * @hw:                 Handle between common and hardware-specific interfaces
  68 * @parent_rate:        Clock frequency of parent clock
  69 * Returns current clock frequency.
  70 */
  71static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw,
  72                unsigned long parent_rate)
  73{
  74        struct zynq_pll *clk = to_zynq_pll(hw);
  75        u32 fbdiv;
  76
  77        /*
  78         * makes probably sense to redundantly save fbdiv in the struct
  79         * zynq_pll to save the IO access.
  80         */
  81        fbdiv = (readl(clk->pll_ctrl) & PLLCTRL_FBDIV_MASK) >>
  82                        PLLCTRL_FBDIV_SHIFT;
  83
  84        return parent_rate * fbdiv;
  85}
  86
  87/**
  88 * zynq_pll_is_enabled - Check if a clock is enabled
  89 * @hw:         Handle between common and hardware-specific interfaces
  90 * Returns 1 if the clock is enabled, 0 otherwise.
  91 *
  92 * Not sure this is a good idea, but since disabled means bypassed for
  93 * this clock implementation we say we are always enabled.
  94 */
  95static int zynq_pll_is_enabled(struct clk_hw *hw)
  96{
  97        unsigned long flags = 0;
  98        u32 reg;
  99        struct zynq_pll *clk = to_zynq_pll(hw);
 100
 101        spin_lock_irqsave(clk->lock, flags);
 102
 103        reg = readl(clk->pll_ctrl);
 104
 105        spin_unlock_irqrestore(clk->lock, flags);
 106
 107        return !(reg & (PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK));
 108}
 109
 110/**
 111 * zynq_pll_enable - Enable clock
 112 * @hw:         Handle between common and hardware-specific interfaces
 113 * Returns 0 on success
 114 */
 115static int zynq_pll_enable(struct clk_hw *hw)
 116{
 117        unsigned long flags = 0;
 118        u32 reg;
 119        struct zynq_pll *clk = to_zynq_pll(hw);
 120
 121        if (zynq_pll_is_enabled(hw))
 122                return 0;
 123
 124        pr_info("PLL: enable\n");
 125
 126        /* Power up PLL and wait for lock */
 127        spin_lock_irqsave(clk->lock, flags);
 128
 129        reg = readl(clk->pll_ctrl);
 130        reg &= ~(PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK);
 131        writel(reg, clk->pll_ctrl);
 132        while (!(readl(clk->pll_status) & (1 << clk->lockbit)))
 133                ;
 134
 135        spin_unlock_irqrestore(clk->lock, flags);
 136
 137        return 0;
 138}
 139
 140/**
 141 * zynq_pll_disable - Disable clock
 142 * @hw:         Handle between common and hardware-specific interfaces
 143 * Returns 0 on success
 144 */
 145static void zynq_pll_disable(struct clk_hw *hw)
 146{
 147        unsigned long flags = 0;
 148        u32 reg;
 149        struct zynq_pll *clk = to_zynq_pll(hw);
 150
 151        if (!zynq_pll_is_enabled(hw))
 152                return;
 153
 154        pr_info("PLL: shutdown\n");
 155
 156        /* shut down PLL */
 157        spin_lock_irqsave(clk->lock, flags);
 158
 159        reg = readl(clk->pll_ctrl);
 160        reg |= PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK;
 161        writel(reg, clk->pll_ctrl);
 162
 163        spin_unlock_irqrestore(clk->lock, flags);
 164}
 165
 166static const struct clk_ops zynq_pll_ops = {
 167        .enable = zynq_pll_enable,
 168        .disable = zynq_pll_disable,
 169        .is_enabled = zynq_pll_is_enabled,
 170        .round_rate = zynq_pll_round_rate,
 171        .recalc_rate = zynq_pll_recalc_rate
 172};
 173
 174/**
 175 * clk_register_zynq_pll() - Register PLL with the clock framework
 176 * @name:       PLL name
 177 * @parent:     Parent clock name
 178 * @pll_ctrl:   Pointer to PLL control register
 179 * @pll_status: Pointer to PLL status register
 180 * @lock_index: Bit index to this PLL's lock status bit in @pll_status
 181 * @lock:       Register lock
 182 * Returns handle to the registered clock.
 183 */
 184struct clk *clk_register_zynq_pll(const char *name, const char *parent,
 185                void __iomem *pll_ctrl, void __iomem *pll_status, u8 lock_index,
 186                spinlock_t *lock)
 187{
 188        struct zynq_pll *pll;
 189        struct clk *clk;
 190        u32 reg;
 191        const char *parent_arr[1] = {parent};
 192        unsigned long flags = 0;
 193        struct clk_init_data initd = {
 194                .name = name,
 195                .parent_names = parent_arr,
 196                .ops = &zynq_pll_ops,
 197                .num_parents = 1,
 198                .flags = 0
 199        };
 200
 201        pll = kmalloc(sizeof(*pll), GFP_KERNEL);
 202        if (!pll)
 203                return ERR_PTR(-ENOMEM);
 204
 205        /* Populate the struct */
 206        pll->hw.init = &initd;
 207        pll->pll_ctrl = pll_ctrl;
 208        pll->pll_status = pll_status;
 209        pll->lockbit = lock_index;
 210        pll->lock = lock;
 211
 212        spin_lock_irqsave(pll->lock, flags);
 213
 214        reg = readl(pll->pll_ctrl);
 215        reg &= ~PLLCTRL_BPQUAL_MASK;
 216        writel(reg, pll->pll_ctrl);
 217
 218        spin_unlock_irqrestore(pll->lock, flags);
 219
 220        clk = clk_register(NULL, &pll->hw);
 221        if (WARN_ON(IS_ERR(clk)))
 222                goto free_pll;
 223
 224        return clk;
 225
 226free_pll:
 227        kfree(pll);
 228
 229        return clk;
 230}
 231