clk: stm32mp13: add multi mux function
authorGabriel Fernandez <gabriel.fernandez@foss.st.com>
Mon, 16 May 2022 07:05:56 +0000 (09:05 +0200)
committerStephen Boyd <sboyd@kernel.org>
Sat, 21 May 2022 04:07:49 +0000 (21:07 -0700)
Some RCC muxes can manages two output clocks with same register.

Signed-off-by: Gabriel Fernandez <gabriel.fernandez@foss.st.com>
Link: https://lore.kernel.org/r/20220516070600.7692-11-gabriel.fernandez@foss.st.com
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
drivers/clk/stm32/clk-stm32-core.c
drivers/clk/stm32/clk-stm32-core.h
drivers/clk/stm32/clk-stm32mp13.c

index 70014c1..e5a22bb 100644 (file)
@@ -472,6 +472,16 @@ static int clk_stm32_composite_set_parent(struct clk_hw *hw, u8 index)
 
        spin_unlock_irqrestore(composite->lock, flags);
 
+       if (composite->clock_data->is_multi_mux) {
+               struct clk_hw *other_mux_hw = composite->clock_data->is_multi_mux(hw);
+
+               if (other_mux_hw) {
+                       struct clk_hw *hwp = clk_hw_get_parent_by_index(hw, index);
+
+                       clk_hw_reparent(other_mux_hw, hwp);
+               }
+       }
+
        return 0;
 }
 
index 5f4c81c..dab1b65 100644 (file)
@@ -61,6 +61,7 @@ struct clk_stm32_clock_data {
        const struct stm32_gate_cfg     *gates;
        const struct stm32_mux_cfg      *muxes;
        const struct stm32_div_cfg      *dividers;
+       struct clk_hw *(*is_multi_mux)(struct clk_hw *hw);
 };
 
 struct stm32_rcc_match_data {
@@ -72,6 +73,7 @@ struct stm32_rcc_match_data {
        u32                             clear_offset;
        int (*check_security)(void __iomem *base,
                              const struct clock_config *cfg);
+       int (*multi_mux)(void __iomem *base, const struct clock_config *cfg);
 };
 
 int stm32_rcc_reset_init(struct device *dev, const struct of_device_id *match,
index 9edd320..08e3fe0 100644 (file)
@@ -1469,6 +1469,35 @@ static int stm32mp13_clock_is_provided_by_secure(void __iomem *base,
        return 0;
 }
 
+struct multi_mux {
+       struct clk_hw *hw1;
+       struct clk_hw *hw2;
+};
+
+static struct multi_mux *stm32_mp13_multi_mux[MUX_NB] = {
+       [MUX_SPI23]     = &(struct multi_mux){ &spi2_k.hw,      &spi3_k.hw },
+       [MUX_I2C12]     = &(struct multi_mux){ &i2c1_k.hw,      &i2c2_k.hw },
+       [MUX_LPTIM45]   = &(struct multi_mux){ &lptim4_k.hw,    &lptim5_k.hw },
+       [MUX_UART35]    = &(struct multi_mux){ &usart3_k.hw,    &uart5_k.hw },
+       [MUX_UART78]    = &(struct multi_mux){ &uart7_k.hw,     &uart8_k.hw },
+       [MUX_SAI1]      = &(struct multi_mux){ &sai1_k.hw,      &adfsdm_k.hw },
+};
+
+static struct clk_hw *stm32mp13_is_multi_mux(struct clk_hw *hw)
+{
+       struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
+       struct multi_mux *mmux = stm32_mp13_multi_mux[composite->mux_id];
+
+       if (mmux) {
+               if (!(mmux->hw1 == hw))
+                       return mmux->hw1;
+               else
+                       return mmux->hw2;
+       }
+
+       return NULL;
+}
+
 static u16 stm32mp13_cpt_gate[GATE_NB];
 
 static struct clk_stm32_clock_data stm32mp13_clock_data = {
@@ -1476,6 +1505,7 @@ static struct clk_stm32_clock_data stm32mp13_clock_data = {
        .gates          = stm32mp13_gates,
        .muxes          = stm32mp13_muxes,
        .dividers       = stm32mp13_dividers,
+       .is_multi_mux   = stm32mp13_is_multi_mux,
 };
 
 static const struct stm32_rcc_match_data stm32mp13_data = {