stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] video: mxsfb: Make sure axi clock is enabled when accessing registers
@ 2015-03-04  5:58 Liu Ying
  2015-03-04  6:08 ` Greg KH
  2015-03-04  6:36 ` Peter Chen
  0 siblings, 2 replies; 4+ messages in thread
From: Liu Ying @ 2015-03-04  5:58 UTC (permalink / raw)
  To: linux-fbdev
  Cc: Peter Chen, Jean-Christophe Plagniol-Villard, Tomi Valkeinen,
	Fabio Estevam, linux-kernel, stable

The LCDIF engines embedded in i.MX6sl and i.MX6sx SoCs need the axi clock
as the engine's system clock.  The clock should be enabled when accessing
LCDIF registers, otherwise the kernel would hang up.  We should also keep
the clock being enabled when the engine is being active to scan out frames
from memory.  This patch makes sure the axi clock is enabled when accessing
registers so that the kernel hang up issue can be fixed.

Reported-by: Peter Chen <peter.chen@freescale.com>
Signed-off-by: Liu Ying <Ying.Liu@freescale.com>
---
 drivers/video/fbdev/mxsfb.c | 70 ++++++++++++++++++++++++++++++++++++---------
 1 file changed, 56 insertions(+), 14 deletions(-)

diff --git a/drivers/video/fbdev/mxsfb.c b/drivers/video/fbdev/mxsfb.c
index f8ac4a4..a8cf3b2 100644
--- a/drivers/video/fbdev/mxsfb.c
+++ b/drivers/video/fbdev/mxsfb.c
@@ -316,6 +316,18 @@ static int mxsfb_check_var(struct fb_var_screeninfo *var,
 	return 0;
 }
 
+static inline void mxsfb_enable_axi_clk(struct mxsfb_info *host)
+{
+	if (host->clk_axi)
+		clk_prepare_enable(host->clk_axi);
+}
+
+static inline void mxsfb_disable_axi_clk(struct mxsfb_info *host)
+{
+	if (host->clk_axi)
+		clk_disable_unprepare(host->clk_axi);
+}
+
 static void mxsfb_enable_controller(struct fb_info *fb_info)
 {
 	struct mxsfb_info *host = to_imxfb_host(fb_info);
@@ -333,14 +345,13 @@ static void mxsfb_enable_controller(struct fb_info *fb_info)
 		}
 	}
 
-	if (host->clk_axi)
-		clk_prepare_enable(host->clk_axi);
-
 	if (host->clk_disp_axi)
 		clk_prepare_enable(host->clk_disp_axi);
 	clk_prepare_enable(host->clk);
 	clk_set_rate(host->clk, PICOS2KHZ(fb_info->var.pixclock) * 1000U);
 
+	mxsfb_enable_axi_clk(host);
+
 	/* if it was disabled, re-enable the mode again */
 	writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET);
 
@@ -380,11 +391,11 @@ static void mxsfb_disable_controller(struct fb_info *fb_info)
 	reg = readl(host->base + LCDC_VDCTRL4);
 	writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4);
 
+	mxsfb_disable_axi_clk(host);
+
 	clk_disable_unprepare(host->clk);
 	if (host->clk_disp_axi)
 		clk_disable_unprepare(host->clk_disp_axi);
-	if (host->clk_axi)
-		clk_disable_unprepare(host->clk_axi);
 
 	host->enabled = 0;
 
@@ -421,6 +432,8 @@ static int mxsfb_set_par(struct fb_info *fb_info)
 		mxsfb_disable_controller(fb_info);
 	}
 
+	mxsfb_enable_axi_clk(host);
+
 	/* clear the FIFOs */
 	writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET);
 
@@ -438,6 +451,7 @@ static int mxsfb_set_par(struct fb_info *fb_info)
 		ctrl |= CTRL_SET_WORD_LENGTH(3);
 		switch (host->ld_intf_width) {
 		case STMLCDIF_8BIT:
+			mxsfb_disable_axi_clk(host);
 			dev_err(&host->pdev->dev,
 					"Unsupported LCD bus width mapping\n");
 			return -EINVAL;
@@ -451,6 +465,7 @@ static int mxsfb_set_par(struct fb_info *fb_info)
 		writel(CTRL1_SET_BYTE_PACKAGING(0x7), host->base + LCDC_CTRL1);
 		break;
 	default:
+		mxsfb_disable_axi_clk(host);
 		dev_err(&host->pdev->dev, "Unhandled color depth of %u\n",
 				fb_info->var.bits_per_pixel);
 		return -EINVAL;
@@ -504,6 +519,8 @@ static int mxsfb_set_par(struct fb_info *fb_info)
 			fb_info->fix.line_length * fb_info->var.yoffset,
 			host->base + host->devdata->next_buf);
 
+	mxsfb_disable_axi_clk(host);
+
 	if (reenable)
 		mxsfb_enable_controller(fb_info);
 
@@ -582,10 +599,16 @@ static int mxsfb_pan_display(struct fb_var_screeninfo *var,
 
 	offset = fb_info->fix.line_length * var->yoffset;
 
+	if (!host->enabled)
+		mxsfb_enable_axi_clk(host);
+
 	/* update on next VSYNC */
 	writel(fb_info->fix.smem_start + offset,
 			host->base + host->devdata->next_buf);
 
+	if (!host->enabled)
+		mxsfb_disable_axi_clk(host);
+
 	return 0;
 }
 
@@ -608,13 +631,17 @@ static int mxsfb_restore_mode(struct mxsfb_info *host,
 	unsigned line_count;
 	unsigned period;
 	unsigned long pa, fbsize;
-	int bits_per_pixel, ofs;
+	int bits_per_pixel, ofs, ret = 0;
 	u32 transfer_count, vdctrl0, vdctrl2, vdctrl3, vdctrl4, ctrl;
 
+	mxsfb_enable_axi_clk(host);
+
 	/* Only restore the mode when the controller is running */
 	ctrl = readl(host->base + LCDC_CTRL);
-	if (!(ctrl & CTRL_RUN))
-		return -EINVAL;
+	if (!(ctrl & CTRL_RUN)) {
+		ret = -EINVAL;
+		goto err;
+	}
 
 	vdctrl0 = readl(host->base + LCDC_VDCTRL0);
 	vdctrl2 = readl(host->base + LCDC_VDCTRL2);
@@ -635,7 +662,8 @@ static int mxsfb_restore_mode(struct mxsfb_info *host,
 		break;
 	case 1:
 	default:
-		return -EINVAL;
+		ret = -EINVAL;
+		goto err;
 	}
 
 	fb_info->var.bits_per_pixel = bits_per_pixel;
@@ -673,10 +701,14 @@ static int mxsfb_restore_mode(struct mxsfb_info *host,
 
 	pa = readl(host->base + host->devdata->cur_buf);
 	fbsize = fb_info->fix.line_length * vmode->yres;
-	if (pa < fb_info->fix.smem_start)
-		return -EINVAL;
-	if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len)
-		return -EINVAL;
+	if (pa < fb_info->fix.smem_start) {
+		ret = -EINVAL;
+		goto err;
+	}
+	if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len) {
+		ret = -EINVAL;
+		goto err;
+	}
 	ofs = pa - fb_info->fix.smem_start;
 	if (ofs) {
 		memmove(fb_info->screen_base, fb_info->screen_base + ofs, fbsize);
@@ -689,7 +721,11 @@ static int mxsfb_restore_mode(struct mxsfb_info *host,
 	clk_prepare_enable(host->clk);
 	host->enabled = 1;
 
-	return 0;
+err:
+	if (ret)
+		mxsfb_disable_axi_clk(host);
+
+	return ret;
 }
 
 static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host,
@@ -915,7 +951,9 @@ static int mxsfb_probe(struct platform_device *pdev)
 	}
 
 	if (!host->enabled) {
+		mxsfb_enable_axi_clk(host);
 		writel(0, host->base + LCDC_CTRL);
+		mxsfb_disable_axi_clk(host);
 		mxsfb_set_par(fb_info);
 		mxsfb_enable_controller(fb_info);
 	}
@@ -954,11 +992,15 @@ static void mxsfb_shutdown(struct platform_device *pdev)
 	struct fb_info *fb_info = platform_get_drvdata(pdev);
 	struct mxsfb_info *host = to_imxfb_host(fb_info);
 
+	mxsfb_enable_axi_clk(host);
+
 	/*
 	 * Force stop the LCD controller as keeping it running during reboot
 	 * might interfere with the BootROM's boot mode pads sampling.
 	 */
 	writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR);
+
+	mxsfb_disable_axi_clk(host);
 }
 
 static struct platform_driver mxsfb_driver = {
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] video: mxsfb: Make sure axi clock is enabled when accessing registers
  2015-03-04  5:58 [PATCH] video: mxsfb: Make sure axi clock is enabled when accessing registers Liu Ying
@ 2015-03-04  6:08 ` Greg KH
  2015-03-04  6:57   ` Peter Chen
  2015-03-04  6:36 ` Peter Chen
  1 sibling, 1 reply; 4+ messages in thread
From: Greg KH @ 2015-03-04  6:08 UTC (permalink / raw)
  To: Liu Ying
  Cc: linux-fbdev, Peter Chen, Jean-Christophe Plagniol-Villard,
	Tomi Valkeinen, Fabio Estevam, linux-kernel, stable

On Wed, Mar 04, 2015 at 01:58:55PM +0800, Liu Ying wrote:
> The LCDIF engines embedded in i.MX6sl and i.MX6sx SoCs need the axi clock
> as the engine's system clock.  The clock should be enabled when accessing
> LCDIF registers, otherwise the kernel would hang up.  We should also keep
> the clock being enabled when the engine is being active to scan out frames
> from memory.  This patch makes sure the axi clock is enabled when accessing
> registers so that the kernel hang up issue can be fixed.
> 
> Reported-by: Peter Chen <peter.chen@freescale.com>
> Signed-off-by: Liu Ying <Ying.Liu@freescale.com>
> ---
>  drivers/video/fbdev/mxsfb.c | 70 ++++++++++++++++++++++++++++++++++++---------
>  1 file changed, 56 insertions(+), 14 deletions(-)

<formletter>

This is not the correct way to submit patches for inclusion in the
stable kernel tree.  Please read Documentation/stable_kernel_rules.txt
for how to do this properly.

</formletter>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] video: mxsfb: Make sure axi clock is enabled when accessing registers
  2015-03-04  5:58 [PATCH] video: mxsfb: Make sure axi clock is enabled when accessing registers Liu Ying
  2015-03-04  6:08 ` Greg KH
@ 2015-03-04  6:36 ` Peter Chen
  1 sibling, 0 replies; 4+ messages in thread
From: Peter Chen @ 2015-03-04  6:36 UTC (permalink / raw)
  To: Liu Ying
  Cc: linux-fbdev, Jean-Christophe Plagniol-Villard, Tomi Valkeinen,
	Fabio Estevam, linux-kernel, stable

On Wed, Mar 04, 2015 at 01:58:55PM +0800, Liu Ying wrote:
> The LCDIF engines embedded in i.MX6sl and i.MX6sx SoCs need the axi clock
> as the engine's system clock.  The clock should be enabled when accessing
> LCDIF registers, otherwise the kernel would hang up.  We should also keep
> the clock being enabled when the engine is being active to scan out frames
> from memory.  This patch makes sure the axi clock is enabled when accessing
> registers so that the kernel hang up issue can be fixed.
> 
> Reported-by: Peter Chen <peter.chen@freescale.com>
> Signed-off-by: Liu Ying <Ying.Liu@freescale.com>
> ---
>  drivers/video/fbdev/mxsfb.c | 70 ++++++++++++++++++++++++++++++++++++---------
>  1 file changed, 56 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/video/fbdev/mxsfb.c b/drivers/video/fbdev/mxsfb.c
> index f8ac4a4..a8cf3b2 100644
> --- a/drivers/video/fbdev/mxsfb.c
> +++ b/drivers/video/fbdev/mxsfb.c
> @@ -316,6 +316,18 @@ static int mxsfb_check_var(struct fb_var_screeninfo *var,
>  	return 0;
>  }
>  
> +static inline void mxsfb_enable_axi_clk(struct mxsfb_info *host)
> +{
> +	if (host->clk_axi)
> +		clk_prepare_enable(host->clk_axi);
> +}
> +
> +static inline void mxsfb_disable_axi_clk(struct mxsfb_info *host)
> +{
> +	if (host->clk_axi)
> +		clk_disable_unprepare(host->clk_axi);
> +}
> +
>  static void mxsfb_enable_controller(struct fb_info *fb_info)
>  {
>  	struct mxsfb_info *host = to_imxfb_host(fb_info);
> @@ -333,14 +345,13 @@ static void mxsfb_enable_controller(struct fb_info *fb_info)
>  		}
>  	}
>  
> -	if (host->clk_axi)
> -		clk_prepare_enable(host->clk_axi);
> -
>  	if (host->clk_disp_axi)
>  		clk_prepare_enable(host->clk_disp_axi);
>  	clk_prepare_enable(host->clk);
>  	clk_set_rate(host->clk, PICOS2KHZ(fb_info->var.pixclock) * 1000U);
>  
> +	mxsfb_enable_axi_clk(host);
> +
>  	/* if it was disabled, re-enable the mode again */
>  	writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET);
>  
> @@ -380,11 +391,11 @@ static void mxsfb_disable_controller(struct fb_info *fb_info)
>  	reg = readl(host->base + LCDC_VDCTRL4);
>  	writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4);
>  
> +	mxsfb_disable_axi_clk(host);
> +
>  	clk_disable_unprepare(host->clk);
>  	if (host->clk_disp_axi)
>  		clk_disable_unprepare(host->clk_disp_axi);
> -	if (host->clk_axi)
> -		clk_disable_unprepare(host->clk_axi);
>  
>  	host->enabled = 0;
>  
> @@ -421,6 +432,8 @@ static int mxsfb_set_par(struct fb_info *fb_info)
>  		mxsfb_disable_controller(fb_info);
>  	}
>  
> +	mxsfb_enable_axi_clk(host);
> +
>  	/* clear the FIFOs */
>  	writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET);
>  
> @@ -438,6 +451,7 @@ static int mxsfb_set_par(struct fb_info *fb_info)
>  		ctrl |= CTRL_SET_WORD_LENGTH(3);
>  		switch (host->ld_intf_width) {
>  		case STMLCDIF_8BIT:
> +			mxsfb_disable_axi_clk(host);
>  			dev_err(&host->pdev->dev,
>  					"Unsupported LCD bus width mapping\n");
>  			return -EINVAL;
> @@ -451,6 +465,7 @@ static int mxsfb_set_par(struct fb_info *fb_info)
>  		writel(CTRL1_SET_BYTE_PACKAGING(0x7), host->base + LCDC_CTRL1);
>  		break;
>  	default:
> +		mxsfb_disable_axi_clk(host);
>  		dev_err(&host->pdev->dev, "Unhandled color depth of %u\n",
>  				fb_info->var.bits_per_pixel);
>  		return -EINVAL;
> @@ -504,6 +519,8 @@ static int mxsfb_set_par(struct fb_info *fb_info)
>  			fb_info->fix.line_length * fb_info->var.yoffset,
>  			host->base + host->devdata->next_buf);
>  
> +	mxsfb_disable_axi_clk(host);
> +
>  	if (reenable)
>  		mxsfb_enable_controller(fb_info);
>  
> @@ -582,10 +599,16 @@ static int mxsfb_pan_display(struct fb_var_screeninfo *var,
>  
>  	offset = fb_info->fix.line_length * var->yoffset;
>  
> +	if (!host->enabled)
> +		mxsfb_enable_axi_clk(host);
> +
>  	/* update on next VSYNC */
>  	writel(fb_info->fix.smem_start + offset,
>  			host->base + host->devdata->next_buf);
>  
> +	if (!host->enabled)
> +		mxsfb_disable_axi_clk(host);
> +
>  	return 0;
>  }
>  
> @@ -608,13 +631,17 @@ static int mxsfb_restore_mode(struct mxsfb_info *host,
>  	unsigned line_count;
>  	unsigned period;
>  	unsigned long pa, fbsize;
> -	int bits_per_pixel, ofs;
> +	int bits_per_pixel, ofs, ret = 0;
>  	u32 transfer_count, vdctrl0, vdctrl2, vdctrl3, vdctrl4, ctrl;
>  
> +	mxsfb_enable_axi_clk(host);
> +
>  	/* Only restore the mode when the controller is running */
>  	ctrl = readl(host->base + LCDC_CTRL);
> -	if (!(ctrl & CTRL_RUN))
> -		return -EINVAL;
> +	if (!(ctrl & CTRL_RUN)) {
> +		ret = -EINVAL;
> +		goto err;
> +	}
>  
>  	vdctrl0 = readl(host->base + LCDC_VDCTRL0);
>  	vdctrl2 = readl(host->base + LCDC_VDCTRL2);
> @@ -635,7 +662,8 @@ static int mxsfb_restore_mode(struct mxsfb_info *host,
>  		break;
>  	case 1:
>  	default:
> -		return -EINVAL;
> +		ret = -EINVAL;
> +		goto err;
>  	}
>  
>  	fb_info->var.bits_per_pixel = bits_per_pixel;
> @@ -673,10 +701,14 @@ static int mxsfb_restore_mode(struct mxsfb_info *host,
>  
>  	pa = readl(host->base + host->devdata->cur_buf);
>  	fbsize = fb_info->fix.line_length * vmode->yres;
> -	if (pa < fb_info->fix.smem_start)
> -		return -EINVAL;
> -	if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len)
> -		return -EINVAL;
> +	if (pa < fb_info->fix.smem_start) {
> +		ret = -EINVAL;
> +		goto err;
> +	}
> +	if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len) {
> +		ret = -EINVAL;
> +		goto err;
> +	}
>  	ofs = pa - fb_info->fix.smem_start;
>  	if (ofs) {
>  		memmove(fb_info->screen_base, fb_info->screen_base + ofs, fbsize);
> @@ -689,7 +721,11 @@ static int mxsfb_restore_mode(struct mxsfb_info *host,
>  	clk_prepare_enable(host->clk);
>  	host->enabled = 1;
>  
> -	return 0;
> +err:
> +	if (ret)
> +		mxsfb_disable_axi_clk(host);
> +
> +	return ret;
>  }
>  
>  static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host,
> @@ -915,7 +951,9 @@ static int mxsfb_probe(struct platform_device *pdev)
>  	}
>  
>  	if (!host->enabled) {
> +		mxsfb_enable_axi_clk(host);
>  		writel(0, host->base + LCDC_CTRL);
> +		mxsfb_disable_axi_clk(host);
>  		mxsfb_set_par(fb_info);
>  		mxsfb_enable_controller(fb_info);
>  	}
> @@ -954,11 +992,15 @@ static void mxsfb_shutdown(struct platform_device *pdev)
>  	struct fb_info *fb_info = platform_get_drvdata(pdev);
>  	struct mxsfb_info *host = to_imxfb_host(fb_info);
>  
> +	mxsfb_enable_axi_clk(host);
> +
>  	/*
>  	 * Force stop the LCD controller as keeping it running during reboot
>  	 * might interfere with the BootROM's boot mode pads sampling.
>  	 */
>  	writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR);
> +
> +	mxsfb_disable_axi_clk(host);
>  }
>  
>  static struct platform_driver mxsfb_driver = {
> -- 
> 2.1.0
> 

It fixed the system hang issue at yocto rootfs at imx6sx sdb
and imx6sl sdb boards.

Tested-by: Peter Chen <peter.chen@freescale.com>

-- 

Best Regards,
Peter Chen

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] video: mxsfb: Make sure axi clock is enabled when accessing registers
  2015-03-04  6:08 ` Greg KH
@ 2015-03-04  6:57   ` Peter Chen
  0 siblings, 0 replies; 4+ messages in thread
From: Peter Chen @ 2015-03-04  6:57 UTC (permalink / raw)
  To: Greg KH
  Cc: Liu Ying, linux-fbdev, Jean-Christophe Plagniol-Villard,
	Tomi Valkeinen, Fabio Estevam, linux-kernel, stable

On Tue, Mar 03, 2015 at 10:08:17PM -0800, Greg KH wrote:
> On Wed, Mar 04, 2015 at 01:58:55PM +0800, Liu Ying wrote:
> > The LCDIF engines embedded in i.MX6sl and i.MX6sx SoCs need the axi clock
> > as the engine's system clock.  The clock should be enabled when accessing
> > LCDIF registers, otherwise the kernel would hang up.  We should also keep
> > the clock being enabled when the engine is being active to scan out frames
> > from memory.  This patch makes sure the axi clock is enabled when accessing
> > registers so that the kernel hang up issue can be fixed.
> > 
> > Reported-by: Peter Chen <peter.chen@freescale.com>
> > Signed-off-by: Liu Ying <Ying.Liu@freescale.com>
> > ---
> >  drivers/video/fbdev/mxsfb.c | 70 ++++++++++++++++++++++++++++++++++++---------
> >  1 file changed, 56 insertions(+), 14 deletions(-)
> 
> <formletter>
> 
> This is not the correct way to submit patches for inclusion in the
> stable kernel tree.  Please read Documentation/stable_kernel_rules.txt
> for how to do this properly.
> 
> </formletter>

Hi Greg,

I find this system hang issue at v4.0, and it should exist at v3.19 too.
Do you mean Ying forget to add tag "Cc: stable@vger.kernel.org # 3.19"
at commit log or you think this fix is too large?

-- 

Best Regards,
Peter Chen

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-03-04  6:57 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-03-04  5:58 [PATCH] video: mxsfb: Make sure axi clock is enabled when accessing registers Liu Ying
2015-03-04  6:08 ` Greg KH
2015-03-04  6:57   ` Peter Chen
2015-03-04  6:36 ` Peter Chen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).