return reg ? PLL_MODE_FRAC : PLL_MODE_INT;
}
+/**
+ * pll_frac_set_mode - Set the fractional mode
+ * @hw: Handle between common and hardware-specific interfaces
+ * @on: Flag to determine the mode
+ */
+static inline void pll_frac_set_mode(struct clk_hw *hw, bool on)
+{
+ struct zynqmp_pll *clk = to_zynqmp_pll(hw);
+ u32 reg = 0;
+ int ret;
+
+ if (on)
+ reg = PLLFCFG_FRAC_EN;
+
+ ret = zynqmp_pm_mmio_write((u32)(ulong)(clk->pll_ctrl + FRAC_OFFSET),
+ PLLFCFG_FRAC_EN, reg);
+ if (ret)
+ pr_warn_once("Write fail pll address: %x\n",
+ (u32)(ulong)(clk->pll_ctrl + FRAC_OFFSET));
+}
+
/**
* zynqmp_pll_round_rate - Round a clock frequency
* @hw: Handle between common and hardware-specific interfaces
unsigned long *prate)
{
u32 fbdiv;
+ long rate_div, f;
+
+ /* Enable the fractional mode if needed */
+ rate_div = ((rate * FRAC_DIV) / *prate);
+ f = rate_div % FRAC_DIV;
+ pll_frac_set_mode(hw, !!f);
if (pll_frac_get_mode(hw) == PLL_MODE_FRAC) {
if (rate > PS_PLL_VCO_MAX) {
long rate_div, frac, m, f;
if (pll_frac_get_mode(hw) == PLL_MODE_FRAC) {
- rate_div = ((rate*1000000) / parent_rate);
- m = rate_div / 1000000;
- f = rate_div % 1000000;
+ rate_div = ((rate * FRAC_DIV) / parent_rate);
+ m = rate_div / FRAC_DIV;
+ f = rate_div % FRAC_DIV;
m = clamp_t(u32, m, (PLL_FBDIV_MIN), (PLL_FBDIV_MAX));
rate = parent_rate * m;
- frac = (parent_rate * f) / 1000000;
+ frac = (parent_rate * f) / FRAC_DIV;
reg = zynqmp_pm_mmio_readl(clk->pll_ctrl);
reg &= ~PLLCTRL_FBDIV_MASK;
reg |= m << PLLCTRL_FBDIV_SHIFT;
reg = zynqmp_pm_mmio_readl(clk->pll_ctrl + FRAC_OFFSET);
reg &= ~0xffff;
- data = (FRAC_DIV * f) / 1000000;
+ data = (FRAC_DIV * f) / FRAC_DIV;
data = data & 0xffff;
reg |= data;
zynqmp_pm_mmio_writel(reg, clk->pll_ctrl + FRAC_OFFSET);