19c92ab61SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2b3ee3effSStephen Boyd /*
3b3ee3effSStephen Boyd  * Copyright (c) 2014, The Linux Foundation. All rights reserved.
4b3ee3effSStephen Boyd  */
5b3ee3effSStephen Boyd 
6b3ee3effSStephen Boyd #include <linux/kernel.h>
7b3ee3effSStephen Boyd #include <linux/bitops.h>
8b3ee3effSStephen Boyd #include <linux/regmap.h>
9b3ee3effSStephen Boyd #include <linux/export.h>
10b3ee3effSStephen Boyd 
11b3ee3effSStephen Boyd #include "clk-regmap-mux.h"
12b3ee3effSStephen Boyd 
to_clk_regmap_mux(struct clk_hw * hw)13b3ee3effSStephen Boyd static inline struct clk_regmap_mux *to_clk_regmap_mux(struct clk_hw *hw)
14b3ee3effSStephen Boyd {
15b3ee3effSStephen Boyd 	return container_of(to_clk_regmap(hw), struct clk_regmap_mux, clkr);
16b3ee3effSStephen Boyd }
17b3ee3effSStephen Boyd 
mux_get_parent(struct clk_hw * hw)18b3ee3effSStephen Boyd static u8 mux_get_parent(struct clk_hw *hw)
19b3ee3effSStephen Boyd {
20b3ee3effSStephen Boyd 	struct clk_regmap_mux *mux = to_clk_regmap_mux(hw);
21b3ee3effSStephen Boyd 	struct clk_regmap *clkr = to_clk_regmap(hw);
22b3ee3effSStephen Boyd 	unsigned int mask = GENMASK(mux->width - 1, 0);
23b3ee3effSStephen Boyd 	unsigned int val;
24b3ee3effSStephen Boyd 
25b3ee3effSStephen Boyd 	regmap_read(clkr->regmap, mux->reg, &val);
26b3ee3effSStephen Boyd 
27b3ee3effSStephen Boyd 	val >>= mux->shift;
28b3ee3effSStephen Boyd 	val &= mask;
29b3ee3effSStephen Boyd 
30df964016SAbhishek Sahu 	if (mux->parent_map)
31*0138d396SDmitry Baryshkov 		return qcom_find_cfg_index(hw, mux->parent_map, val);
32df964016SAbhishek Sahu 
33b3ee3effSStephen Boyd 	return val;
34b3ee3effSStephen Boyd }
35b3ee3effSStephen Boyd 
mux_set_parent(struct clk_hw * hw,u8 index)36b3ee3effSStephen Boyd static int mux_set_parent(struct clk_hw *hw, u8 index)
37b3ee3effSStephen Boyd {
38b3ee3effSStephen Boyd 	struct clk_regmap_mux *mux = to_clk_regmap_mux(hw);
39b3ee3effSStephen Boyd 	struct clk_regmap *clkr = to_clk_regmap(hw);
40b3ee3effSStephen Boyd 	unsigned int mask = GENMASK(mux->width + mux->shift - 1, mux->shift);
41b3ee3effSStephen Boyd 	unsigned int val;
42b3ee3effSStephen Boyd 
43df964016SAbhishek Sahu 	if (mux->parent_map)
44df964016SAbhishek Sahu 		index = mux->parent_map[index].cfg;
45df964016SAbhishek Sahu 
46b3ee3effSStephen Boyd 	val = index;
47b3ee3effSStephen Boyd 	val <<= mux->shift;
48b3ee3effSStephen Boyd 
49b3ee3effSStephen Boyd 	return regmap_update_bits(clkr->regmap, mux->reg, mask, val);
50b3ee3effSStephen Boyd }
51b3ee3effSStephen Boyd 
52b3ee3effSStephen Boyd const struct clk_ops clk_regmap_mux_closest_ops = {
53b3ee3effSStephen Boyd 	.get_parent = mux_get_parent,
54b3ee3effSStephen Boyd 	.set_parent = mux_set_parent,
55b3ee3effSStephen Boyd 	.determine_rate = __clk_mux_determine_rate_closest,
56b3ee3effSStephen Boyd };
57b3ee3effSStephen Boyd EXPORT_SYMBOL_GPL(clk_regmap_mux_closest_ops);
58