Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Zynq UltraScale+ MPSoC PLL driver
0004  *
0005  *  Copyright (C) 2016-2018 Xilinx
0006  */
0007 
0008 #include <linux/clk.h>
0009 #include <linux/clk-provider.h>
0010 #include <linux/slab.h>
0011 #include "clk-zynqmp.h"
0012 
0013 /**
0014  * struct zynqmp_pll - PLL clock
0015  * @hw:     Handle between common and hardware-specific interfaces
0016  * @clk_id: PLL clock ID
0017  * @set_pll_mode:   Whether an IOCTL_SET_PLL_FRAC_MODE request be sent to ATF
0018  */
0019 struct zynqmp_pll {
0020     struct clk_hw hw;
0021     u32 clk_id;
0022     bool set_pll_mode;
0023 };
0024 
0025 #define to_zynqmp_pll(_hw)  container_of(_hw, struct zynqmp_pll, hw)
0026 
0027 #define PLL_FBDIV_MIN   25
0028 #define PLL_FBDIV_MAX   125
0029 
0030 #define PS_PLL_VCO_MIN 1500000000
0031 #define PS_PLL_VCO_MAX 3000000000UL
0032 
0033 enum pll_mode {
0034     PLL_MODE_INT = 0,
0035     PLL_MODE_FRAC = 1,
0036     PLL_MODE_ERROR = 2,
0037 };
0038 
0039 #define FRAC_OFFSET 0x8
0040 #define PLLFCFG_FRAC_EN BIT(31)
0041 #define FRAC_DIV  BIT(16)  /* 2^16 */
0042 
0043 /**
0044  * zynqmp_pll_get_mode() - Get mode of PLL
0045  * @hw:     Handle between common and hardware-specific interfaces
0046  *
0047  * Return: Mode of PLL
0048  */
0049 static inline enum pll_mode zynqmp_pll_get_mode(struct clk_hw *hw)
0050 {
0051     struct zynqmp_pll *clk = to_zynqmp_pll(hw);
0052     u32 clk_id = clk->clk_id;
0053     const char *clk_name = clk_hw_get_name(hw);
0054     u32 ret_payload[PAYLOAD_ARG_CNT];
0055     int ret;
0056 
0057     ret = zynqmp_pm_get_pll_frac_mode(clk_id, ret_payload);
0058     if (ret) {
0059         pr_debug("%s() PLL get frac mode failed for %s, ret = %d\n",
0060              __func__, clk_name, ret);
0061         return PLL_MODE_ERROR;
0062     }
0063 
0064     return ret_payload[1];
0065 }
0066 
0067 /**
0068  * zynqmp_pll_set_mode() - Set the PLL mode
0069  * @hw:     Handle between common and hardware-specific interfaces
0070  * @on:     Flag to determine the mode
0071  */
0072 static inline void zynqmp_pll_set_mode(struct clk_hw *hw, bool on)
0073 {
0074     struct zynqmp_pll *clk = to_zynqmp_pll(hw);
0075     u32 clk_id = clk->clk_id;
0076     const char *clk_name = clk_hw_get_name(hw);
0077     int ret;
0078     u32 mode;
0079 
0080     if (on)
0081         mode = PLL_MODE_FRAC;
0082     else
0083         mode = PLL_MODE_INT;
0084 
0085     ret = zynqmp_pm_set_pll_frac_mode(clk_id, mode);
0086     if (ret)
0087         pr_debug("%s() PLL set frac mode failed for %s, ret = %d\n",
0088              __func__, clk_name, ret);
0089     else
0090         clk->set_pll_mode = true;
0091 }
0092 
0093 /**
0094  * zynqmp_pll_round_rate() - Round a clock frequency
0095  * @hw:     Handle between common and hardware-specific interfaces
0096  * @rate:   Desired clock frequency
0097  * @prate:  Clock frequency of parent clock
0098  *
0099  * Return: Frequency closest to @rate the hardware can generate
0100  */
0101 static long zynqmp_pll_round_rate(struct clk_hw *hw, unsigned long rate,
0102                   unsigned long *prate)
0103 {
0104     u32 fbdiv;
0105     long rate_div, f;
0106 
0107     /* Enable the fractional mode if needed */
0108     rate_div = (rate * FRAC_DIV) / *prate;
0109     f = rate_div % FRAC_DIV;
0110     if (f) {
0111         if (rate > PS_PLL_VCO_MAX) {
0112             fbdiv = rate / PS_PLL_VCO_MAX;
0113             rate = rate / (fbdiv + 1);
0114         }
0115         if (rate < PS_PLL_VCO_MIN) {
0116             fbdiv = DIV_ROUND_UP(PS_PLL_VCO_MIN, rate);
0117             rate = rate * fbdiv;
0118         }
0119         return rate;
0120     }
0121 
0122     fbdiv = DIV_ROUND_CLOSEST(rate, *prate);
0123     fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX);
0124     return *prate * fbdiv;
0125 }
0126 
0127 /**
0128  * zynqmp_pll_recalc_rate() - Recalculate clock frequency
0129  * @hw:         Handle between common and hardware-specific interfaces
0130  * @parent_rate:    Clock frequency of parent clock
0131  *
0132  * Return: Current clock frequency or 0 in case of error
0133  */
0134 static unsigned long zynqmp_pll_recalc_rate(struct clk_hw *hw,
0135                         unsigned long parent_rate)
0136 {
0137     struct zynqmp_pll *clk = to_zynqmp_pll(hw);
0138     u32 clk_id = clk->clk_id;
0139     const char *clk_name = clk_hw_get_name(hw);
0140     u32 fbdiv, data;
0141     unsigned long rate, frac;
0142     u32 ret_payload[PAYLOAD_ARG_CNT];
0143     int ret;
0144     enum pll_mode mode;
0145 
0146     ret = zynqmp_pm_clock_getdivider(clk_id, &fbdiv);
0147     if (ret) {
0148         pr_debug("%s() get divider failed for %s, ret = %d\n",
0149              __func__, clk_name, ret);
0150         return 0ul;
0151     }
0152 
0153     mode = zynqmp_pll_get_mode(hw);
0154     if (mode == PLL_MODE_ERROR)
0155         return 0ul;
0156 
0157     rate =  parent_rate * fbdiv;
0158     if (mode == PLL_MODE_FRAC) {
0159         zynqmp_pm_get_pll_frac_data(clk_id, ret_payload);
0160         data = ret_payload[1];
0161         frac = (parent_rate * data) / FRAC_DIV;
0162         rate = rate + frac;
0163     }
0164 
0165     return rate;
0166 }
0167 
0168 /**
0169  * zynqmp_pll_set_rate() - Set rate of PLL
0170  * @hw:         Handle between common and hardware-specific interfaces
0171  * @rate:       Frequency of clock to be set
0172  * @parent_rate:    Clock frequency of parent clock
0173  *
0174  * Set PLL divider to set desired rate.
0175  *
0176  * Returns:            rate which is set on success else error code
0177  */
0178 static int zynqmp_pll_set_rate(struct clk_hw *hw, unsigned long rate,
0179                    unsigned long parent_rate)
0180 {
0181     struct zynqmp_pll *clk = to_zynqmp_pll(hw);
0182     u32 clk_id = clk->clk_id;
0183     const char *clk_name = clk_hw_get_name(hw);
0184     u32 fbdiv;
0185     long rate_div, frac, m, f;
0186     int ret;
0187 
0188     rate_div = (rate * FRAC_DIV) / parent_rate;
0189     f = rate_div % FRAC_DIV;
0190     zynqmp_pll_set_mode(hw, !!f);
0191 
0192     if (f) {
0193         m = rate_div / FRAC_DIV;
0194         m = clamp_t(u32, m, (PLL_FBDIV_MIN), (PLL_FBDIV_MAX));
0195         rate = parent_rate * m;
0196         frac = (parent_rate * f) / FRAC_DIV;
0197 
0198         ret = zynqmp_pm_clock_setdivider(clk_id, m);
0199         if (ret == -EUSERS)
0200             WARN(1, "More than allowed devices are using the %s, which is forbidden\n",
0201                  clk_name);
0202         else if (ret)
0203             pr_debug("%s() set divider failed for %s, ret = %d\n",
0204                  __func__, clk_name, ret);
0205         zynqmp_pm_set_pll_frac_data(clk_id, f);
0206 
0207         return rate + frac;
0208     }
0209 
0210     fbdiv = DIV_ROUND_CLOSEST(rate, parent_rate);
0211     fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX);
0212     ret = zynqmp_pm_clock_setdivider(clk_id, fbdiv);
0213     if (ret)
0214         pr_debug("%s() set divider failed for %s, ret = %d\n",
0215              __func__, clk_name, ret);
0216 
0217     return parent_rate * fbdiv;
0218 }
0219 
0220 /**
0221  * zynqmp_pll_is_enabled() - Check if a clock is enabled
0222  * @hw:     Handle between common and hardware-specific interfaces
0223  *
0224  * Return: 1 if the clock is enabled, 0 otherwise
0225  */
0226 static int zynqmp_pll_is_enabled(struct clk_hw *hw)
0227 {
0228     struct zynqmp_pll *clk = to_zynqmp_pll(hw);
0229     const char *clk_name = clk_hw_get_name(hw);
0230     u32 clk_id = clk->clk_id;
0231     unsigned int state;
0232     int ret;
0233 
0234     ret = zynqmp_pm_clock_getstate(clk_id, &state);
0235     if (ret) {
0236         pr_debug("%s() clock get state failed for %s, ret = %d\n",
0237              __func__, clk_name, ret);
0238         return -EIO;
0239     }
0240 
0241     return state ? 1 : 0;
0242 }
0243 
0244 /**
0245  * zynqmp_pll_enable() - Enable clock
0246  * @hw:     Handle between common and hardware-specific interfaces
0247  *
0248  * Return: 0 on success else error code
0249  */
0250 static int zynqmp_pll_enable(struct clk_hw *hw)
0251 {
0252     struct zynqmp_pll *clk = to_zynqmp_pll(hw);
0253     const char *clk_name = clk_hw_get_name(hw);
0254     u32 clk_id = clk->clk_id;
0255     int ret;
0256 
0257     /*
0258      * Don't skip enabling clock if there is an IOCTL_SET_PLL_FRAC_MODE request
0259      * that has been sent to ATF.
0260      */
0261     if (zynqmp_pll_is_enabled(hw) && (!clk->set_pll_mode))
0262         return 0;
0263 
0264     clk->set_pll_mode = false;
0265 
0266     ret = zynqmp_pm_clock_enable(clk_id);
0267     if (ret)
0268         pr_debug("%s() clock enable failed for %s, ret = %d\n",
0269              __func__, clk_name, ret);
0270 
0271     return ret;
0272 }
0273 
0274 /**
0275  * zynqmp_pll_disable() - Disable clock
0276  * @hw:     Handle between common and hardware-specific interfaces
0277  */
0278 static void zynqmp_pll_disable(struct clk_hw *hw)
0279 {
0280     struct zynqmp_pll *clk = to_zynqmp_pll(hw);
0281     const char *clk_name = clk_hw_get_name(hw);
0282     u32 clk_id = clk->clk_id;
0283     int ret;
0284 
0285     if (!zynqmp_pll_is_enabled(hw))
0286         return;
0287 
0288     ret = zynqmp_pm_clock_disable(clk_id);
0289     if (ret)
0290         pr_debug("%s() clock disable failed for %s, ret = %d\n",
0291              __func__, clk_name, ret);
0292 }
0293 
0294 static const struct clk_ops zynqmp_pll_ops = {
0295     .enable = zynqmp_pll_enable,
0296     .disable = zynqmp_pll_disable,
0297     .is_enabled = zynqmp_pll_is_enabled,
0298     .round_rate = zynqmp_pll_round_rate,
0299     .recalc_rate = zynqmp_pll_recalc_rate,
0300     .set_rate = zynqmp_pll_set_rate,
0301 };
0302 
0303 /**
0304  * zynqmp_clk_register_pll() - Register PLL with the clock framework
0305  * @name:       PLL name
0306  * @clk_id:     Clock ID
0307  * @parents:        Name of this clock's parents
0308  * @num_parents:    Number of parents
0309  * @nodes:      Clock topology node
0310  *
0311  * Return: clock hardware to the registered clock
0312  */
0313 struct clk_hw *zynqmp_clk_register_pll(const char *name, u32 clk_id,
0314                        const char * const *parents,
0315                        u8 num_parents,
0316                        const struct clock_topology *nodes)
0317 {
0318     struct zynqmp_pll *pll;
0319     struct clk_hw *hw;
0320     struct clk_init_data init;
0321     int ret;
0322 
0323     init.name = name;
0324     init.ops = &zynqmp_pll_ops;
0325 
0326     init.flags = zynqmp_clk_map_common_ccf_flags(nodes->flag);
0327 
0328     init.parent_names = parents;
0329     init.num_parents = 1;
0330 
0331     pll = kzalloc(sizeof(*pll), GFP_KERNEL);
0332     if (!pll)
0333         return ERR_PTR(-ENOMEM);
0334 
0335     pll->hw.init = &init;
0336     pll->clk_id = clk_id;
0337 
0338     hw = &pll->hw;
0339     ret = clk_hw_register(NULL, hw);
0340     if (ret) {
0341         kfree(pll);
0342         return ERR_PTR(ret);
0343     }
0344 
0345     clk_hw_set_rate_range(hw, PS_PLL_VCO_MIN, PS_PLL_VCO_MAX);
0346 
0347     return hw;
0348 }