summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/powergate.c
diff options
context:
space:
mode:
authorYen Lin <yelin@nvidia.com>2011-07-10 16:07:39 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:47:49 -0800
commit9cec1fb0aee0f5d0793a6552ef1e3f9da4fd3c61 (patch)
treef95a0b733c03d21d82c6071b45ac69c23b695109 /arch/arm/mach-tegra/powergate.c
parent727df62ef3a7e0c53d32ba9b7a361a68defa00fc (diff)
arm: tegra: ahci/sata: enable sata rails/partition at init
Enable sata rails and sata partition when driver initializes - add sata_oob and cml1 clocks to sata powergate partition. - set sata and sata_oob clock source using clk_set_parent API. - fix a bug in while(timeout) loop Bug 836589 Original-Change-Id: Iddc08bf851ffc83d45bd6aed4df85cde3b13f0e4 Reviewed-on: http://git-master/r/41314 Tested-by: Yen Lin <yelin@nvidia.com> Reviewed-by: Aleksandr Frid <afrid@nvidia.com> Reviewed-by: Karan Jhavar <kjhavar@nvidia.com> Reviewed-by: Rhyland Klein <rklein@nvidia.com> Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com> Rebase-Id: R500e99ac50d1e3c0851958b1c83316dded00d617
Diffstat (limited to 'arch/arm/mach-tegra/powergate.c')
-rw-r--r--arch/arm/mach-tegra/powergate.c89
1 files changed, 55 insertions, 34 deletions
diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c
index 51ab424f90ba..bdd3695d46ce 100644
--- a/arch/arm/mach-tegra/powergate.c
+++ b/arch/arm/mach-tegra/powergate.c
@@ -71,9 +71,15 @@ static DEFINE_SPINLOCK(tegra_powergate_lock);
#define MAX_HOTRESET_CLIENT_NUM 3
+enum clk_type {
+ CLK_AND_RST,
+ RST_ONLY,
+ CLK_ONLY,
+};
+
struct partition_clk_info {
const char *clk_name;
- bool only_reset;
+ enum clk_type clk_type;
/* true if clk is only used in assert/deassert reset and not while enable-den*/
struct clk *clk_ptr;
};
@@ -89,38 +95,42 @@ static struct powergate_partition powergate_partition_info[TEGRA_NUM_POWERGATE]
[TEGRA_POWERGATE_L2] = { "l2", {MC_CLIENT_LAST}, },
[TEGRA_POWERGATE_3D] = { "3d0",
{MC_CLIENT_NV, MC_CLIENT_LAST},
- {{"3d", false} }, },
+ {{"3d", CLK_AND_RST} }, },
[TEGRA_POWERGATE_PCIE] = { "pcie",
{MC_CLIENT_AFI, MC_CLIENT_LAST},
- {{"afi", false},
- {"pcie", false},
- {"pciex", true} }, },
+ {{"afi", CLK_AND_RST},
+ {"pcie", CLK_AND_RST},
+ {"pciex", RST_ONLY} }, },
[TEGRA_POWERGATE_VDEC] = { "vde",
{MC_CLIENT_VDE, MC_CLIENT_LAST},
- {{"vde", false} }, },
+ {{"vde", CLK_AND_RST} }, },
[TEGRA_POWERGATE_MPE] = { "mpe",
{MC_CLIENT_MPE, MC_CLIENT_LAST},
- {{"mpe", false} }, },
+ {{"mpe", CLK_AND_RST} }, },
[TEGRA_POWERGATE_VENC] = { "ve",
{MC_CLIENT_ISP, MC_CLIENT_VI, MC_CLIENT_LAST},
- {{"isp", false}, {"vi", false},
- {"csi", false} }, },
+ {{"isp", CLK_AND_RST},
+ {"vi", CLK_AND_RST},
+ {"csi", CLK_AND_RST} }, },
#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
[TEGRA_POWERGATE_CPU1] = { "cpu1", {MC_CLIENT_LAST}, },
[TEGRA_POWERGATE_CPU2] = { "cpu2", {MC_CLIENT_LAST}, },
[TEGRA_POWERGATE_CPU3] = { "cpu3", {MC_CLIENT_LAST}, },
[TEGRA_POWERGATE_A9LP] = { "a9lp", {MC_CLIENT_LAST}, },
[TEGRA_POWERGATE_SATA] = { "sata", {MC_CLIENT_SATA, MC_CLIENT_LAST},
- {{"sata", false},
- {"sata_cold", true} }, },
+ {{"sata", CLK_AND_RST},
+ {"sata_oob", CLK_AND_RST},
+ {"cml1", CLK_ONLY},
+ {"sata_cold", RST_ONLY} }, },
[TEGRA_POWERGATE_3D1] = { "3d1",
{MC_CLIENT_NV2, MC_CLIENT_LAST},
- {{"3d2", false} }, },
+ {{"3d2", CLK_AND_RST} }, },
[TEGRA_POWERGATE_HEG] = { "heg",
{MC_CLIENT_G2, MC_CLIENT_EPP, MC_CLIENT_HC},
- {{"2d", false}, {"epp", false},
- {"host1x", false},
- {"3d", true} }, },
+ {{"2d", CLK_AND_RST},
+ {"epp", CLK_AND_RST},
+ {"host1x", CLK_AND_RST},
+ {"3d", RST_ONLY} }, },
#endif
};
@@ -295,15 +305,17 @@ static int partition_clk_enable(int id)
int ret;
u32 idx;
struct clk *clk;
+ struct partition_clk_info *clk_info;
BUG_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
- clk = powergate_partition_info[id].clk_info[idx].clk_ptr;
+ clk_info = &powergate_partition_info[id].clk_info[idx];
+ clk = clk_info->clk_ptr;
if (!clk)
break;
- if (!powergate_partition_info[id].clk_info[idx].only_reset) {
+ if (clk_info->clk_type != RST_ONLY) {
ret = clk_enable(clk);
if (ret)
goto err_clk_en;
@@ -315,11 +327,9 @@ static int partition_clk_enable(int id)
err_clk_en:
WARN(1, "Could not enable clk %s", clk->name);
while (idx--) {
- if (!powergate_partition_info[id].clk_info[idx].only_reset) {
- clk = powergate_partition_info[id].
- clk_info[idx].clk_ptr;
- clk_disable(clk);
- }
+ clk_info = &powergate_partition_info[id].clk_info[idx];
+ if (clk_info->clk_type != RST_ONLY)
+ clk_disable(clk_info->clk_ptr);
}
return ret;
@@ -329,16 +339,18 @@ static int is_partition_clk_disabled(int id)
{
u32 idx;
struct clk *clk;
+ struct partition_clk_info *clk_info;
int ret = 0;
BUG_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
- clk = powergate_partition_info[id].clk_info[idx].clk_ptr;
+ clk_info = &powergate_partition_info[id].clk_info[idx];
+ clk = clk_info->clk_ptr;
if (!clk)
break;
- if (!powergate_partition_info[id].clk_info[idx].only_reset) {
+ if (clk_info->clk_type != RST_ONLY) {
if (tegra_is_clk_enabled(clk)) {
ret = -1;
break;
@@ -353,15 +365,17 @@ static void partition_clk_disable(int id)
{
u32 idx;
struct clk *clk;
+ struct partition_clk_info *clk_info;
BUG_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
- clk = powergate_partition_info[id].clk_info[idx].clk_ptr;
+ clk_info = &powergate_partition_info[id].clk_info[idx];
+ clk = clk_info->clk_ptr;
if (!clk)
break;
- if (!powergate_partition_info[id].clk_info[idx].only_reset)
+ if (clk_info->clk_type != RST_ONLY)
clk_disable(clk);
}
}
@@ -369,29 +383,36 @@ static void partition_clk_disable(int id)
static void powergate_partition_assert_reset(int id)
{
u32 idx;
+ struct clk *clk_ptr;
+ struct partition_clk_info *clk_info;
BUG_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
- if (!powergate_partition_info[id].clk_info[idx].clk_ptr)
+ clk_info = &powergate_partition_info[id].clk_info[idx];
+ clk_ptr = clk_info->clk_ptr;
+ if (!clk_ptr)
break;
- tegra_periph_reset_assert(
- powergate_partition_info[id].
- clk_info[idx].clk_ptr);
- }
+ if (clk_info->clk_type != CLK_ONLY)
+ tegra_periph_reset_assert(clk_ptr);
+ }
}
static void powergate_partition_deassert_reset(int id)
{
u32 idx;
+ struct clk *clk_ptr;
+ struct partition_clk_info *clk_info;
BUG_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
- if (!powergate_partition_info[id].clk_info[idx].clk_ptr)
+ clk_info = &powergate_partition_info[id].clk_info[idx];
+ clk_ptr = clk_info->clk_ptr;
+ if (!clk_ptr)
break;
- tegra_periph_reset_deassert(
- powergate_partition_info[id].clk_info[idx].clk_ptr);
+ if (clk_info->clk_type != CLK_ONLY)
+ tegra_periph_reset_deassert(clk_ptr);
}
}