clk: renesas: rzg2l: Check reset monitor registers

[ Upstream commit da235d2fac212d0add570e755feb1167a830bc99 ]

The hardware manual of both RZ/G2L and RZ/G3S specifies that the reset
monitor registers need to be interrogated when the reset signals are
toggled (chapters "Procedures for Supplying and Stopping Reset Signals"
and "Procedure for Activating Modules").  Without this, there is a
chance that different modules (e.g. Ethernet) are not ready after their
reset signal is toggled, leading to failures (on probe or resume from
deep sleep states).

The same indications are available for RZ/V2M for TYPE-B reset controls.

Fixes: ef3c613ccd ("clk: renesas: Add CPG core wrapper for RZ/G2L SoC")
Fixes: 8090bea324 ("clk: renesas: rzg2l: Add support for RZ/V2M reset monitor reg")
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/20231207070700.4156557-2-claudiu.beznea.uj@bp.renesas.com
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Claudiu Beznea 2023-12-07 09:06:50 +02:00 committed by Greg Kroah-Hartman
parent 3e1dd6a1b4
commit 9570ae0e1d
1 changed files with 44 additions and 15 deletions

View File

@ -1121,12 +1121,27 @@ static int rzg2l_cpg_assert(struct reset_controller_dev *rcdev,
struct rzg2l_cpg_priv *priv = rcdev_to_priv(rcdev);
const struct rzg2l_cpg_info *info = priv->info;
unsigned int reg = info->resets[id].off;
u32 value = BIT(info->resets[id].bit) << 16;
u32 mask = BIT(info->resets[id].bit);
s8 monbit = info->resets[id].monbit;
u32 value = mask << 16;
dev_dbg(rcdev->dev, "assert id:%ld offset:0x%x\n", id, CLK_RST_R(reg));
writel(value, priv->base + CLK_RST_R(reg));
return 0;
if (info->has_clk_mon_regs) {
reg = CLK_MRST_R(reg);
} else if (monbit >= 0) {
reg = CPG_RST_MON;
mask = BIT(monbit);
} else {
/* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */
udelay(35);
return 0;
}
return readl_poll_timeout_atomic(priv->base + reg, value,
value & mask, 10, 200);
}
static int rzg2l_cpg_deassert(struct reset_controller_dev *rcdev,
@ -1135,14 +1150,28 @@ static int rzg2l_cpg_deassert(struct reset_controller_dev *rcdev,
struct rzg2l_cpg_priv *priv = rcdev_to_priv(rcdev);
const struct rzg2l_cpg_info *info = priv->info;
unsigned int reg = info->resets[id].off;
u32 dis = BIT(info->resets[id].bit);
u32 value = (dis << 16) | dis;
u32 mask = BIT(info->resets[id].bit);
s8 monbit = info->resets[id].monbit;
u32 value = (mask << 16) | mask;
dev_dbg(rcdev->dev, "deassert id:%ld offset:0x%x\n", id,
CLK_RST_R(reg));
writel(value, priv->base + CLK_RST_R(reg));
return 0;
if (info->has_clk_mon_regs) {
reg = CLK_MRST_R(reg);
} else if (monbit >= 0) {
reg = CPG_RST_MON;
mask = BIT(monbit);
} else {
/* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */
udelay(35);
return 0;
}
return readl_poll_timeout_atomic(priv->base + reg, value,
!(value & mask), 10, 200);
}
static int rzg2l_cpg_reset(struct reset_controller_dev *rcdev,
@ -1154,9 +1183,6 @@ static int rzg2l_cpg_reset(struct reset_controller_dev *rcdev,
if (ret)
return ret;
/* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */
udelay(35);
return rzg2l_cpg_deassert(rcdev, id);
}
@ -1165,18 +1191,21 @@ static int rzg2l_cpg_status(struct reset_controller_dev *rcdev,
{
struct rzg2l_cpg_priv *priv = rcdev_to_priv(rcdev);
const struct rzg2l_cpg_info *info = priv->info;
unsigned int reg = info->resets[id].off;
u32 bitmask = BIT(info->resets[id].bit);
s8 monbit = info->resets[id].monbit;
unsigned int reg;
u32 bitmask;
if (info->has_clk_mon_regs) {
return !!(readl(priv->base + CLK_MRST_R(reg)) & bitmask);
reg = CLK_MRST_R(info->resets[id].off);
bitmask = BIT(info->resets[id].bit);
} else if (monbit >= 0) {
u32 monbitmask = BIT(monbit);
return !!(readl(priv->base + CPG_RST_MON) & monbitmask);
reg = CPG_RST_MON;
bitmask = BIT(monbit);
} else {
return -ENOTSUPP;
}
return -ENOTSUPP;
return !!(readl(priv->base + reg) & bitmask);
}
static const struct reset_control_ops rzg2l_cpg_reset_ops = {