1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // |
3 | // Spreadtrum multiplexer clock driver |
4 | // |
5 | // Copyright (C) 2017 Spreadtrum, Inc. |
6 | // Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> |
7 | |
8 | #include <linux/clk.h> |
9 | #include <linux/clk-provider.h> |
10 | #include <linux/regmap.h> |
11 | |
12 | #include "mux.h" |
13 | |
14 | u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common, |
15 | const struct sprd_mux_ssel *mux) |
16 | { |
17 | unsigned int reg; |
18 | u8 parent; |
19 | int num_parents; |
20 | int i; |
21 | |
22 | regmap_read(map: common->regmap, reg: common->reg, val: ®); |
23 | parent = reg >> mux->shift; |
24 | parent &= (1 << mux->width) - 1; |
25 | |
26 | if (!mux->table) |
27 | return parent; |
28 | |
29 | num_parents = clk_hw_get_num_parents(hw: &common->hw); |
30 | |
31 | for (i = 0; i < num_parents - 1; i++) |
32 | if (parent >= mux->table[i] && parent < mux->table[i + 1]) |
33 | return i; |
34 | |
35 | return num_parents - 1; |
36 | } |
37 | EXPORT_SYMBOL_GPL(sprd_mux_helper_get_parent); |
38 | |
39 | static u8 sprd_mux_get_parent(struct clk_hw *hw) |
40 | { |
41 | struct sprd_mux *cm = hw_to_sprd_mux(hw); |
42 | |
43 | return sprd_mux_helper_get_parent(&cm->common, &cm->mux); |
44 | } |
45 | |
46 | int sprd_mux_helper_set_parent(const struct sprd_clk_common *common, |
47 | const struct sprd_mux_ssel *mux, |
48 | u8 index) |
49 | { |
50 | unsigned int reg; |
51 | |
52 | if (mux->table) |
53 | index = mux->table[index]; |
54 | |
55 | regmap_read(map: common->regmap, reg: common->reg, val: ®); |
56 | reg &= ~GENMASK(mux->width + mux->shift - 1, mux->shift); |
57 | regmap_write(map: common->regmap, reg: common->reg, |
58 | val: reg | (index << mux->shift)); |
59 | |
60 | return 0; |
61 | } |
62 | EXPORT_SYMBOL_GPL(sprd_mux_helper_set_parent); |
63 | |
64 | static int sprd_mux_set_parent(struct clk_hw *hw, u8 index) |
65 | { |
66 | struct sprd_mux *cm = hw_to_sprd_mux(hw); |
67 | |
68 | return sprd_mux_helper_set_parent(&cm->common, &cm->mux, index); |
69 | } |
70 | |
71 | const struct clk_ops sprd_mux_ops = { |
72 | .get_parent = sprd_mux_get_parent, |
73 | .set_parent = sprd_mux_set_parent, |
74 | .determine_rate = __clk_mux_determine_rate, |
75 | }; |
76 | EXPORT_SYMBOL_GPL(sprd_mux_ops); |
77 | |