summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/host
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2011-11-03 12:40:29 +0200
committerVarun Colbert <vcolbert@nvidia.com>2011-11-10 10:21:55 -0800
commit9251b247ae4b7831c49a49ade13b433c884c6ceb (patch)
tree2facfe6d0bc592320e62a3f53eece20a297481cb /drivers/video/tegra/host
parent3ba1a4e17b6839bf0485b6db542ab1d5fd1edbc0 (diff)
video: tegra: host: Set power state in boot-up
Set correct power state for modules during boot-up. This is done by splitting nvhost_module_init() into two parts: preinit and init. Preinit sets correct power state, and is called for all modules during boot-up. Init calls pre-init and performs the rest of initialization of nvhost_module structure. Bug 855755 Reviewed-on: http://git-master/r/62102 (cherry picked from commit 003df5ddd4fcffca9b7456cdb1150cfc041f406c) Conflicts: drivers/video/tegra/host/nvhost_acm.c Change-Id: I807f0c3608b1859bcbd7e8bfcb6ed27d6cdb1a80 Reviewed-on: http://git-master/r/63218 Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Tested-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
Diffstat (limited to 'drivers/video/tegra/host')
-rw-r--r--drivers/video/tegra/host/dev.c8
-rw-r--r--drivers/video/tegra/host/nvhost_acm.c66
-rw-r--r--drivers/video/tegra/host/nvhost_acm.h2
3 files changed, 55 insertions, 21 deletions
diff --git a/drivers/video/tegra/host/dev.c b/drivers/video/tegra/host/dev.c
index 5f3380e9830a..8f8bc3783f98 100644
--- a/drivers/video/tegra/host/dev.c
+++ b/drivers/video/tegra/host/dev.c
@@ -873,7 +873,7 @@ static int __devinit nvhost_init_chip_support(struct nvhost_master *host)
return 0;
}
-struct nvhost_moduledesc hostdesc = {
+const struct nvhost_moduledesc hostdesc = {
.finalize_poweron = power_on_host,
.prepare_poweroff = power_off_host,
.clocks = {{"host1x", UINT_MAX}, {} },
@@ -952,6 +952,12 @@ static int __devinit nvhost_probe(struct platform_device *pdev)
err = nvhost_module_init(&host->mod, "host1x",
&hostdesc, NULL, &pdev->dev);
+ for (i = 0; i < host->nb_channels; i++) {
+ struct nvhost_channel *ch = &host->channels[i];
+ nvhost_module_preinit(ch->desc->name,
+ &ch->desc->module);
+ }
+
if (err)
goto fail;
diff --git a/drivers/video/tegra/host/nvhost_acm.c b/drivers/video/tegra/host/nvhost_acm.c
index d61fe7370548..3ea1e7445f10 100644
--- a/drivers/video/tegra/host/nvhost_acm.c
+++ b/drivers/video/tegra/host/nvhost_acm.c
@@ -44,6 +44,17 @@ struct nvhost_module_client {
void *priv;
};
+static void do_powergate(int id)
+{
+ if (id != -1 && tegra_powergate_is_powered(id))
+ tegra_powergate_partition(id);
+}
+
+static void do_unpowergate(int id)
+{
+ if (id != -1 && !tegra_powergate_is_powered(id))
+ tegra_unpowergate_partition(id);
+}
void nvhost_module_reset(struct device *dev, struct nvhost_module *mod)
{
@@ -93,11 +104,8 @@ static void to_state_clockgated(struct nvhost_module *mod)
nvhost_module_idle(mod->parent);
} else if (mod->powerstate == NVHOST_POWER_STATE_POWERGATED
&& mod->desc->can_powergate) {
- if (desc->powergate_ids[0] != -1)
- tegra_unpowergate_partition(desc->powergate_ids[0]);
-
- if (desc->powergate_ids[1] != -1)
- tegra_unpowergate_partition(desc->powergate_ids[1]);
+ do_unpowergate(desc->powergate_ids[0]);
+ do_unpowergate(desc->powergate_ids[1]);
}
mod->powerstate = NVHOST_POWER_STATE_CLOCKGATED;
}
@@ -144,11 +152,8 @@ static int to_state_powergated(struct nvhost_module *mod)
to_state_clockgated(mod);
if (mod->desc->can_powergate) {
- if (mod->desc->powergate_ids[0] != -1)
- tegra_powergate_partition(mod->desc->powergate_ids[0]);
-
- if (mod->desc->powergate_ids[1] != -1)
- tegra_powergate_partition(mod->desc->powergate_ids[1]);
+ do_powergate(mod->desc->powergate_ids[0]);
+ do_powergate(mod->desc->powergate_ids[1]);
}
mod->powerstate = NVHOST_POWER_STATE_POWERGATED;
@@ -331,6 +336,36 @@ void nvhost_module_remove_client(struct nvhost_master *host,
mutex_unlock(&client_list_lock);
}
+void nvhost_module_preinit(const char *name,
+ const struct nvhost_moduledesc *desc)
+{
+ int i = 0;
+ /* initialize clocks to known state */
+ while (desc->clocks[i].name && i < NVHOST_MODULE_MAX_CLOCKS) {
+ char devname[MAX_DEVID_LENGTH];
+ long rate = desc->clocks[i].default_rate;
+ struct clk *c;
+
+ snprintf(devname, MAX_DEVID_LENGTH, "tegra_%s", name);
+ c = clk_get_sys(devname, desc->clocks[i].name);
+ BUG_ON(IS_ERR_OR_NULL(c));
+
+ rate = clk_round_rate(c, rate);
+ clk_enable(c);
+ clk_set_rate(c, rate);
+ clk_disable(c);
+ i++;
+ }
+
+ if (desc->can_powergate) {
+ do_powergate(desc->powergate_ids[0]);
+ do_powergate(desc->powergate_ids[1]);
+ } else {
+ do_unpowergate(desc->powergate_ids[0]);
+ do_unpowergate(desc->powergate_ids[1]);
+ }
+}
+
int nvhost_module_init(struct nvhost_module *mod, const char *name,
const struct nvhost_moduledesc *desc,
struct nvhost_module *parent,
@@ -338,21 +373,16 @@ int nvhost_module_init(struct nvhost_module *mod, const char *name,
{
int i = 0;
+ nvhost_module_preinit(name, desc);
mod->name = name;
INIT_LIST_HEAD(&mod->client_list);
while (desc->clocks[i].name && i < NVHOST_MODULE_MAX_CLOCKS) {
char devname[MAX_DEVID_LENGTH];
- long rate = desc->clocks[i].default_rate;
snprintf(devname, MAX_DEVID_LENGTH, "tegra_%s", name);
mod->clk[i] = clk_get_sys(devname, desc->clocks[i].name);
BUG_ON(IS_ERR_OR_NULL(mod->clk[i]));
-
- rate = clk_round_rate(mod->clk[i], rate);
- clk_enable(mod->clk[i]);
- clk_set_rate(mod->clk[i], rate);
- clk_disable(mod->clk[i]);
i++;
}
mod->num_clks = i;
@@ -367,10 +397,6 @@ int nvhost_module_init(struct nvhost_module *mod, const char *name,
mod->powerstate = NVHOST_POWER_STATE_POWERGATED;
} else {
mod->powerstate = NVHOST_POWER_STATE_CLOCKGATED;
- if (desc->powergate_ids[0] != -1)
- tegra_unpowergate_partition(desc->powergate_ids[0]);
- if (desc->powergate_ids[1] != -1)
- tegra_unpowergate_partition(desc->powergate_ids[1]);
}
if (desc->init)
diff --git a/drivers/video/tegra/host/nvhost_acm.h b/drivers/video/tegra/host/nvhost_acm.h
index 5843eed8944f..06ef09ddf929 100644
--- a/drivers/video/tegra/host/nvhost_acm.h
+++ b/drivers/video/tegra/host/nvhost_acm.h
@@ -78,6 +78,8 @@ struct nvhost_module {
struct list_head client_list;
};
+/* Sets clocks and powergating state for a module */
+void nvhost_module_preinit(const char *name, const struct nvhost_moduledesc *desc);
int nvhost_module_init(struct nvhost_module *mod, const char *name,
const struct nvhost_moduledesc *desc,
struct nvhost_module *parent,