[PATCH 01/17] drm/tegra: dc: Add powergate support

2014-11-04 Thread Thierry Reding
On Mon, Nov 03, 2014 at 12:15:38PM -0500, Sean Paul wrote:
> On Mon, Nov 3, 2014 at 4:27 AM, Thierry Reding  
> wrote:
> > From: Thierry Reding 
> >
> > Both display controllers are in their own power partition. Currently the
> > driver relies on the assumption that these partitions are on (which is
> > the hardware default). However some bootloaders may disable them, so the
> > driver must make sure to turn them back on to avoid hangs.
> >
> 
> A bug in our firmware caused the host1x block to be in a bad state on
> boot such that we had to pulse the reset control in kernel probe to
> recover. I'm not sure how paranoid you want to be here, but something
> to keep in mind.

I think I'd rather not do that. The reason is simple: eventually what
I'd like to do is implement a way for firmware to hand over display to
the kernel so we can seamlessly transition graphics. If we pulse reset
for any of the blocks we can no longer do that.

Thierry
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: 



[PATCH 01/17] drm/tegra: dc: Add powergate support

2014-11-03 Thread Sean Paul
On Mon, Nov 3, 2014 at 4:27 AM, Thierry Reding  
wrote:
> From: Thierry Reding 
>
> Both display controllers are in their own power partition. Currently the
> driver relies on the assumption that these partitions are on (which is
> the hardware default). However some bootloaders may disable them, so the
> driver must make sure to turn them back on to avoid hangs.
>

A bug in our firmware caused the host1x block to be in a bad state on
boot such that we had to pulse the reset control in kernel probe to
recover. I'm not sure how paranoid you want to be here, but something
to keep in mind.

Sean


> Signed-off-by: Thierry Reding 
> ---
>  drivers/gpu/drm/tegra/dc.c  | 45 
> ++---
>  drivers/gpu/drm/tegra/drm.h |  1 +
>  2 files changed, 43 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> index 6553fd238685..4a015232e2e8 100644
> --- a/drivers/gpu/drm/tegra/dc.c
> +++ b/drivers/gpu/drm/tegra/dc.c
> @@ -11,6 +11,8 @@
>  #include 
>  #include 
>
> +#include 
> +
>  #include "dc.h"
>  #include "drm.h"
>  #include "gem.h"
> @@ -20,6 +22,7 @@ struct tegra_dc_soc_info {
> bool supports_cursor;
> bool supports_block_linear;
> unsigned int pitch_align;
> +   bool has_powergate;
>  };
>
>  struct tegra_plane {
> @@ -1357,6 +1360,7 @@ static const struct tegra_dc_soc_info 
> tegra20_dc_soc_info = {
> .supports_cursor = false,
> .supports_block_linear = false,
> .pitch_align = 8,
> +   .has_powergate = false,
>  };
>
>  static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
> @@ -1364,6 +1368,7 @@ static const struct tegra_dc_soc_info 
> tegra30_dc_soc_info = {
> .supports_cursor = false,
> .supports_block_linear = false,
> .pitch_align = 8,
> +   .has_powergate = false,
>  };
>
>  static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
> @@ -1371,6 +1376,7 @@ static const struct tegra_dc_soc_info 
> tegra114_dc_soc_info = {
> .supports_cursor = false,
> .supports_block_linear = false,
> .pitch_align = 64,
> +   .has_powergate = true,
>  };
>
>  static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
> @@ -1378,6 +1384,7 @@ static const struct tegra_dc_soc_info 
> tegra124_dc_soc_info = {
> .supports_cursor = true,
> .supports_block_linear = true,
> .pitch_align = 64,
> +   .has_powergate = true,
>  };
>
>  static const struct of_device_id tegra_dc_of_match[] = {
> @@ -1385,6 +1392,9 @@ static const struct of_device_id tegra_dc_of_match[] = {
> .compatible = "nvidia,tegra124-dc",
> .data = _dc_soc_info,
> }, {
> +   .compatible = "nvidia,tegra114-dc",
> +   .data = _dc_soc_info,
> +   }, {
> .compatible = "nvidia,tegra30-dc",
> .data = _dc_soc_info,
> }, {
> @@ -1467,9 +1477,34 @@ static int tegra_dc_probe(struct platform_device *pdev)
> return PTR_ERR(dc->rst);
> }
>
> -   err = clk_prepare_enable(dc->clk);
> -   if (err < 0)
> -   return err;
> +   if (dc->soc->has_powergate) {
> +   if (dc->pipe == 0)
> +   dc->powergate = TEGRA_POWERGATE_DIS;
> +   else
> +   dc->powergate = TEGRA_POWERGATE_DISB;
> +
> +   err = tegra_powergate_sequence_power_up(dc->powergate, 
> dc->clk,
> +   dc->rst);
> +   if (err < 0) {
> +   dev_err(>dev, "failed to power partition: %d\n",
> +   err);
> +   return err;
> +   }
> +   } else {
> +   err = clk_prepare_enable(dc->clk);
> +   if (err < 0) {
> +   dev_err(>dev, "failed to enable clock: %d\n",
> +   err);
> +   return err;
> +   }
> +
> +   err = reset_control_deassert(dc->rst);
> +   if (err < 0) {
> +   dev_err(>dev, "failed to deassert reset: %d\n",
> +   err);
> +   return err;
> +   }
> +   }
>
> regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> dc->regs = devm_ioremap_resource(>dev, regs);
> @@ -1523,6 +1558,10 @@ static int tegra_dc_remove(struct platform_device 
> *pdev)
> }
>
> reset_control_assert(dc->rst);
> +
> +   if (dc->soc->has_powergate)
> +   tegra_powergate_power_off(dc->powergate);
> +
> clk_disable_unprepare(dc->clk);
>
> return 0;
> diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
> index e89c70fa82d5..b994c017971d 100644
> --- a/drivers/gpu/drm/tegra/drm.h
> +++ b/drivers/gpu/drm/tegra/drm.h
> @@ -101,6 +101,7 @@ struct tegra_dc {
>  

[PATCH 01/17] drm/tegra: dc: Add powergate support

2014-11-03 Thread Thierry Reding
From: Thierry Reding 

Both display controllers are in their own power partition. Currently the
driver relies on the assumption that these partitions are on (which is
the hardware default). However some bootloaders may disable them, so the
driver must make sure to turn them back on to avoid hangs.

Signed-off-by: Thierry Reding 
---
 drivers/gpu/drm/tegra/dc.c  | 45 ++---
 drivers/gpu/drm/tegra/drm.h |  1 +
 2 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 6553fd238685..4a015232e2e8 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -11,6 +11,8 @@
 #include 
 #include 

+#include 
+
 #include "dc.h"
 #include "drm.h"
 #include "gem.h"
@@ -20,6 +22,7 @@ struct tegra_dc_soc_info {
bool supports_cursor;
bool supports_block_linear;
unsigned int pitch_align;
+   bool has_powergate;
 };

 struct tegra_plane {
@@ -1357,6 +1360,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info 
= {
.supports_cursor = false,
.supports_block_linear = false,
.pitch_align = 8,
+   .has_powergate = false,
 };

 static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
@@ -1364,6 +1368,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info 
= {
.supports_cursor = false,
.supports_block_linear = false,
.pitch_align = 8,
+   .has_powergate = false,
 };

 static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
@@ -1371,6 +1376,7 @@ static const struct tegra_dc_soc_info 
tegra114_dc_soc_info = {
.supports_cursor = false,
.supports_block_linear = false,
.pitch_align = 64,
+   .has_powergate = true,
 };

 static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
@@ -1378,6 +1384,7 @@ static const struct tegra_dc_soc_info 
tegra124_dc_soc_info = {
.supports_cursor = true,
.supports_block_linear = true,
.pitch_align = 64,
+   .has_powergate = true,
 };

 static const struct of_device_id tegra_dc_of_match[] = {
@@ -1385,6 +1392,9 @@ static const struct of_device_id tegra_dc_of_match[] = {
.compatible = "nvidia,tegra124-dc",
.data = _dc_soc_info,
}, {
+   .compatible = "nvidia,tegra114-dc",
+   .data = _dc_soc_info,
+   }, {
.compatible = "nvidia,tegra30-dc",
.data = _dc_soc_info,
}, {
@@ -1467,9 +1477,34 @@ static int tegra_dc_probe(struct platform_device *pdev)
return PTR_ERR(dc->rst);
}

-   err = clk_prepare_enable(dc->clk);
-   if (err < 0)
-   return err;
+   if (dc->soc->has_powergate) {
+   if (dc->pipe == 0)
+   dc->powergate = TEGRA_POWERGATE_DIS;
+   else
+   dc->powergate = TEGRA_POWERGATE_DISB;
+
+   err = tegra_powergate_sequence_power_up(dc->powergate, dc->clk,
+   dc->rst);
+   if (err < 0) {
+   dev_err(>dev, "failed to power partition: %d\n",
+   err);
+   return err;
+   }
+   } else {
+   err = clk_prepare_enable(dc->clk);
+   if (err < 0) {
+   dev_err(>dev, "failed to enable clock: %d\n",
+   err);
+   return err;
+   }
+
+   err = reset_control_deassert(dc->rst);
+   if (err < 0) {
+   dev_err(>dev, "failed to deassert reset: %d\n",
+   err);
+   return err;
+   }
+   }

regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dc->regs = devm_ioremap_resource(>dev, regs);
@@ -1523,6 +1558,10 @@ static int tegra_dc_remove(struct platform_device *pdev)
}

reset_control_assert(dc->rst);
+
+   if (dc->soc->has_powergate)
+   tegra_powergate_power_off(dc->powergate);
+
clk_disable_unprepare(dc->clk);

return 0;
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index e89c70fa82d5..b994c017971d 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -101,6 +101,7 @@ struct tegra_dc {
spinlock_t lock;

struct drm_crtc base;
+   int powergate;
int pipe;

struct clk *clk;
-- 
2.1.2