[v5,08/11] clk: sunxi-ng: mux: Support finding closest rate
Commit Message
When finding the best rate for a mux clock, consider rates that are
higher than the requested rate when CCU_FEATURE_ROUND_CLOSEST is used.
Furthermore, introduce an initialization macro that sets this flag.
Acked-by: Maxime Ripard <mripard@kernel.org>
Signed-off-by: Frank Oltmanns <frank@oltmanns.dev>
---
drivers/clk/sunxi-ng/ccu_mux.c | 13 ++++++++++++-
drivers/clk/sunxi-ng/ccu_mux.h | 38 +++++++++++++++++++++++++++-----------
2 files changed, 39 insertions(+), 12 deletions(-)
Comments
Dne nedelja, 06. avgust 2023 ob 15:06:53 CEST je Frank Oltmanns napisal(a):
> When finding the best rate for a mux clock, consider rates that are
> higher than the requested rate when CCU_FEATURE_ROUND_CLOSEST is used.
> Furthermore, introduce an initialization macro that sets this flag.
>
> Acked-by: Maxime Ripard <mripard@kernel.org>
> Signed-off-by: Frank Oltmanns <frank@oltmanns.dev>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Best regards,
Jernej
> ---
> drivers/clk/sunxi-ng/ccu_mux.c | 13 ++++++++++++-
> drivers/clk/sunxi-ng/ccu_mux.h | 38 +++++++++++++++++++++++++++-----------
> 2 files changed, 39 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
> index 3ca695439620..5edc63b46651 100644
> --- a/drivers/clk/sunxi-ng/ccu_mux.c
> +++ b/drivers/clk/sunxi-ng/ccu_mux.c
> @@ -242,6 +242,17 @@ static int ccu_mux_set_parent(struct clk_hw *hw, u8
> index) return ccu_mux_helper_set_parent(&cm->common, &cm->mux, index);
> }
>
> +static int ccu_mux_determine_rate(struct clk_hw *hw,
> + struct clk_rate_request *req)
> +{
> + struct ccu_mux *cm = hw_to_ccu_mux(hw);
> +
> + if (cm->common.features & CCU_FEATURE_CLOSEST_RATE)
> + return clk_mux_determine_rate_flags(hw, req,
CLK_MUX_ROUND_CLOSEST);
> +
> + return clk_mux_determine_rate_flags(hw, req, 0);
> +}
> +
> static unsigned long ccu_mux_recalc_rate(struct clk_hw *hw,
> unsigned long
parent_rate)
> {
> @@ -259,7 +270,7 @@ const struct clk_ops ccu_mux_ops = {
> .get_parent = ccu_mux_get_parent,
> .set_parent = ccu_mux_set_parent,
>
> - .determine_rate = __clk_mux_determine_rate,
> + .determine_rate = ccu_mux_determine_rate,
> .recalc_rate = ccu_mux_recalc_rate,
> };
> EXPORT_SYMBOL_NS_GPL(ccu_mux_ops, SUNXI_CCU);
> diff --git a/drivers/clk/sunxi-ng/ccu_mux.h b/drivers/clk/sunxi-ng/ccu_mux.h
> index 2c1811a445b0..eb1172ebbd94 100644
> --- a/drivers/clk/sunxi-ng/ccu_mux.h
> +++ b/drivers/clk/sunxi-ng/ccu_mux.h
> @@ -46,20 +46,36 @@ struct ccu_mux {
> struct ccu_common common;
> };
>
> +#define SUNXI_CCU_MUX_TABLE_WITH_GATE_FEAT(_struct, _name, _parents,
> _table, \ + _reg, _shift,
_width, _gate, \
> + _flags, _features)
\
> + struct ccu_mux _struct = {
\
> + .enable = _gate,
\
> + .mux = _SUNXI_CCU_MUX_TABLE(_shift, _width,
_table), \
> + .common = {
\
> + .reg = _reg,
\
> + .hw.init = CLK_HW_INIT_PARENTS(_name,
\
> +
_parents, \
> +
&ccu_mux_ops, \
> +
_flags), \
> + .features = _features,
\
> + }
\
> + }
> +
> +#define SUNXI_CCU_MUX_TABLE_WITH_GATE_CLOSEST(_struct, _name, _parents,
\
> + _table, _reg,
_shift, \
> + _width, _gate,
_flags) \
> + SUNXI_CCU_MUX_TABLE_WITH_GATE_FEAT(_struct, _name, _parents,
\
> + _table, _reg,
_shift, \
> + _width, _gate,
_flags, \
> +
CCU_FEATURE_CLOSEST_RATE)
> +
> #define SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, _table,
\
> _reg, _shift, _width, _gate,
\
> _flags)
\
> - struct ccu_mux _struct = {
\
> - .enable = _gate,
\
> - .mux = _SUNXI_CCU_MUX_TABLE(_shift, _width,
_table), \
> - .common = {
\
> - .reg = _reg,
\
> - .hw.init = CLK_HW_INIT_PARENTS(_name,
\
> -
_parents, \
> -
&ccu_mux_ops, \
> -
_flags), \
> - }
\
> - }
> + SUNXI_CCU_MUX_TABLE_WITH_GATE_FEAT(_struct, _name, _parents,
\
> + _table, _reg,
_shift, \
> + _width, _gate,
_flags, 0)
>
> #define SUNXI_CCU_MUX_WITH_GATE(_struct, _name, _parents, _reg,
\
> _shift, _width, _gate, _flags)
\
@@ -242,6 +242,17 @@ static int ccu_mux_set_parent(struct clk_hw *hw, u8 index)
return ccu_mux_helper_set_parent(&cm->common, &cm->mux, index);
}
+static int ccu_mux_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct ccu_mux *cm = hw_to_ccu_mux(hw);
+
+ if (cm->common.features & CCU_FEATURE_CLOSEST_RATE)
+ return clk_mux_determine_rate_flags(hw, req, CLK_MUX_ROUND_CLOSEST);
+
+ return clk_mux_determine_rate_flags(hw, req, 0);
+}
+
static unsigned long ccu_mux_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
@@ -259,7 +270,7 @@ const struct clk_ops ccu_mux_ops = {
.get_parent = ccu_mux_get_parent,
.set_parent = ccu_mux_set_parent,
- .determine_rate = __clk_mux_determine_rate,
+ .determine_rate = ccu_mux_determine_rate,
.recalc_rate = ccu_mux_recalc_rate,
};
EXPORT_SYMBOL_NS_GPL(ccu_mux_ops, SUNXI_CCU);
@@ -46,20 +46,36 @@ struct ccu_mux {
struct ccu_common common;
};
+#define SUNXI_CCU_MUX_TABLE_WITH_GATE_FEAT(_struct, _name, _parents, _table, \
+ _reg, _shift, _width, _gate, \
+ _flags, _features) \
+ struct ccu_mux _struct = { \
+ .enable = _gate, \
+ .mux = _SUNXI_CCU_MUX_TABLE(_shift, _width, _table), \
+ .common = { \
+ .reg = _reg, \
+ .hw.init = CLK_HW_INIT_PARENTS(_name, \
+ _parents, \
+ &ccu_mux_ops, \
+ _flags), \
+ .features = _features, \
+ } \
+ }
+
+#define SUNXI_CCU_MUX_TABLE_WITH_GATE_CLOSEST(_struct, _name, _parents, \
+ _table, _reg, _shift, \
+ _width, _gate, _flags) \
+ SUNXI_CCU_MUX_TABLE_WITH_GATE_FEAT(_struct, _name, _parents, \
+ _table, _reg, _shift, \
+ _width, _gate, _flags, \
+ CCU_FEATURE_CLOSEST_RATE)
+
#define SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, _table, \
_reg, _shift, _width, _gate, \
_flags) \
- struct ccu_mux _struct = { \
- .enable = _gate, \
- .mux = _SUNXI_CCU_MUX_TABLE(_shift, _width, _table), \
- .common = { \
- .reg = _reg, \
- .hw.init = CLK_HW_INIT_PARENTS(_name, \
- _parents, \
- &ccu_mux_ops, \
- _flags), \
- } \
- }
+ SUNXI_CCU_MUX_TABLE_WITH_GATE_FEAT(_struct, _name, _parents, \
+ _table, _reg, _shift, \
+ _width, _gate, _flags, 0)
#define SUNXI_CCU_MUX_WITH_GATE(_struct, _name, _parents, _reg, \
_shift, _width, _gate, _flags) \