root/drivers/clk/imx/clk-frac-pll.c

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

DEFINITIONS

This source file includes following definitions.
  1. clk_wait_lock
  2. clk_wait_ack
  3. clk_pll_prepare
  4. clk_pll_unprepare
  5. clk_pll_is_prepared
  6. clk_pll_recalc_rate
  7. clk_pll_round_rate
  8. clk_pll_set_rate
  9. imx_clk_frac_pll

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright 2018 NXP.
   4  *
   5  * This driver supports the fractional plls found in the imx8m SOCs
   6  *
   7  * Documentation for this fractional pll can be found at:
   8  *   https://www.nxp.com/docs/en/reference-manual/IMX8MDQLQRM.pdf#page=834
   9  */
  10 
  11 #include <linux/clk-provider.h>
  12 #include <linux/err.h>
  13 #include <linux/io.h>
  14 #include <linux/iopoll.h>
  15 #include <linux/slab.h>
  16 #include <linux/bitfield.h>
  17 
  18 #include "clk.h"
  19 
  20 #define PLL_CFG0                0x0
  21 #define PLL_CFG1                0x4
  22 
  23 #define PLL_LOCK_STATUS         BIT(31)
  24 #define PLL_PD_MASK             BIT(19)
  25 #define PLL_BYPASS_MASK         BIT(14)
  26 #define PLL_NEWDIV_VAL          BIT(12)
  27 #define PLL_NEWDIV_ACK          BIT(11)
  28 #define PLL_FRAC_DIV_MASK       GENMASK(30, 7)
  29 #define PLL_INT_DIV_MASK        GENMASK(6, 0)
  30 #define PLL_OUTPUT_DIV_MASK     GENMASK(4, 0)
  31 #define PLL_FRAC_DENOM          0x1000000
  32 
  33 #define PLL_FRAC_LOCK_TIMEOUT   10000
  34 #define PLL_FRAC_ACK_TIMEOUT    500000
  35 
  36 struct clk_frac_pll {
  37         struct clk_hw   hw;
  38         void __iomem    *base;
  39 };
  40 
  41 #define to_clk_frac_pll(_hw) container_of(_hw, struct clk_frac_pll, hw)
  42 
  43 static int clk_wait_lock(struct clk_frac_pll *pll)
  44 {
  45         u32 val;
  46 
  47         return readl_poll_timeout(pll->base, val, val & PLL_LOCK_STATUS, 0,
  48                                         PLL_FRAC_LOCK_TIMEOUT);
  49 }
  50 
  51 static int clk_wait_ack(struct clk_frac_pll *pll)
  52 {
  53         u32 val;
  54 
  55         /* return directly if the pll is in powerdown or in bypass */
  56         if (readl_relaxed(pll->base) & (PLL_PD_MASK | PLL_BYPASS_MASK))
  57                 return 0;
  58 
  59         /* Wait for the pll's divfi and divff to be reloaded */
  60         return readl_poll_timeout(pll->base, val, val & PLL_NEWDIV_ACK, 0,
  61                                         PLL_FRAC_ACK_TIMEOUT);
  62 }
  63 
  64 static int clk_pll_prepare(struct clk_hw *hw)
  65 {
  66         struct clk_frac_pll *pll = to_clk_frac_pll(hw);
  67         u32 val;
  68 
  69         val = readl_relaxed(pll->base + PLL_CFG0);
  70         val &= ~PLL_PD_MASK;
  71         writel_relaxed(val, pll->base + PLL_CFG0);
  72 
  73         return clk_wait_lock(pll);
  74 }
  75 
  76 static void clk_pll_unprepare(struct clk_hw *hw)
  77 {
  78         struct clk_frac_pll *pll = to_clk_frac_pll(hw);
  79         u32 val;
  80 
  81         val = readl_relaxed(pll->base + PLL_CFG0);
  82         val |= PLL_PD_MASK;
  83         writel_relaxed(val, pll->base + PLL_CFG0);
  84 }
  85 
  86 static int clk_pll_is_prepared(struct clk_hw *hw)
  87 {
  88         struct clk_frac_pll *pll = to_clk_frac_pll(hw);
  89         u32 val;
  90 
  91         val = readl_relaxed(pll->base + PLL_CFG0);
  92         return (val & PLL_PD_MASK) ? 0 : 1;
  93 }
  94 
  95 static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
  96                                          unsigned long parent_rate)
  97 {
  98         struct clk_frac_pll *pll = to_clk_frac_pll(hw);
  99         u32 val, divff, divfi, divq;
 100         u64 temp64 = parent_rate;
 101         u64 rate;
 102 
 103         val = readl_relaxed(pll->base + PLL_CFG0);
 104         divq = (FIELD_GET(PLL_OUTPUT_DIV_MASK, val) + 1) * 2;
 105         val = readl_relaxed(pll->base + PLL_CFG1);
 106         divff = FIELD_GET(PLL_FRAC_DIV_MASK, val);
 107         divfi = FIELD_GET(PLL_INT_DIV_MASK, val);
 108 
 109         temp64 *= 8;
 110         temp64 *= divff;
 111         do_div(temp64, PLL_FRAC_DENOM);
 112         do_div(temp64, divq);
 113 
 114         rate = parent_rate * 8 * (divfi + 1);
 115         do_div(rate, divq);
 116         rate += temp64;
 117 
 118         return rate;
 119 }
 120 
 121 static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 122                                unsigned long *prate)
 123 {
 124         u64 parent_rate = *prate;
 125         u32 divff, divfi;
 126         u64 temp64;
 127 
 128         parent_rate *= 8;
 129         rate *= 2;
 130         temp64 = rate;
 131         do_div(temp64, parent_rate);
 132         divfi = temp64;
 133         temp64 = rate - divfi * parent_rate;
 134         temp64 *= PLL_FRAC_DENOM;
 135         do_div(temp64, parent_rate);
 136         divff = temp64;
 137 
 138         temp64 = parent_rate;
 139         temp64 *= divff;
 140         do_div(temp64, PLL_FRAC_DENOM);
 141 
 142         rate = parent_rate * divfi + temp64;
 143 
 144         return rate / 2;
 145 }
 146 
 147 /*
 148  * To simplify the clock calculation, we can keep the 'PLL_OUTPUT_VAL' at zero
 149  * (means the PLL output will be divided by 2). So the PLL output can use
 150  * the below formula:
 151  * pllout = parent_rate * 8 / 2 * DIVF_VAL;
 152  * where DIVF_VAL = 1 + DIVFI + DIVFF / 2^24.
 153  */
 154 static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 155                             unsigned long parent_rate)
 156 {
 157         struct clk_frac_pll *pll = to_clk_frac_pll(hw);
 158         u32 val, divfi, divff;
 159         u64 temp64;
 160         int ret;
 161 
 162         parent_rate *= 8;
 163         rate *= 2;
 164         divfi = rate / parent_rate;
 165         temp64 = parent_rate * divfi;
 166         temp64 = rate - temp64;
 167         temp64 *= PLL_FRAC_DENOM;
 168         do_div(temp64, parent_rate);
 169         divff = temp64;
 170 
 171         val = readl_relaxed(pll->base + PLL_CFG1);
 172         val &= ~(PLL_FRAC_DIV_MASK | PLL_INT_DIV_MASK);
 173         val |= (divff << 7) | (divfi - 1);
 174         writel_relaxed(val, pll->base + PLL_CFG1);
 175 
 176         val = readl_relaxed(pll->base + PLL_CFG0);
 177         val &= ~0x1f;
 178         writel_relaxed(val, pll->base + PLL_CFG0);
 179 
 180         /* Set the NEV_DIV_VAL to reload the DIVFI and DIVFF */
 181         val = readl_relaxed(pll->base + PLL_CFG0);
 182         val |= PLL_NEWDIV_VAL;
 183         writel_relaxed(val, pll->base + PLL_CFG0);
 184 
 185         ret = clk_wait_ack(pll);
 186 
 187         /* clear the NEV_DIV_VAL */
 188         val = readl_relaxed(pll->base + PLL_CFG0);
 189         val &= ~PLL_NEWDIV_VAL;
 190         writel_relaxed(val, pll->base + PLL_CFG0);
 191 
 192         return ret;
 193 }
 194 
 195 static const struct clk_ops clk_frac_pll_ops = {
 196         .prepare        = clk_pll_prepare,
 197         .unprepare      = clk_pll_unprepare,
 198         .is_prepared    = clk_pll_is_prepared,
 199         .recalc_rate    = clk_pll_recalc_rate,
 200         .round_rate     = clk_pll_round_rate,
 201         .set_rate       = clk_pll_set_rate,
 202 };
 203 
 204 struct clk *imx_clk_frac_pll(const char *name, const char *parent_name,
 205                              void __iomem *base)
 206 {
 207         struct clk_init_data init;
 208         struct clk_frac_pll *pll;
 209         struct clk_hw *hw;
 210         int ret;
 211 
 212         pll = kzalloc(sizeof(*pll), GFP_KERNEL);
 213         if (!pll)
 214                 return ERR_PTR(-ENOMEM);
 215 
 216         init.name = name;
 217         init.ops = &clk_frac_pll_ops;
 218         init.flags = 0;
 219         init.parent_names = &parent_name;
 220         init.num_parents = 1;
 221 
 222         pll->base = base;
 223         pll->hw.init = &init;
 224 
 225         hw = &pll->hw;
 226 
 227         ret = clk_hw_register(NULL, hw);
 228         if (ret) {
 229                 kfree(pll);
 230                 return ERR_PTR(ret);
 231         }
 232 
 233         return hw->clk;
 234 }

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