mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-13 15:03:58 +03:00
clk: qcom: Allow polling for clock status in qcom_gate_clk_en()
GATE_CLK() in its current state is unsafe: A simple write to the clock enable register does not guarantee that the clock is immediately running. Without polling the clock status, we may issue writes to registers before the necessary clocks start running. This doesn't seem to cause issues in U-Boot at the moment, but for example removing the CLK_OFF polling in TF-A for the SMMU clocks on DB410c reliably triggers an exception during boot. Make it possible to poll the branch clock status register, by adding a new GATE_CLK_POLLED() macro that takes the extra register address. Existing usages work just as before, without polling the clock status. Ideally all usages should be updated to specify the correct poll address in the future. The Qualcomm naming for these clocks is "branch" and not "gate", but let's keep the existing naming for now to avoid confusion until all others drivers have been converted. Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org> Signed-off-by: Stephan Gerhold <stephan.gerhold@linaro.org> Reviewed-by: Sumit Garg <sumit.garg@oss.qualcomm.com> Reviewed-by: Casey Connolly <casey.connolly@linaro.org> Link: https://lore.kernel.org/r/20250424-apq8016-clock-fixes2-v2-4-fcc371c9e45f@linaro.org Signed-off-by: Casey Connolly <casey.connolly@linaro.org>
This commit is contained in:
committed by
Casey Connolly
parent
94e57ba201
commit
6c049ed993
@@ -83,6 +83,21 @@ int qcom_gate_clk_en(const struct msm_clk_priv *priv, unsigned long id)
|
||||
}
|
||||
|
||||
setbits_le32(priv->base + priv->data->clks[id].reg, priv->data->clks[id].en_val);
|
||||
if (priv->data->clks[id].cbcr_reg) {
|
||||
unsigned int count;
|
||||
u32 val;
|
||||
|
||||
for (count = 0; count < 200; count++) {
|
||||
val = readl(priv->base + priv->data->clks[id].cbcr_reg);
|
||||
val &= BRANCH_CHECK_MASK;
|
||||
if (val == BRANCH_ON_VAL || val == BRANCH_NOC_FSM_ON_VAL)
|
||||
break;
|
||||
udelay(1);
|
||||
}
|
||||
if (WARN(count == 200, "WARNING: Clock @ %#lx [%#010x] stuck at off\n",
|
||||
priv->data->clks[id].cbcr_reg, val))
|
||||
return -EBUSY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,13 +52,20 @@ struct freq_tbl {
|
||||
struct gate_clk {
|
||||
uintptr_t reg;
|
||||
u32 en_val;
|
||||
uintptr_t cbcr_reg;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
/*
|
||||
* GATE_CLK() is deprecated: Use GATE_CLK_POLLED() instead to ensure the clock
|
||||
* is running before we start making use of devices or registers.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
#define GATE_CLK(clk, reg, val) [clk] = { reg, val, #clk }
|
||||
#define GATE_CLK(clk, reg, val) [clk] = { reg, val, 0, #clk }
|
||||
#define GATE_CLK_POLLED(clk, en_reg, val, cbcr_reg) [clk] = { en_reg, val, cbcr_reg, #clk }
|
||||
#else
|
||||
#define GATE_CLK(clk, reg, val) [clk] = { reg, val, NULL }
|
||||
#define GATE_CLK(clk, reg, val) [clk] = { reg, val, 0, NULL }
|
||||
#define GATE_CLK_POLLED(clk, en_reg, val, cbcr_reg) [clk] = { en_reg, val, cbcr_reg, NULL }
|
||||
#endif
|
||||
|
||||
struct qcom_reset_map {
|
||||
|
||||
Reference in New Issue
Block a user