diff options
author | Terje Bergstrom <tbergstrom@nvidia.com> | 2011-11-03 12:40:29 +0200 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-11-10 10:21:55 -0800 |
commit | 9251b247ae4b7831c49a49ade13b433c884c6ceb (patch) | |
tree | 2facfe6d0bc592320e62a3f53eece20a297481cb /drivers/video/tegra/host | |
parent | 3ba1a4e17b6839bf0485b6db542ab1d5fd1edbc0 (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.c | 8 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_acm.c | 66 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_acm.h | 2 |
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, |