| From f8b0bc01229a247b58b8abf88bfb664fa809482d Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 21 Dec 2020 23:32:25 +0100 |
| Subject: media: aspeed: fix clock handling logic |
| |
| From: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com> |
| |
| [ Upstream commit 3536169f8531c2c5b153921dc7d1ac9fd570cda7 ] |
| |
| Video engine uses eclk and vclk for its clock sources and its reset |
| control is coupled with eclk so the current clock enabling sequence works |
| like below. |
| |
| Enable eclk |
| De-assert Video Engine reset |
| 10ms delay |
| Enable vclk |
| |
| It introduces improper reset on the Video Engine hardware and eventually |
| the hardware generates unexpected DMA memory transfers that can corrupt |
| memory region in random and sporadic patterns. This issue is observed |
| very rarely on some specific AST2500 SoCs but it causes a critical |
| kernel panic with making a various shape of signature so it's extremely |
| hard to debug. Moreover, the issue is observed even when the video |
| engine is not actively used because udevd turns on the video engine |
| hardware for a short time to make a query in every boot. |
| |
| To fix this issue, this commit changes the clock handling logic to make |
| the reset de-assertion triggered after enabling both eclk and vclk. Also, |
| it adds clk_unprepare call for a case when probe fails. |
| |
| clk: ast2600: fix reset settings for eclk and vclk |
| Video engine reset setting should be coupled with eclk to match it |
| with the setting for previous Aspeed SoCs which is defined in |
| clk-aspeed.c since all Aspeed SoCs are sharing a single video engine |
| driver. Also, reset bit 6 is defined as 'Video Engine' reset in |
| datasheet so it should be de-asserted when eclk is enabled. This |
| commit fixes the setting. |
| |
| Fixes: d2b4387f3bdf ("media: platform: Add Aspeed Video Engine driver") |
| Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com> |
| Reviewed-by: Joel Stanley <joel@jms.id.au> |
| Reviewed-by: Eddie James <eajames@linux.ibm.com> |
| Fixes: d3d04f6c330a ("clk: Add support for AST2600 SoC") |
| Reviewed-by: Joel Stanley <joel@jms.id.au> |
| Acked-by: Stephen Boyd <sboyd@kernel.org> |
| Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> |
| Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/clk/clk-ast2600.c | 4 ++-- |
| drivers/media/platform/aspeed-video.c | 9 ++++++--- |
| 2 files changed, 8 insertions(+), 5 deletions(-) |
| |
| diff --git a/drivers/clk/clk-ast2600.c b/drivers/clk/clk-ast2600.c |
| index a55b37fc2c8b..bc3be5f3eae1 100644 |
| --- a/drivers/clk/clk-ast2600.c |
| +++ b/drivers/clk/clk-ast2600.c |
| @@ -61,10 +61,10 @@ static void __iomem *scu_g6_base; |
| static const struct aspeed_gate_data aspeed_g6_gates[] = { |
| /* clk rst name parent flags */ |
| [ASPEED_CLK_GATE_MCLK] = { 0, -1, "mclk-gate", "mpll", CLK_IS_CRITICAL }, /* SDRAM */ |
| - [ASPEED_CLK_GATE_ECLK] = { 1, -1, "eclk-gate", "eclk", 0 }, /* Video Engine */ |
| + [ASPEED_CLK_GATE_ECLK] = { 1, 6, "eclk-gate", "eclk", 0 }, /* Video Engine */ |
| [ASPEED_CLK_GATE_GCLK] = { 2, 7, "gclk-gate", NULL, 0 }, /* 2D engine */ |
| /* vclk parent - dclk/d1clk/hclk/mclk */ |
| - [ASPEED_CLK_GATE_VCLK] = { 3, 6, "vclk-gate", NULL, 0 }, /* Video Capture */ |
| + [ASPEED_CLK_GATE_VCLK] = { 3, -1, "vclk-gate", NULL, 0 }, /* Video Capture */ |
| [ASPEED_CLK_GATE_BCLK] = { 4, 8, "bclk-gate", "bclk", 0 }, /* PCIe/PCI */ |
| /* From dpll */ |
| [ASPEED_CLK_GATE_DCLK] = { 5, -1, "dclk-gate", NULL, CLK_IS_CRITICAL }, /* DAC */ |
| diff --git a/drivers/media/platform/aspeed-video.c b/drivers/media/platform/aspeed-video.c |
| index f2c4dadd6a0e..7bb6babdcade 100644 |
| --- a/drivers/media/platform/aspeed-video.c |
| +++ b/drivers/media/platform/aspeed-video.c |
| @@ -514,8 +514,8 @@ static void aspeed_video_off(struct aspeed_video *video) |
| aspeed_video_write(video, VE_INTERRUPT_STATUS, 0xffffffff); |
| |
| /* Turn off the relevant clocks */ |
| - clk_disable(video->vclk); |
| clk_disable(video->eclk); |
| + clk_disable(video->vclk); |
| |
| clear_bit(VIDEO_CLOCKS_ON, &video->flags); |
| } |
| @@ -526,8 +526,8 @@ static void aspeed_video_on(struct aspeed_video *video) |
| return; |
| |
| /* Turn on the relevant clocks */ |
| - clk_enable(video->eclk); |
| clk_enable(video->vclk); |
| + clk_enable(video->eclk); |
| |
| set_bit(VIDEO_CLOCKS_ON, &video->flags); |
| } |
| @@ -1719,8 +1719,11 @@ static int aspeed_video_probe(struct platform_device *pdev) |
| return rc; |
| |
| rc = aspeed_video_setup_video(video); |
| - if (rc) |
| + if (rc) { |
| + clk_unprepare(video->vclk); |
| + clk_unprepare(video->eclk); |
| return rc; |
| + } |
| |
| return 0; |
| } |
| -- |
| 2.30.2 |
| |