1*74e4190cSDmitry Baryshkov // SPDX-License-Identifier: GPL-2.0-only
2*74e4190cSDmitry Baryshkov /*
3*74e4190cSDmitry Baryshkov * Copyright (c) 2022, Linaro Ltd.
4*74e4190cSDmitry Baryshkov */
5*74e4190cSDmitry Baryshkov
6*74e4190cSDmitry Baryshkov #include <linux/clk-provider.h>
7*74e4190cSDmitry Baryshkov #include <linux/bitfield.h>
8*74e4190cSDmitry Baryshkov #include <linux/regmap.h>
9*74e4190cSDmitry Baryshkov #include <linux/export.h>
10*74e4190cSDmitry Baryshkov
11*74e4190cSDmitry Baryshkov #include "clk-regmap.h"
12*74e4190cSDmitry Baryshkov #include "clk-regmap-phy-mux.h"
13*74e4190cSDmitry Baryshkov
14*74e4190cSDmitry Baryshkov #define PHY_MUX_MASK GENMASK(1, 0)
15*74e4190cSDmitry Baryshkov #define PHY_MUX_PHY_SRC 0
16*74e4190cSDmitry Baryshkov #define PHY_MUX_REF_SRC 2
17*74e4190cSDmitry Baryshkov
to_clk_regmap_phy_mux(struct clk_regmap * clkr)18*74e4190cSDmitry Baryshkov static inline struct clk_regmap_phy_mux *to_clk_regmap_phy_mux(struct clk_regmap *clkr)
19*74e4190cSDmitry Baryshkov {
20*74e4190cSDmitry Baryshkov return container_of(clkr, struct clk_regmap_phy_mux, clkr);
21*74e4190cSDmitry Baryshkov }
22*74e4190cSDmitry Baryshkov
phy_mux_is_enabled(struct clk_hw * hw)23*74e4190cSDmitry Baryshkov static int phy_mux_is_enabled(struct clk_hw *hw)
24*74e4190cSDmitry Baryshkov {
25*74e4190cSDmitry Baryshkov struct clk_regmap *clkr = to_clk_regmap(hw);
26*74e4190cSDmitry Baryshkov struct clk_regmap_phy_mux *phy_mux = to_clk_regmap_phy_mux(clkr);
27*74e4190cSDmitry Baryshkov unsigned int val;
28*74e4190cSDmitry Baryshkov
29*74e4190cSDmitry Baryshkov regmap_read(clkr->regmap, phy_mux->reg, &val);
30*74e4190cSDmitry Baryshkov val = FIELD_GET(PHY_MUX_MASK, val);
31*74e4190cSDmitry Baryshkov
32*74e4190cSDmitry Baryshkov WARN_ON(val != PHY_MUX_PHY_SRC && val != PHY_MUX_REF_SRC);
33*74e4190cSDmitry Baryshkov
34*74e4190cSDmitry Baryshkov return val == PHY_MUX_PHY_SRC;
35*74e4190cSDmitry Baryshkov }
36*74e4190cSDmitry Baryshkov
phy_mux_enable(struct clk_hw * hw)37*74e4190cSDmitry Baryshkov static int phy_mux_enable(struct clk_hw *hw)
38*74e4190cSDmitry Baryshkov {
39*74e4190cSDmitry Baryshkov struct clk_regmap *clkr = to_clk_regmap(hw);
40*74e4190cSDmitry Baryshkov struct clk_regmap_phy_mux *phy_mux = to_clk_regmap_phy_mux(clkr);
41*74e4190cSDmitry Baryshkov
42*74e4190cSDmitry Baryshkov return regmap_update_bits(clkr->regmap, phy_mux->reg,
43*74e4190cSDmitry Baryshkov PHY_MUX_MASK,
44*74e4190cSDmitry Baryshkov FIELD_PREP(PHY_MUX_MASK, PHY_MUX_PHY_SRC));
45*74e4190cSDmitry Baryshkov }
46*74e4190cSDmitry Baryshkov
phy_mux_disable(struct clk_hw * hw)47*74e4190cSDmitry Baryshkov static void phy_mux_disable(struct clk_hw *hw)
48*74e4190cSDmitry Baryshkov {
49*74e4190cSDmitry Baryshkov struct clk_regmap *clkr = to_clk_regmap(hw);
50*74e4190cSDmitry Baryshkov struct clk_regmap_phy_mux *phy_mux = to_clk_regmap_phy_mux(clkr);
51*74e4190cSDmitry Baryshkov
52*74e4190cSDmitry Baryshkov regmap_update_bits(clkr->regmap, phy_mux->reg,
53*74e4190cSDmitry Baryshkov PHY_MUX_MASK,
54*74e4190cSDmitry Baryshkov FIELD_PREP(PHY_MUX_MASK, PHY_MUX_REF_SRC));
55*74e4190cSDmitry Baryshkov }
56*74e4190cSDmitry Baryshkov
57*74e4190cSDmitry Baryshkov const struct clk_ops clk_regmap_phy_mux_ops = {
58*74e4190cSDmitry Baryshkov .enable = phy_mux_enable,
59*74e4190cSDmitry Baryshkov .disable = phy_mux_disable,
60*74e4190cSDmitry Baryshkov .is_enabled = phy_mux_is_enabled,
61*74e4190cSDmitry Baryshkov };
62*74e4190cSDmitry Baryshkov EXPORT_SYMBOL_GPL(clk_regmap_phy_mux_ops);
63