summaryrefslogtreecommitdiff
path: root/drivers/clk/zynqmp/divider.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/zynqmp/divider.c')
-rw-r--r--drivers/clk/zynqmp/divider.c40
1 files changed, 36 insertions, 4 deletions
diff --git a/drivers/clk/zynqmp/divider.c b/drivers/clk/zynqmp/divider.c
index e9bf7958b821..cb49281f9cf9 100644
--- a/drivers/clk/zynqmp/divider.c
+++ b/drivers/clk/zynqmp/divider.c
@@ -256,6 +256,11 @@ static const struct clk_ops zynqmp_clk_divider_ops = {
.set_rate = zynqmp_clk_divider_set_rate,
};
+static const struct clk_ops zynqmp_clk_divider_ro_ops = {
+ .recalc_rate = zynqmp_clk_divider_recalc_rate,
+ .round_rate = zynqmp_clk_divider_round_rate,
+};
+
/**
* zynqmp_clk_get_max_divisor() - Get maximum supported divisor from firmware.
* @clk_id: Id of clock
@@ -284,6 +289,29 @@ static u32 zynqmp_clk_get_max_divisor(u32 clk_id, u32 type)
return ret_payload[1];
}
+static inline unsigned long zynqmp_clk_map_divider_ccf_flags(
+ const u32 zynqmp_type_flag)
+{
+ unsigned long ccf_flag = 0;
+
+ if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_ONE_BASED)
+ ccf_flag |= CLK_DIVIDER_ONE_BASED;
+ if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_POWER_OF_TWO)
+ ccf_flag |= CLK_DIVIDER_POWER_OF_TWO;
+ if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_ALLOW_ZERO)
+ ccf_flag |= CLK_DIVIDER_ALLOW_ZERO;
+ if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_POWER_OF_TWO)
+ ccf_flag |= CLK_DIVIDER_HIWORD_MASK;
+ if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_ROUND_CLOSEST)
+ ccf_flag |= CLK_DIVIDER_ROUND_CLOSEST;
+ if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_READ_ONLY)
+ ccf_flag |= CLK_DIVIDER_READ_ONLY;
+ if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_MAX_AT_ZERO)
+ ccf_flag |= CLK_DIVIDER_MAX_AT_ZERO;
+
+ return ccf_flag;
+}
+
/**
* zynqmp_clk_register_divider() - Register a divider clock
* @name: Name of this clock
@@ -311,16 +339,20 @@ struct clk_hw *zynqmp_clk_register_divider(const char *name,
return ERR_PTR(-ENOMEM);
init.name = name;
- init.ops = &zynqmp_clk_divider_ops;
- /* CLK_FRAC is not defined in the common clk framework */
- init.flags = nodes->flag & ~CLK_FRAC;
+ if (nodes->type_flag & CLK_DIVIDER_READ_ONLY)
+ init.ops = &zynqmp_clk_divider_ro_ops;
+ else
+ init.ops = &zynqmp_clk_divider_ops;
+
+ init.flags = zynqmp_clk_map_common_ccf_flags(nodes->flag);
+
init.parent_names = parents;
init.num_parents = 1;
/* struct clk_divider assignments */
div->is_frac = !!((nodes->flag & CLK_FRAC) |
(nodes->custom_type_flag & CUSTOM_FLAG_CLK_FRAC));
- div->flags = nodes->type_flag;
+ div->flags = zynqmp_clk_map_divider_ccf_flags(nodes->type_flag);
div->hw.init = &init;
div->clk_id = clk_id;
div->div_type = nodes->type;