/** * zynq_periphclk_div2_set_rate() - Change clock frequncy * @hw: Handle between common and hardware-specific interfaces * @rate: Desired clock frequency * @prate: Clock frequency of parent clock * Returns 0 on success, negative errno otherwise. */ static int zynq_periphclk_div2_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long prate) { u32 div1; u32 div2; u32 reg; unsigned long flags = 0; struct zynq_periph_clk *clk = to_zynq_periph_clk(hw); if (!zynq_periphclk_get_best_divs2(prate, rate, &div1, &div2)) return -EINVAL; spin_lock_irqsave(clk->lock, flags); reg = readl(clk->clkctrl); reg &= ~CLKCTRL_DIV1_MASK; reg &= ~CLKCTRL_DIV2_MASK; reg |= div1 << CLKCTRL_DIV1_SHIFT; reg |= div2 << CLKCTRL_DIV2_SHIFT; writel(reg, clk->clkctrl); spin_unlock_irqrestore(clk->lock, flags); return 0; }
/** * zynq_periphclk_get_parent() - Reparent clock * @hw: Handle between common and hardware-specific interfaces * Returns the index of the current clock parent. */ static u8 zynq_periphclk_get_parent(struct clk_hw *hw) { struct zynq_periph_clk *clk = to_zynq_periph_clk(hw); return (readl(clk->clkctrl) & CLKCTRL_CLKSRC_MASK) >> CLKCTRL_CLKSRC_SHIFT; }
/** * zynq_periphclk_gate1_disable - Disable clock * @hw: Handle between common and hardware-specific interfaces * Returns 0 on success */ static void zynq_periphclk_gate1_disable(struct clk_hw *hw) { u32 reg; unsigned long flags = 0; struct zynq_periph_clk *clk = to_zynq_periph_clk(hw); spin_lock_irqsave(clk->lock, flags); reg = readl(clk->clkctrl); reg &= ~CLKCTRL_ENABLE_MASK; writel(reg, clk->clkctrl); spin_unlock_irqrestore(clk->lock, flags); }
/** * zynq_periphclk_gate1_is_enabled - Check if a clock is enabled * @hw: Handle between common and hardware-specific interfaces * Returns 1 if the clock is enabled, 0 otherwise. */ static int zynq_periphclk_gate1_is_enabled(struct clk_hw *hw) { u32 reg; unsigned long flags = 0; struct zynq_periph_clk *clk = to_zynq_periph_clk(hw); /* do we need lock for read? */ spin_lock_irqsave(clk->lock, flags); reg = readl(clk->clkctrl); spin_unlock_irqrestore(clk->lock, flags); return (reg & CLKCTRL_ENABLE_MASK) >> CLKCTRL_ENABLE_SHIFT; }
/** * zynq_periphclk_set_parent() - Reparent clock * @hw: Handle between common and hardware-specific interfaces * @index: Index of new parent. * Returns 0 on success, negative errno otherwise. */ static int zynq_periphclk_set_parent(struct clk_hw *hw, u8 index) { u32 reg; unsigned long flags = 0; struct zynq_periph_clk *clk = to_zynq_periph_clk(hw); spin_lock_irqsave(clk->lock, flags); reg = readl(clk->clkctrl); reg &= ~CLKCTRL_CLKSRC_MASK; reg |= index << CLKCTRL_CLKSRC_SHIFT; writel(reg, clk->clkctrl); spin_unlock_irqrestore(clk->lock, flags); return 0; }
/** * zynq_periphclk_div1_recalc_rate() - Recalculate clock frequency * @hw: Handle between common and hardware-specific interfaces * @parent_rate: Clock frequency of parent clock * Returns current clock frequency. */ static unsigned long zynq_periphclk_div1_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { u32 div; struct zynq_periph_clk *clk = to_zynq_periph_clk(hw); /* * makes probably sense to redundantly save div in the struct * zynq_periphclk_gd1m to save the IO access. Do we need spinlock for * read access? */ div = (readl(clk->clkctrl) & CLKCTRL_DIV_MASK) >> CLKCTRL_DIV_SHIFT; if (div < 1) div = 1; return parent_rate / div; }
/** * zynq_periphclk_div1_recalc_rate() - Recalculate clock frequency * @hw: Handle between common and hardware-specific interfaces * @parent_rate: Clock frequency of parent clock * Returns current clock frequency. */ static unsigned long zynq_periphclk_div2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { u32 div1; u32 div2; struct zynq_periph_clk *clk = to_zynq_periph_clk(hw); /* * makes probably sense to redundantly save div in the struct * zynq_periphclk_gd1m to save the IO access. Should we use spinlock for * reading? */ div1 = (readl(clk->clkctrl) & CLKCTRL_DIV1_MASK) >> CLKCTRL_DIV1_SHIFT; div2 = (readl(clk->clkctrl) & CLKCTRL_DIV2_MASK) >> CLKCTRL_DIV2_SHIFT; if (div1 < 1) div1 = 1; if (div2 < 1) div2 = 1; return (parent_rate / div1) / div2; }
/** * zynq_periphclk_div1_set_rate() - Change clock frequncy * @hw: Handle between common and hardware-specific interfaces * @rate: Desired clock frequency * @prate: Clock frequency of parent clock * Returns 0 on success, negative errno otherwise. */ static int zynq_periphclk_div1_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long prate) { u32 div = DIV_ROUND_CLOSEST(prate, rate); u32 reg; unsigned long flags = 0; struct zynq_periph_clk *clk = to_zynq_periph_clk(hw); if ((div < 1) || (div > 0x3f)) return -EINVAL; spin_lock_irqsave(clk->lock, flags); reg = readl(clk->clkctrl); reg &= ~CLKCTRL_DIV_MASK; reg |= div << CLKCTRL_DIV_SHIFT; writel(reg, clk->clkctrl); spin_unlock_irqrestore(clk->lock, flags); return 0; }
static int zynq_periph_get_parent(struct clk *clk) { struct zynq_periph_clk *periph = to_zynq_periph_clk(clk); return PERIPH_CLK_CTRL_SRC(readl(periph->clk_ctrl)); }
static unsigned long zynq_periph_recalc_rate(struct clk *clk, unsigned long parent_rate) { struct zynq_periph_clk *periph = to_zynq_periph_clk(clk); return parent_rate / PERIPH_CLK_CTRL_DIV(readl(periph->clk_ctrl)); }
static u8 zynq_periph_get_parent(struct clk_hw *hw) { struct zynq_periph_clk *periph = to_zynq_periph_clk(hw); return PERIPH_CLK_CTRL_SRC(ioread32(periph->clk_ctrl)); }
static unsigned long zynq_periph_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct zynq_periph_clk *periph = to_zynq_periph_clk(hw); return parent_rate / PERIPH_CLK_CTRL_DIV(ioread32(periph->clk_ctrl)); }