From: Gabriel Fernandez <gabriel.fernan...@foss.st.com>

'ck_rtc' has multiple clocks as input (ck_hsi, ck_lsi, and ck_hse).
A divider is available only on the specific rtc input for ck_hse.
This Merge will facilitate to have a more coherent clock tree
in no trusted / trusted world.

Signed-off-by: Gabriel Fernandez <gabriel.fernan...@foss.st.com>
---
 drivers/clk/clk-stm32mp1.c | 54 +++++++++++++++++++++++++++++++++-----
 1 file changed, 48 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c
index 35d5aee8f9b0..a7c244fd0b03 100644
--- a/drivers/clk/clk-stm32mp1.c
+++ b/drivers/clk/clk-stm32mp1.c
@@ -245,7 +245,7 @@ static const char * const dsi_src[] = {
 };
 
 static const char * const rtc_src[] = {
-       "off", "ck_lse", "ck_lsi", "ck_hse_rtc"
+       "off", "ck_lse", "ck_lsi", "ck_hse"
 };
 
 static const char * const mco1_src[] = {
@@ -1031,6 +1031,47 @@ static struct clk_hw *clk_register_cktim(struct device 
*dev, const char *name,
        return hw;
 }
 
+/* The divider of RTC clock concerns only ck_hse clock */
+#define HSE_RTC 3
+
+static unsigned long clk_divider_rtc_recalc_rate(struct clk_hw *hw,
+                                                unsigned long parent_rate)
+{
+       if (clk_hw_get_parent(hw) == clk_hw_get_parent_by_index(hw, HSE_RTC))
+               return clk_divider_ops.recalc_rate(hw, parent_rate);
+
+       return parent_rate;
+}
+
+static int clk_divider_rtc_set_rate(struct clk_hw *hw, unsigned long rate,
+                                   unsigned long parent_rate)
+{
+       if (clk_hw_get_parent(hw) == clk_hw_get_parent_by_index(hw, HSE_RTC))
+               return clk_divider_ops.set_rate(hw, rate, parent_rate);
+
+       return parent_rate;
+}
+
+static int clk_divider_rtc_determine_rate(struct clk_hw *hw, struct 
clk_rate_request *req)
+{
+       unsigned long best_parent_rate = req->best_parent_rate;
+
+       if (req->best_parent_hw == clk_hw_get_parent_by_index(hw, HSE_RTC)) {
+               req->rate = clk_divider_ops.round_rate(hw, req->rate, 
&best_parent_rate);
+               req->best_parent_rate = best_parent_rate;
+       } else {
+               req->rate = best_parent_rate;
+       }
+
+       return 0;
+}
+
+static const struct clk_ops rtc_div_clk_ops = {
+       .recalc_rate    = clk_divider_rtc_recalc_rate,
+       .set_rate       = clk_divider_rtc_set_rate,
+       .determine_rate = clk_divider_rtc_determine_rate
+};
+
 struct stm32_pll_cfg {
        u32 offset;
 };
@@ -1243,6 +1284,10 @@ _clk_stm32_register_composite(struct device *dev,
        _STM32_DIV(_div_offset, _div_shift, _div_width,\
                   _div_flags, _div_table, NULL)\
 
+#define _DIV_RTC(_div_offset, _div_shift, _div_width, _div_flags, _div_table)\
+       _STM32_DIV(_div_offset, _div_shift, _div_width,\
+                  _div_flags, _div_table, &rtc_div_clk_ops)
+
 #define _STM32_MUX(_offset, _shift, _width, _mux_flags, _mmux, _ops)\
        .mux = &(struct stm32_mux_cfg) {\
                &(struct mux_cfg) {\
@@ -1965,13 +2010,10 @@ static const struct clock_config stm32mp1_clock_cfg[] = 
{
                  _DIV(RCC_ETHCKSELR, 4, 4, 0, NULL)),
 
        /* RTC clock */
-       DIV(NO_ID, "ck_hse_rtc", "ck_hse", 0, RCC_RTCDIVR, 0, 6, 0),
-
-       COMPOSITE(RTC, "ck_rtc", rtc_src, CLK_OPS_PARENT_ENABLE |
-                  CLK_SET_RATE_PARENT,
+       COMPOSITE(RTC, "ck_rtc", rtc_src, CLK_OPS_PARENT_ENABLE,
                  _GATE(RCC_BDCR, 20, 0),
                  _MUX(RCC_BDCR, 16, 2, 0),
-                 _NO_DIV),
+                 _DIV_RTC(RCC_RTCDIVR, 0, 6, 0, NULL)),
 
        /* MCO clocks */
        COMPOSITE(CK_MCO1, "ck_mco1", mco1_src, CLK_OPS_PARENT_ENABLE |
-- 
2.17.1

Reply via email to