Skip to content

Commit d2692ed

Browse files
claudiubezneageertu
authored andcommitted
clk: renesas: rzg2l: Lock around writes to mux register
The SD MUX output (SD0) is further divided by 4 in G2{L,UL}. The divided clock is SD0_DIV4. SD0_DIV4 is registered with CLK_SET_RATE_PARENT which means a rate request for it is propagated to the MUX and could reach rzg2l_cpg_sd_clk_mux_set_parent() concurrently with the users of SD0. Add proper locking to avoid concurrent accesses on SD MUX set rate registers. Fixes: eaff336 ("clk: renesas: rzg2l: Add SDHI clk mux support") Signed-off-by: Claudiu Beznea <[email protected]> Reviewed-by: Geert Uytterhoeven <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Geert Uytterhoeven <[email protected]>
1 parent 549f4ae commit d2692ed

File tree

2 files changed

+14
-11
lines changed

2 files changed

+14
-11
lines changed

drivers/clk/renesas/rzg2l-cpg.c

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index)
189189
u32 shift = GET_SHIFT(hwdata->conf);
190190
const u32 clk_src_266 = 2;
191191
u32 msk, val, bitmask;
192+
unsigned long flags;
192193
int ret;
193194

194195
/*
@@ -204,23 +205,25 @@ static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index)
204205
*/
205206
bitmask = (GENMASK(GET_WIDTH(hwdata->conf) - 1, 0) << shift) << 16;
206207
msk = off ? CPG_CLKSTATUS_SELSDHI1_STS : CPG_CLKSTATUS_SELSDHI0_STS;
208+
spin_lock_irqsave(&priv->rmw_lock, flags);
207209
if (index != clk_src_266) {
208210
writel(bitmask | ((clk_src_266 + 1) << shift), priv->base + off);
209211

210-
ret = readl_poll_timeout(priv->base + CPG_CLKSTATUS, val,
211-
!(val & msk), 100,
212-
CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US);
213-
if (ret) {
214-
dev_err(priv->dev, "failed to switch clk source\n");
215-
return ret;
216-
}
212+
ret = readl_poll_timeout_atomic(priv->base + CPG_CLKSTATUS, val,
213+
!(val & msk), 10,
214+
CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US);
215+
if (ret)
216+
goto unlock;
217217
}
218218

219219
writel(bitmask | ((index + 1) << shift), priv->base + off);
220220

221-
ret = readl_poll_timeout(priv->base + CPG_CLKSTATUS, val,
222-
!(val & msk), 100,
223-
CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US);
221+
ret = readl_poll_timeout_atomic(priv->base + CPG_CLKSTATUS, val,
222+
!(val & msk), 10,
223+
CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US);
224+
unlock:
225+
spin_unlock_irqrestore(&priv->rmw_lock, flags);
226+
224227
if (ret)
225228
dev_err(priv->dev, "failed to switch clk source\n");
226229

drivers/clk/renesas/rzg2l-cpg.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
#define CPG_CLKSTATUS_SELSDHI0_STS BIT(28)
4444
#define CPG_CLKSTATUS_SELSDHI1_STS BIT(29)
4545

46-
#define CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US 20000
46+
#define CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US 200
4747

4848
/* n = 0/1/2 for PLL1/4/6 */
4949
#define CPG_SAMPLL_CLK1(n) (0x04 + (16 * n))

0 commit comments

Comments
 (0)