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