Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: composite: allow fixed rates & fixed dividers

The composite clock assumes that any clock implementing the .recalc_rate
callback will also implement .round_rate and .set_rate. This is not
always true; the basic fixed-rate clock will only implement .recalc_rate
and a fixed-divider clock may choose to implement .recalc_rate and
.round_rate but not .set_rate.

Fix this by conditionally registering .round_rate and .set_rate
callbacks based on the rate_ops passed in to clk_composite_register.

Signed-off-by: Mike Turquette <mturquette@linaro.org>
Cc: Prashant Gaikwad <pgaikwad@nvidia.com>
Tested-by: Emilio López <emilio@elopez.com.ar>
Cc: Gregory CLEMENT <gregory.clement@free-electrons.com>

+13 -4
+13 -4
drivers/clk/clk-composite.c
··· 150 150 } 151 151 152 152 if (rate_hw && rate_ops) { 153 - if (!rate_ops->recalc_rate || !rate_ops->round_rate || 154 - !rate_ops->set_rate) { 153 + if (!rate_ops->recalc_rate) { 155 154 clk = ERR_PTR(-EINVAL); 156 155 goto err; 156 + } 157 + 158 + /* .round_rate is a prerequisite for .set_rate */ 159 + if (rate_ops->round_rate) { 160 + clk_composite_ops->round_rate = clk_composite_round_rate; 161 + if (rate_ops->set_rate) { 162 + clk_composite_ops->set_rate = clk_composite_set_rate; 163 + } 164 + } else { 165 + WARN(rate_ops->set_rate, 166 + "%s: missing round_rate op is required\n", 167 + __func__); 157 168 } 158 169 159 170 composite->rate_hw = rate_hw; 160 171 composite->rate_ops = rate_ops; 161 172 clk_composite_ops->recalc_rate = clk_composite_recalc_rate; 162 - clk_composite_ops->round_rate = clk_composite_round_rate; 163 - clk_composite_ops->set_rate = clk_composite_set_rate; 164 173 } 165 174 166 175 if (gate_hw && gate_ops) {