diff --git a/drivers/clk/qcom/clk-regmap-phy-mux.c b/drivers/clk/qcom/clk-regmap-phy-mux.c index 7b7243b7107d..b7d1c69d62f7 100644 --- a/drivers/clk/qcom/clk-regmap-phy-mux.c +++ b/drivers/clk/qcom/clk-regmap-phy-mux.c @@ -15,48 +15,66 @@ #define PHY_MUX_PHY_SRC 0 #define PHY_MUX_REF_SRC 2 +#define XO_RATE 19200000UL + static inline struct clk_regmap_phy_mux *to_clk_regmap_phy_mux(struct clk_regmap *clkr) { return container_of(clkr, struct clk_regmap_phy_mux, clkr); } -static int phy_mux_is_enabled(struct clk_hw *hw) +static unsigned long phy_mux_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_regmap *clkr = to_clk_regmap(hw); struct clk_regmap_phy_mux *phy_mux = to_clk_regmap_phy_mux(clkr); - unsigned int val; + u32 val; regmap_read(clkr->regmap, phy_mux->reg, &val); - val = FIELD_GET(PHY_MUX_MASK, val); - WARN_ON(val != PHY_MUX_PHY_SRC && val != PHY_MUX_REF_SRC); - - return val == PHY_MUX_PHY_SRC; + switch (FIELD_GET(PHY_MUX_MASK, val)) { + case PHY_MUX_PHY_SRC: + return ULONG_MAX; + case PHY_MUX_REF_SRC: + return XO_RATE; + default: + return 0; + } } -static int phy_mux_enable(struct clk_hw *hw) +static int phy_mux_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) +{ + if (req->rate == XO_RATE || req->rate == ULONG_MAX) + return 0; + + return -EINVAL; +} + +static int phy_mux_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clk_regmap *clkr = to_clk_regmap(hw); struct clk_regmap_phy_mux *phy_mux = to_clk_regmap_phy_mux(clkr); + u32 val; - return regmap_update_bits(clkr->regmap, phy_mux->reg, - PHY_MUX_MASK, - FIELD_PREP(PHY_MUX_MASK, PHY_MUX_PHY_SRC)); -} - -static void phy_mux_disable(struct clk_hw *hw) -{ - struct clk_regmap *clkr = to_clk_regmap(hw); - struct clk_regmap_phy_mux *phy_mux = to_clk_regmap_phy_mux(clkr); + switch (rate) { + case XO_RATE: + val = PHY_MUX_REF_SRC; + break; + case ULONG_MAX: + val = PHY_MUX_PHY_SRC; + break; + default: + return -EINVAL; + } regmap_update_bits(clkr->regmap, phy_mux->reg, PHY_MUX_MASK, - FIELD_PREP(PHY_MUX_MASK, PHY_MUX_REF_SRC)); + FIELD_PREP(PHY_MUX_MASK, val)); + + return 0; } const struct clk_ops clk_regmap_phy_mux_ops = { - .enable = phy_mux_enable, - .disable = phy_mux_disable, - .is_enabled = phy_mux_is_enabled, + .recalc_rate = phy_mux_recalc_rate, + .determine_rate = phy_mux_determine_rate, + .set_rate = phy_mux_set_rate, }; EXPORT_SYMBOL_GPL(clk_regmap_phy_mux_ops);