static int clkgena_divmux_is_enabled(struct clk_hw *hw) { struct clkgena_divmux *genamux = to_clkgena_divmux(hw); struct clk_hw *mux_hw = &genamux->mux.hw; __clk_hw_set_clk(mux_hw, hw); return (s8)clk_mux_ops.get_parent(mux_hw) > 0; }
static void clkgena_divmux_disable(struct clk_hw *hw) { struct clkgena_divmux *genamux = to_clkgena_divmux(hw); struct clk_hw *mux_hw = &genamux->mux.hw; __clk_hw_set_clk(mux_hw, hw); clk_mux_ops.set_parent(mux_hw, CKGAX_CLKOPSRC_SWITCH_OFF); }
static long clkgena_divmux_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { struct clkgena_divmux *genamux = to_clkgena_divmux(hw); struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw; __clk_hw_set_clk(div_hw, hw); return clk_divider_ops.round_rate(div_hw, rate, prate); }
static unsigned long clkgena_divmux_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clkgena_divmux *genamux = to_clkgena_divmux(hw); struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw; __clk_hw_set_clk(div_hw, hw); return clk_divider_ops.recalc_rate(div_hw, parent_rate); }
static int clkgena_divmux_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clkgena_divmux *genamux = to_clkgena_divmux(hw); struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw; div_hw->clk = hw->clk; return clk_divider_ops.set_rate(div_hw, rate, parent_rate); }
static u8 clkgena_divmux_get_parent(struct clk_hw *hw) { struct clkgena_divmux *genamux = to_clkgena_divmux(hw); struct clk_hw *mux_hw = &genamux->mux.hw; __clk_hw_set_clk(mux_hw, hw); genamux->muxsel = clk_mux_ops.get_parent(mux_hw); if ((s8)genamux->muxsel < 0) { pr_debug("%s: %s: Invalid parent, setting to default.\n", __func__, clk_hw_get_name(hw)); genamux->muxsel = 0; } return genamux->muxsel; }
static int clkgena_divmux_set_parent(struct clk_hw *hw, u8 index) { struct clkgena_divmux *genamux = to_clkgena_divmux(hw); if (index >= CKGAX_CLKOPSRC_SWITCH_OFF) return -EINVAL; genamux->muxsel = index; /* * If the mux is already enabled, call enable directly to set the * new mux position and wait for it to start running again. Otherwise * do nothing. */ if (clkgena_divmux_is_enabled(hw)) clkgena_divmux_enable(hw); return 0; }
static int clkgena_divmux_enable(struct clk_hw *hw) { struct clkgena_divmux *genamux = to_clkgena_divmux(hw); struct clk_hw *mux_hw = &genamux->mux.hw; unsigned long timeout; int ret = 0; __clk_hw_set_clk(mux_hw, hw); ret = clk_mux_ops.set_parent(mux_hw, genamux->muxsel); if (ret) return ret; timeout = jiffies + msecs_to_jiffies(10); while (!clkgena_divmux_is_running(genamux)) { if (time_after(jiffies, timeout)) return -ETIMEDOUT; cpu_relax(); } return 0; }