1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2018 BayLibre, SAS.
4 * Author: Jerome Brunet <jbrunet@baylibre.com>
7 #include "clk-regmap.h"
9 static int clk_regmap_gate_endisable(struct clk_hw
*hw
, int enable
)
11 struct clk_regmap
*clk
= to_clk_regmap(hw
);
12 struct clk_regmap_gate_data
*gate
= clk_get_regmap_gate_data(clk
);
13 int set
= gate
->flags
& CLK_GATE_SET_TO_DISABLE
? 1 : 0;
17 return regmap_update_bits(clk
->map
, gate
->offset
, BIT(gate
->bit_idx
),
18 set
? BIT(gate
->bit_idx
) : 0);
21 static int clk_regmap_gate_enable(struct clk_hw
*hw
)
23 return clk_regmap_gate_endisable(hw
, 1);
26 static void clk_regmap_gate_disable(struct clk_hw
*hw
)
28 clk_regmap_gate_endisable(hw
, 0);
31 static int clk_regmap_gate_is_enabled(struct clk_hw
*hw
)
33 struct clk_regmap
*clk
= to_clk_regmap(hw
);
34 struct clk_regmap_gate_data
*gate
= clk_get_regmap_gate_data(clk
);
37 regmap_read(clk
->map
, gate
->offset
, &val
);
38 if (gate
->flags
& CLK_GATE_SET_TO_DISABLE
)
39 val
^= BIT(gate
->bit_idx
);
41 val
&= BIT(gate
->bit_idx
);
46 const struct clk_ops clk_regmap_gate_ops
= {
47 .enable
= clk_regmap_gate_enable
,
48 .disable
= clk_regmap_gate_disable
,
49 .is_enabled
= clk_regmap_gate_is_enabled
,
51 EXPORT_SYMBOL_GPL(clk_regmap_gate_ops
);
53 static unsigned long clk_regmap_div_recalc_rate(struct clk_hw
*hw
,
56 struct clk_regmap
*clk
= to_clk_regmap(hw
);
57 struct clk_regmap_div_data
*div
= clk_get_regmap_div_data(clk
);
61 ret
= regmap_read(clk
->map
, div
->offset
, &val
);
63 /* Gives a hint that something is wrong */
67 val
&= clk_div_mask(div
->width
);
68 return divider_recalc_rate(hw
, prate
, val
, div
->table
, div
->flags
,
72 static long clk_regmap_div_round_rate(struct clk_hw
*hw
, unsigned long rate
,
75 struct clk_regmap
*clk
= to_clk_regmap(hw
);
76 struct clk_regmap_div_data
*div
= clk_get_regmap_div_data(clk
);
80 /* if read only, just return current value */
81 if (div
->flags
& CLK_DIVIDER_READ_ONLY
) {
82 ret
= regmap_read(clk
->map
, div
->offset
, &val
);
84 /* Gives a hint that something is wrong */
88 val
&= clk_div_mask(div
->width
);
90 return divider_ro_round_rate(hw
, rate
, prate
, div
->table
,
91 div
->width
, div
->flags
, val
);
94 return divider_round_rate(hw
, rate
, prate
, div
->table
, div
->width
,
98 static int clk_regmap_div_set_rate(struct clk_hw
*hw
, unsigned long rate
,
99 unsigned long parent_rate
)
101 struct clk_regmap
*clk
= to_clk_regmap(hw
);
102 struct clk_regmap_div_data
*div
= clk_get_regmap_div_data(clk
);
106 ret
= divider_get_val(rate
, parent_rate
, div
->table
, div
->width
,
111 val
= (unsigned int)ret
<< div
->shift
;
112 return regmap_update_bits(clk
->map
, div
->offset
,
113 clk_div_mask(div
->width
) << div
->shift
, val
);
116 /* Would prefer clk_regmap_div_ro_ops but clashes with qcom */
118 const struct clk_ops clk_regmap_divider_ops
= {
119 .recalc_rate
= clk_regmap_div_recalc_rate
,
120 .round_rate
= clk_regmap_div_round_rate
,
121 .set_rate
= clk_regmap_div_set_rate
,
123 EXPORT_SYMBOL_GPL(clk_regmap_divider_ops
);
125 const struct clk_ops clk_regmap_divider_ro_ops
= {
126 .recalc_rate
= clk_regmap_div_recalc_rate
,
127 .round_rate
= clk_regmap_div_round_rate
,
129 EXPORT_SYMBOL_GPL(clk_regmap_divider_ro_ops
);
131 static u8
clk_regmap_mux_get_parent(struct clk_hw
*hw
)
133 struct clk_regmap
*clk
= to_clk_regmap(hw
);
134 struct clk_regmap_mux_data
*mux
= clk_get_regmap_mux_data(clk
);
138 ret
= regmap_read(clk
->map
, mux
->offset
, &val
);
144 return clk_mux_val_to_index(hw
, mux
->table
, mux
->flags
, val
);
147 static int clk_regmap_mux_set_parent(struct clk_hw
*hw
, u8 index
)
149 struct clk_regmap
*clk
= to_clk_regmap(hw
);
150 struct clk_regmap_mux_data
*mux
= clk_get_regmap_mux_data(clk
);
151 unsigned int val
= clk_mux_index_to_val(mux
->table
, mux
->flags
, index
);
153 return regmap_update_bits(clk
->map
, mux
->offset
,
154 mux
->mask
<< mux
->shift
,
158 static int clk_regmap_mux_determine_rate(struct clk_hw
*hw
,
159 struct clk_rate_request
*req
)
161 struct clk_regmap
*clk
= to_clk_regmap(hw
);
162 struct clk_regmap_mux_data
*mux
= clk_get_regmap_mux_data(clk
);
164 return clk_mux_determine_rate_flags(hw
, req
, mux
->flags
);
167 const struct clk_ops clk_regmap_mux_ops
= {
168 .get_parent
= clk_regmap_mux_get_parent
,
169 .set_parent
= clk_regmap_mux_set_parent
,
170 .determine_rate
= clk_regmap_mux_determine_rate
,
172 EXPORT_SYMBOL_GPL(clk_regmap_mux_ops
);
174 const struct clk_ops clk_regmap_mux_ro_ops
= {
175 .get_parent
= clk_regmap_mux_get_parent
,
177 EXPORT_SYMBOL_GPL(clk_regmap_mux_ro_ops
);