root/drivers/clk/zynq/pll.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. zynq_pll_round_rate
  2. zynq_pll_recalc_rate
  3. zynq_pll_is_enabled
  4. zynq_pll_enable
  5. zynq_pll_disable
  6. clk_register_zynq_pll

   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  */
  23 struct 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  */
  51 static 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  */
  71 static 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  */
  95 static 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  */
 115 static 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  */
 145 static 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 
 166 static 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  */
 184 struct 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 
 226 free_pll:
 227         kfree(pll);
 228 
 229         return clk;
 230 }

/* [<][>][^][v][top][bottom][index][help] */