From 82b635d15f294b1384d632f4c7268078d547155d Mon Sep 17 00:00:00 2001 From: Xilin Wu Date: Thu, 6 Aug 2026 16:39:52 +0800 Subject: [PATCH 1/8] pwm: clk: support constant output levels with a GPIO Clock outputs do not guarantee a defined pin level when the clock is disabled, and some clock providers cannot represent exact 0% or 100% duty cycles. Add optional GPIO and pinctrl support. Use the GPIO to drive constant levels when the PWM is disabled or configured for 0% or 100% duty cycle, and select the clock function for normal PWM output. Link: https://github.com/radxa/kernel/commit/8975042b7c9aa5f5a3635404bb059e52a1aedf94 Signed-off-by: Xilin Wu Signed-off-by: Songjun Li --- drivers/pwm/pwm-clk.c | 85 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 4 deletions(-) diff --git a/drivers/pwm/pwm-clk.c b/drivers/pwm/pwm-clk.c index 9dd88b386907c..8fac5c50d7ae2 100644 --- a/drivers/pwm/pwm-clk.c +++ b/drivers/pwm/pwm-clk.c @@ -11,11 +11,20 @@ * - Due to the fact that exact behavior depends on the underlying * clock driver, various limitations are possible. * - Underlying clock may not be able to give 0% or 100% duty cycle - * (constant off or on), exact behavior will depend on the clock. + * (constant off or on), exact behavior will depend on the clock, + * unless a gpio pinctrl state is supplied. * - When the PWM is disabled, the clock will be disabled as well, - * line state will depend on the clock. + * line state will depend on the clock, unless a gpio pinctrl + * state is supplied. * - The clk API doesn't expose the necessary calls to implement * .get_state(). + * + * Optionally, a GPIO descriptor and pinctrl states ("default" and + * "gpio") can be provided. When a constant output level is needed + * (0% duty, 100% duty, or disabled), the driver switches the pin to + * GPIO mode and drives the appropriate level. For normal PWM output + * the pin is switched back to its clock function mux. If no GPIO is + * provided, the driver falls back to the original clock-only behavior. */ #include @@ -25,12 +34,18 @@ #include #include #include +#include +#include #include struct pwm_clk_chip { struct pwm_chip chip; struct clk *clk; bool clk_enabled; + struct pinctrl *pinctrl; + struct pinctrl_state *pins_default; + struct pinctrl_state *pins_gpio; + struct gpio_desc *gpiod; }; #define to_pwm_clk_chip(_chip) container_of(_chip, struct pwm_clk_chip, chip) @@ -43,14 +58,38 @@ static int pwm_clk_apply(struct pwm_chip *chip, struct pwm_device *pwm, u32 rate; u64 period = state->period; u64 duty_cycle = state->duty_cycle; + bool constant_level = false; + int gpio_value = 0; if (!state->enabled) { - if (pwm->state.enabled) { + constant_level = true; + gpio_value = 0; + } else if (state->duty_cycle == 0) { + constant_level = true; + gpio_value = (state->polarity == PWM_POLARITY_INVERSED) ? 1 : 0; + } else if (state->duty_cycle >= state->period) { + constant_level = true; + gpio_value = (state->polarity == PWM_POLARITY_INVERSED) ? 0 : 1; + } + + if (constant_level) { + if (pcchip->gpiod) + gpiod_direction_output(pcchip->gpiod, gpio_value); + if (pcchip->clk_enabled) { clk_disable(pcchip->clk); pcchip->clk_enabled = false; } + if (pcchip->gpiod) { + pinctrl_select_state(pcchip->pinctrl, pcchip->pins_gpio); + gpiod_direction_output(pcchip->gpiod, gpio_value); + } return 0; - } else if (!pwm->state.enabled) { + } + + if (pcchip->gpiod) + pinctrl_select_state(pcchip->pinctrl, pcchip->pins_default); + + if (!pcchip->clk_enabled) { ret = clk_enable(pcchip->clk); if (ret) return ret; @@ -93,6 +132,44 @@ static int pwm_clk_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, PTR_ERR(pcchip->clk), "Failed to get clock\n"); + pcchip->pinctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(pcchip->pinctrl)) { + ret = PTR_ERR(pcchip->pinctrl); + pcchip->pinctrl = NULL; + if (ret == -EPROBE_DEFER) + return ret; + } else { + pcchip->pins_default = pinctrl_lookup_state(pcchip->pinctrl, + PINCTRL_STATE_DEFAULT); + pcchip->pins_gpio = pinctrl_lookup_state(pcchip->pinctrl, "gpio"); + if (IS_ERR(pcchip->pins_default) || IS_ERR(pcchip->pins_gpio)) + pcchip->pinctrl = NULL; + } + + /* + * Switch to GPIO pinctrl state before requesting the GPIO. The driver + * core has already applied the default state, which muxes the pin to the + * clock function and claims it. Release that claim first so gpiolib can + * request the pin. + */ + if (pcchip->pinctrl) + pinctrl_select_state(pcchip->pinctrl, pcchip->pins_gpio); + + pcchip->gpiod = devm_gpiod_get_optional(&pdev->dev, NULL, GPIOD_ASIS); + if (IS_ERR(pcchip->gpiod)) + return dev_err_probe(&pdev->dev, PTR_ERR(pcchip->gpiod), + "Failed to get gpio\n"); + + /* + * If pinctrl states were found but no GPIO was provided, the pin is stuck + * in GPIO mode from the switch above. Restore the default mux and fall + * back to clock-only operation. + */ + if (pcchip->pinctrl && !pcchip->gpiod) { + pinctrl_select_state(pcchip->pinctrl, pcchip->pins_default); + pcchip->pinctrl = NULL; + } + pcchip->chip.dev = &pdev->dev; pcchip->chip.ops = &pwm_clk_ops; pcchip->chip.npwm = 1; From ff93daa607a82e96cdc460e34f74a4c91ab11c1d Mon Sep 17 00:00:00 2001 From: Songjun Li Date: Thu, 6 Aug 2026 16:50:31 +0800 Subject: [PATCH 2/8] clk: qcom: gcc-sa8775p: support PWM on GP clocks The SA8775P GP clock frequency table only provides 100 MHz and 200 MHz rates, which cannot satisfy low-frequency PWM consumers. Add 1, 5, 10, 20 and 100 kHz configurations derived from the 19.2 MHz TCXO. Use clk_rcg2_ops for the GP clock sources so clk-pwm can configure the output duty cycle. The 10 kHz and 20 kHz rates are used by the VMARC-Q9075 fan and display backlight respectively. Signed-off-by: Songjun Li --- drivers/clk/qcom/gcc-sa8775p.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/clk/qcom/gcc-sa8775p.c b/drivers/clk/qcom/gcc-sa8775p.c index 11c72a10ba698..199bfdfacb2b3 100644 --- a/drivers/clk/qcom/gcc-sa8775p.c +++ b/drivers/clk/qcom/gcc-sa8775p.c @@ -721,6 +721,11 @@ static struct clk_rcg2 gcc_emac1_rgmii_clk_src = { }; static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = { + F(1000, P_BI_TCXO, 16, 1, 1200), + F(5000, P_BI_TCXO, 16, 1, 240), + F(10000, P_BI_TCXO, 16, 1, 120), + F(20000, P_BI_TCXO, 16, 1, 60), + F(100000, P_BI_TCXO, 16, 1, 12), F(100000000, P_GCC_GPLL0_OUT_MAIN, 6, 0, 0), F(200000000, P_GCC_GPLL0_OUT_MAIN, 3, 0, 0), { } @@ -736,7 +741,7 @@ static struct clk_rcg2 gcc_gp1_clk_src = { .name = "gcc_gp1_clk_src", .parent_data = gcc_parent_data_2, .num_parents = ARRAY_SIZE(gcc_parent_data_2), - .ops = &clk_rcg2_shared_ops, + .ops = &clk_rcg2_ops, }, }; @@ -750,7 +755,7 @@ static struct clk_rcg2 gcc_gp2_clk_src = { .name = "gcc_gp2_clk_src", .parent_data = gcc_parent_data_2, .num_parents = ARRAY_SIZE(gcc_parent_data_2), - .ops = &clk_rcg2_shared_ops, + .ops = &clk_rcg2_ops, }, }; @@ -764,7 +769,7 @@ static struct clk_rcg2 gcc_gp3_clk_src = { .name = "gcc_gp3_clk_src", .parent_data = gcc_parent_data_2, .num_parents = ARRAY_SIZE(gcc_parent_data_2), - .ops = &clk_rcg2_shared_ops, + .ops = &clk_rcg2_ops, }, }; @@ -778,7 +783,7 @@ static struct clk_rcg2 gcc_gp4_clk_src = { .name = "gcc_gp4_clk_src", .parent_data = gcc_parent_data_2, .num_parents = ARRAY_SIZE(gcc_parent_data_2), - .ops = &clk_rcg2_shared_ops, + .ops = &clk_rcg2_ops, }, }; @@ -792,7 +797,7 @@ static struct clk_rcg2 gcc_gp5_clk_src = { .name = "gcc_gp5_clk_src", .parent_data = gcc_parent_data_2, .num_parents = ARRAY_SIZE(gcc_parent_data_2), - .ops = &clk_rcg2_shared_ops, + .ops = &clk_rcg2_ops, }, }; From 2aa878d587ec1436e5fdae0677ced244290a0e54 Mon Sep 17 00:00:00 2001 From: Songjun Li Date: Thu, 6 Aug 2026 16:51:11 +0800 Subject: [PATCH 3/8] arm64: defconfig: Enable CONFIG_PWM_CLK Signed-off-by: Songjun Li --- arch/arm64/configs/qcom_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom_defconfig b/arch/arm64/configs/qcom_defconfig index bad36f3818f3e..a1539178e5a14 100644 --- a/arch/arm64/configs/qcom_defconfig +++ b/arch/arm64/configs/qcom_defconfig @@ -760,6 +760,7 @@ CONFIG_IIO=y CONFIG_QCOM_SPMI_VADC=m CONFIG_QCOM_SPMI_ADC5=y CONFIG_PWM=y +CONFIG_PWM_CLK=y CONFIG_PWM_GPIO=m CONFIG_PWM_PCA9632=m CONFIG_PWM_PCA9685=m From b7070e32ce196b616997797ebdaba7caccf7245f Mon Sep 17 00:00:00 2001 From: Songjun Li Date: Thu, 6 Aug 2026 17:22:10 +0800 Subject: [PATCH 4/8] net: stmmac: qcom-ethqos: reset adapter on 2.5G speed changes Switching between 1Gbps and 2.5Gbps can leave the QCOM ETHQOS MAC and PCS in a state where the PHY ID cannot be read and the link cannot be restored. Track the previously configured link speed and request an adapter reset when the speed changes to or from 2.5Gbps. Skip the reset for the initial link setup. Expose stmmac_request_reset() so the platform driver can schedule the existing stmmac service-task reset instead of resetting the device directly from the MAC link-up callback. This restores link operation across 1Gbps and 2.5Gbps transitions. Signed-off-by: Songjun Li --- .../stmicro/stmmac/dwmac-qcom-ethqos.c | 23 ++++++++++++++++++- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 6 +++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index d95f39e5b3219..ea1999d0290b3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -147,6 +147,7 @@ struct qcom_ethqos { struct phy *serdes_phy; unsigned int speed; int serdes_speed; + bool link_speed_valid; phy_interface_t phy_mode; struct reset_control *serdes_reset; @@ -948,15 +949,27 @@ static void ethqos_xpcs_validate_link_post_reset(struct qcom_ethqos *ethqos) } } +static bool ethqos_needs_speed_change_reset(unsigned int old_speed, + unsigned int new_speed) +{ + return old_speed != new_speed && + (old_speed == SPEED_2500 || new_speed == SPEED_2500); +} + static void ethqos_fix_mac_speed(void *priv_n, unsigned int speed, unsigned int mode) { struct qcom_ethqos *ethqos = priv_n; struct net_device *dev = platform_get_drvdata(ethqos->pdev); struct stmmac_priv *priv = netdev_priv(dev); + unsigned int old_speed = ethqos->speed; + bool reset_needed; + + reset_needed = ethqos->link_speed_valid && + ethqos_needs_speed_change_reset(old_speed, speed); qcom_ethqos_set_sgmii_loopback(ethqos, false); - ethqos->speed = speed; ethqos_update_link_clk(ethqos, speed); + ethqos->speed = speed; ethqos_configure(ethqos); if (priv->hw->phylink_pcs) { @@ -965,6 +978,14 @@ static void ethqos_fix_mac_speed(void *priv_n, unsigned int speed, unsigned int DUPLEX_FULL); ethqos_xpcs_validate_link_post_reset(ethqos); } + + ethqos->link_speed_valid = true; + + if (reset_needed) { + netdev_info(dev, "reset adapter after %uMbps to %uMbps link speed change\n", + old_speed, speed); + stmmac_request_reset(priv); + } } static int qcom_ethqos_serdes_powerup(struct net_device *ndev, void *priv) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 7020d369801b7..2b8eec75e1688 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -387,6 +387,7 @@ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt); int stmmac_reinit_ringparam(struct net_device *dev, u32 rx_size, u32 tx_size); int stmmac_bus_clks_config(struct stmmac_priv *priv, bool enabled); void stmmac_fpe_handshake(struct stmmac_priv *priv, bool enable); +void stmmac_request_reset(struct stmmac_priv *priv); static inline bool stmmac_xdp_is_enabled(struct stmmac_priv *priv) { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 40fdb1a11ff08..bd7f3ad3c3825 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -287,6 +287,12 @@ static void stmmac_global_err(struct stmmac_priv *priv) stmmac_service_event_schedule(priv); } +void stmmac_request_reset(struct stmmac_priv *priv) +{ + stmmac_global_err(priv); +} +EXPORT_SYMBOL_GPL(stmmac_request_reset); + /** * stmmac_clk_csr_set - dynamically set the MDC clock * @priv: driver private structure From d6f2a0b52d047f3ff8c080db7d6bbec5094ff269 Mon Sep 17 00:00:00 2001 From: Songjun Li Date: Thu, 6 Aug 2026 17:34:32 +0800 Subject: [PATCH 5/8] serial: qcom-geni: honor RS-485 RTS idle polarity The RS-485 configuration callback forces RTS to a fixed level when RS-485 mode is enabled. This ignores SER_RS485_RTS_AFTER_SEND and can leave the transceiver in transmit mode while the bus is idle. Initialize RTS according to SER_RS485_RTS_AFTER_SEND when RS-485 mode is enabled. Reapply the configured idle level during startup so the state is restored after port setup or power cycles. Signed-off-by: Songjun Li --- drivers/tty/serial/qcom_geni_serial.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 765a3701d95a0..a533457e02196 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -1243,6 +1243,11 @@ static int qcom_geni_serial_startup(struct uart_port *uport) if (ret) return ret; } + + if (uport->rs485.flags & SER_RS485_ENABLED) + qcom_geni_set_rts_pin(uport, + !!(uport->rs485.flags & SER_RS485_RTS_AFTER_SEND)); + enable_irq(uport->irq); return 0; @@ -1601,12 +1606,12 @@ static void qcom_geni_serial_pm(struct uart_port *uport, static int qcom_geni_rs485_config(struct uart_port *uport, struct ktermios *termios, struct serial_rs485 *rs485) { - /* When RS485 is enabled, keep the RTS pin in ACTIVE state - * and revert back to auto flow control mode, i.e. flow control - * managed by the QUP HW once RS485 is disabled. + /* Initialize RTS to its idle state when RS485 is enabled and revert + * to QUP-managed automatic flow control once RS485 is disabled. */ if (rs485->flags & SER_RS485_ENABLED) - qcom_geni_set_rts_pin(uport, true); + qcom_geni_set_rts_pin(uport, + !!(rs485->flags & SER_RS485_RTS_AFTER_SEND)); else writel(0, uport->membase + SE_UART_MANUAL_RFR); From 90f3c3696cddb0e44f1d20250a0a1638fa1885b5 Mon Sep 17 00:00:00 2001 From: Songjun Li Date: Mon, 10 Aug 2026 17:55:06 +0800 Subject: [PATCH 6/8] clk: qcom: gcc-sa8775p: add 25 and 40 kHz GP clock rates Signed-off-by: Songjun Li --- drivers/clk/qcom/gcc-sa8775p.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/qcom/gcc-sa8775p.c b/drivers/clk/qcom/gcc-sa8775p.c index 199bfdfacb2b3..95b2a1334d19b 100644 --- a/drivers/clk/qcom/gcc-sa8775p.c +++ b/drivers/clk/qcom/gcc-sa8775p.c @@ -725,6 +725,8 @@ static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = { F(5000, P_BI_TCXO, 16, 1, 240), F(10000, P_BI_TCXO, 16, 1, 120), F(20000, P_BI_TCXO, 16, 1, 60), + F(25000, P_BI_TCXO, 16, 1, 48), + F(40000, P_BI_TCXO, 16, 1, 30), F(100000, P_BI_TCXO, 16, 1, 12), F(100000000, P_GCC_GPLL0_OUT_MAIN, 6, 0, 0), F(200000000, P_GCC_GPLL0_OUT_MAIN, 3, 0, 0), From d1629593e3f02f3101326640f71156c27eb58e60 Mon Sep 17 00:00:00 2001 From: Xilin Wu Date: Mon, 17 Aug 2026 18:24:49 +0800 Subject: [PATCH 7/8] clk: qcom: clk-branch: calculate timeout based on clock frequency Low-rate clock branches can exceed the fixed 200 us toggle timeout. Calculate the timeout from three cycles at the current clock rate. Link: https://git.codelinaro.org/clo/la/kernel/qcom/-/commit/aa899c2d1fa31e247f04810f125ac9c60927c901 Link: https://github.com/radxa/kernel/commit/ec8c29802c870212e2bd89bfb5f8cac93af25687 Signed-off-by: Mike Tipton Signed-off-by: Xilin Wu Signed-off-by: Songjun Li --- drivers/clk/qcom/clk-branch.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/clk-branch.c b/drivers/clk/qcom/clk-branch.c index e213a0284c21c..5632f45131d98 100644 --- a/drivers/clk/qcom/clk-branch.c +++ b/drivers/clk/qcom/clk-branch.c @@ -60,9 +60,27 @@ static bool clk_branch2_check_halt(const struct clk_branch *br, bool enabling) return (val & CBCR_CLK_OFF) == (invert ? 0 : CBCR_CLK_OFF); } +static int get_branch_timeout(const struct clk_branch *br) +{ + unsigned long rate; + int timeout; + + /* + * The time it takes a clock branch to toggle is roughly 3 clock cycles. + */ + rate = clk_hw_get_rate(&br->clkr.hw); + if (!rate) + return 200; + + timeout = 3 * (USEC_PER_SEC / rate); + + return max(timeout, 200); +} + static int clk_branch_wait(const struct clk_branch *br, bool enabling, bool (check_halt)(const struct clk_branch *, bool)) { + int timeout, count; bool voted = br->halt_check & BRANCH_VOTED; const char *name = clk_hw_get_name(&br->clkr.hw); @@ -78,9 +96,9 @@ static int clk_branch_wait(const struct clk_branch *br, bool enabling, } else if (br->halt_check == BRANCH_HALT_ENABLE || br->halt_check == BRANCH_HALT || (enabling && voted)) { - int count = 200; + timeout = get_branch_timeout(br); - while (count-- > 0) { + for (count = timeout; count > 0; count--) { if (check_halt(br, enabling)) return 0; udelay(1); From 0ed74d63c7dd3ae353f72abb876b7730991f87c2 Mon Sep 17 00:00:00 2001 From: Xilin Wu Date: Mon, 17 Aug 2026 18:25:07 +0800 Subject: [PATCH 8/8] clk: qcom: clk-rcg2: calculate timeout based on clock frequency Low-rate RCG updates can exceed the fixed 500 us timeout. Calculate the timeout from three cycles at both the old and new clock rates. Backport only the frequency-table path; dynamic GP rates are absent in 6.8. Link: https://git.codelinaro.org/clo/la/kernel/qcom/-/commit/aa899c2d1fa31e247f04810f125ac9c60927c901 Link: https://github.com/radxa/kernel/commit/7b87e74a503845d806910bc685b4186c76c6e66a Signed-off-by: Mike Tipton Signed-off-by: Xilin Wu Signed-off-by: Songjun Li --- drivers/clk/qcom/clk-rcg.h | 2 ++ drivers/clk/qcom/clk-rcg2.c | 23 +++++++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h index 7d0f925960559..dc64e57b1da62 100644 --- a/drivers/clk/qcom/clk-rcg.h +++ b/drivers/clk/qcom/clk-rcg.h @@ -141,6 +141,7 @@ extern const struct clk_ops clk_dyn_rcg_ops; * @clkr: regmap clock handle * @cfg_off: defines the cfg register offset from the CMD_RCGR + CFG_REG * @parked_cfg: cached value of the CFG register for parked RCGs + * @configured_freq: last configured frequency, used for timeout calculation * @hw_clk_ctrl: whether to enable hardware clock control */ struct clk_rcg2 { @@ -153,6 +154,7 @@ struct clk_rcg2 { struct clk_regmap clkr; u8 cfg_off; u32 parked_cfg; + unsigned long configured_freq; bool hw_clk_ctrl; }; diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index fae1c07982aba..1dd6bfb7aa0eb 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -108,9 +108,24 @@ static u8 clk_rcg2_get_parent(struct clk_hw *hw) return __clk_rcg2_get_parent(hw, cfg); } +static int get_update_timeout(const struct clk_rcg2 *rcg) +{ + int timeout = 0; + unsigned long current_freq; + + /* Allow roughly three cycles at both the old and new clock rates. */ + current_freq = clk_hw_get_rate(&rcg->clkr.hw); + if (current_freq) + timeout += 3 * (USEC_PER_SEC / current_freq); + if (rcg->configured_freq) + timeout += 3 * (USEC_PER_SEC / rcg->configured_freq); + + return max(timeout, 500); +} + static int update_config(struct clk_rcg2 *rcg) { - int count, ret; + int timeout, count, ret; u32 cmd; struct clk_hw *hw = &rcg->clkr.hw; const char *name = clk_hw_get_name(hw); @@ -120,8 +135,10 @@ static int update_config(struct clk_rcg2 *rcg) if (ret) return ret; + timeout = get_update_timeout(rcg); + /* Wait for update to take effect */ - for (count = 500; count > 0; count--) { + for (count = timeout; count > 0; count--) { ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG, &cmd); if (ret) return ret; @@ -345,6 +362,8 @@ static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f) if (ret) return ret; + rcg->configured_freq = f->freq; + return update_config(rcg); }