static freq_t
_pll_set_freq(clk_t* clk, freq_t hz)
{
    volatile uint32_t* ctrl_reg;
    volatile uint32_t* cfg_reg;
    uint32_t status_mask;
    uint32_t fin;
    uint8_t fdiv;

    fin = clk_get_freq(clk->parent);
    fdiv = fin / hz;
    fdiv = INRANGE(PLL_CTRL_FDIV_MIN, fdiv, PLL_CTRL_FDIV_MAX);

    status_mask = _decode_pll(clk, &ctrl_reg, &cfg_reg);
    if (status_mask == 0) {
        return 0;
    }

    /* Program the feedback divider value and the configuration register */
    *ctrl_reg &= ~(PLL_CTRL_FDIV_MASK);
    *ctrl_reg |= PLL_CTRL_FDIV(fdiv);
    *cfg_reg = pll_cfg_tbl[fdiv - PLL_CTRL_FDIV_MIN].pll_cfg;

    /* Force the PLL into bypass mode */
    *ctrl_reg |= PLL_CTRL_BYPASS_FORCE;

    /* Assert and de-assert the PLL reset */
    *ctrl_reg |= PLL_CTRL_RESET;
    *ctrl_reg &= ~(PLL_CTRL_RESET);

    /* Verify that the PLL is locked */
    while (!(clk_regs->pll_status & status_mask));

    /* Disable the PLL bypass mode */
    *ctrl_reg &= ~(PLL_CTRL_BYPASS_FORCE);

    return clk_get_freq(clk);
}
static unsigned long zynq_pll_recalc_rate(struct clk *clk,
					  unsigned long parent_rate)
{
	struct zynq_pll_clk *pll = to_zynq_pll_clk(clk);
	return parent_rate * PLL_CTRL_FDIV(readl(pll->pll_ctrl));
}