Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe11826f authored by Jernej Skrabec's avatar Jernej Skrabec Committed by Greg Kroah-Hartman
Browse files

clk: sunxi-ng: h6: Reparent CPUX during PLL CPUX rate change



[ Upstream commit 7e91ed763dc07437777bd012af7a2bd4493731ff ]

While PLL CPUX clock rate change when CPU is running from it works in
vast majority of cases, now and then it causes instability. This leads
to system crashes and other undefined behaviour. After a lot of testing
(30+ hours) while also doing a lot of frequency switches, we can't
observe any instability issues anymore when doing reparenting to stable
clock like 24 MHz oscillator.

Fixes: 524353ea ("clk: sunxi-ng: add support for the Allwinner H6 CCU")
Reported-by: default avatarChad Wagner <wagnerch42@gmail.com>
Link: https://forum.libreelec.tv/thread/27295-orange-pi-3-lts-freezes/


Tested-by: default avatarChad Wagner <wagnerch42@gmail.com>
Reviewed-by: default avatarChen-Yu Tsai <wens@csie.org>
Link: https://lore.kernel.org/r/20231013181712.2128037-1-jernej.skrabec@gmail.com


Signed-off-by: default avatarJernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 2f87fd94
Loading
Loading
Loading
Loading
+17 −2
Original line number Diff line number Diff line
@@ -1172,12 +1172,19 @@ static const u32 usb2_clk_regs[] = {
	SUN50I_H6_USB3_CLK_REG,
};

static struct ccu_mux_nb sun50i_h6_cpu_nb = {
	.common		= &cpux_clk.common,
	.cm		= &cpux_clk.mux,
	.delay_us       = 1,
	.bypass_index   = 0, /* index of 24 MHz oscillator */
};

static int sun50i_h6_ccu_probe(struct platform_device *pdev)
{
	struct resource *res;
	void __iomem *reg;
	int i, ret;
	u32 val;
	int i;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	reg = devm_ioremap_resource(&pdev->dev, res);
@@ -1231,7 +1238,15 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev)
	val |= BIT(24);
	writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG);

	return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_h6_ccu_desc);
	ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_h6_ccu_desc);
	if (ret)
		return ret;

	/* Reparent CPU during PLL CPUX rate changes */
	ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk,
				  &sun50i_h6_cpu_nb);

	return 0;
}

static const struct of_device_id sun50i_h6_ccu_ids[] = {