summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/host/nvhost_acm.c
diff options
context:
space:
mode:
authorVandana Salve <vsalve@nvidia.com>2011-10-18 18:34:02 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:49:29 -0800
commite7a4d6233d300b607bcc1a9153fc0ea69ce65547 (patch)
treea51a67b41bf65ce85213e5be5d9867aeaa22791d /drivers/video/tegra/host/nvhost_acm.c
parentfd46ce8f4be0adfa61272185c1fd9a4ac15eac98 (diff)
nvhost: Add host module clock functionality for T20/T30
This includes Get/Set clock rate functionality. Removed the abstraction and added functionality for T20 and T30 into nvhost_acm file Bug 887263 Change-Id: I2e8ad3d96fcc3711f99f9aa42150e7d4588910fa Reviewed-on: http://git-master/r/58654 Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-by: Vandana Salve <vsalve@nvidia.com> Tested-by: Vandana Salve <vsalve@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Rebase-Id: R5aebeda335d753d23b0e8704dea949ccf0f7303e
Diffstat (limited to 'drivers/video/tegra/host/nvhost_acm.c')
-rw-r--r--drivers/video/tegra/host/nvhost_acm.c102
1 files changed, 89 insertions, 13 deletions
diff --git a/drivers/video/tegra/host/nvhost_acm.c b/drivers/video/tegra/host/nvhost_acm.c
index ed950a562be7..e4ff2d51a325 100644
--- a/drivers/video/tegra/host/nvhost_acm.c
+++ b/drivers/video/tegra/host/nvhost_acm.c
@@ -36,6 +36,15 @@
#define POWERGATE_DELAY 10
#define MAX_DEVID_LENGTH 16
+DEFINE_MUTEX(client_list_lock);
+
+struct nvhost_module_client {
+ struct list_head node;
+ unsigned long rate[NVHOST_MODULE_MAX_CLOCKS];
+ void *priv;
+};
+
+
void nvhost_module_reset(struct device *dev, struct nvhost_module *mod)
{
dev_dbg(dev,
@@ -182,36 +191,103 @@ int nvhost_module_get_rate(struct nvhost_master *host,
struct nvhost_module *mod, unsigned long *rate,
int index)
{
- int ret = -EINVAL;
- if (host_acm_op(host).get_rate)
- ret = host_acm_op(host).get_rate(mod, rate, index);
- return ret;
+ struct clk *c;
+
+ c = mod->clk[index];
+ if (IS_ERR_OR_NULL(c))
+ return -EINVAL;
+
+ /* Need to enable client to get correct rate */
+ nvhost_module_busy(mod);
+ *rate = clk_get_rate(c);
+ nvhost_module_idle(mod);
+ return 0;
+
+}
+
+static int nvhost_module_update_rate(struct nvhost_module *mod, int index)
+{
+ unsigned long rate = 0;
+ struct nvhost_module_client *m;
+
+ if (!mod->clk[index])
+ return -EINVAL;
+
+ list_for_each_entry(m, &mod->client_list, node) {
+ rate = max(m->rate[index], rate);
+ }
+ if (!rate)
+ rate = clk_round_rate(mod->clk[index],
+ mod->desc->clocks[index].default_rate);
+
+ return clk_set_rate(mod->clk[index], rate);
}
int nvhost_module_set_rate(struct nvhost_master *host,
struct nvhost_module *mod, void *priv,
unsigned long rate, int index)
{
- int ret = -EINVAL;
- if (host_acm_op(host).set_rate)
- ret = host_acm_op(host).set_rate(mod, priv, rate, index);
+ struct nvhost_module_client *m;
+ int ret;
+
+ mutex_lock(&client_list_lock);
+ list_for_each_entry(m, &mod->client_list, node) {
+ if (m->priv == priv) {
+ rate = clk_round_rate(mod->clk[index], rate);
+ m->rate[index] = rate;
+ break;
+ }
+ }
+ ret = nvhost_module_update_rate(mod, index);
+ mutex_unlock(&client_list_lock);
return ret;
+
}
int nvhost_module_add_client(struct nvhost_master *host,
struct nvhost_module *mod, void *priv)
{
- int ret = 0;
- if (host_acm_op(host).add_client)
- ret = host_acm_op(host).add_client(mod, priv);
- return ret;
+ int i;
+ unsigned long rate;
+ struct nvhost_module_client *client;
+
+ client = kzalloc(sizeof(*client), GFP_KERNEL);
+ if (!client)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&client->node);
+ client->priv = priv;
+
+ for (i = 0; i < mod->num_clks; i++) {
+ rate = clk_round_rate(mod->clk[i],
+ mod->desc->clocks[i].default_rate);
+ client->rate[i] = rate;
+ }
+ mutex_lock(&client_list_lock);
+ list_add_tail(&client->node, &mod->client_list);
+ mutex_unlock(&client_list_lock);
+ return 0;
}
void nvhost_module_remove_client(struct nvhost_master *host,
struct nvhost_module *mod, void *priv)
{
- if (host_acm_op(host).remove_client)
- host_acm_op(host).remove_client(mod, priv);
+ int i;
+ struct nvhost_module_client *m;
+
+ mutex_lock(&client_list_lock);
+ list_for_each_entry(m, &mod->client_list, node) {
+ if (priv == m->priv) {
+ list_del(&m->node);
+ break;
+ }
+ }
+ if (m) {
+ kfree(m);
+ for (i = 0; i < mod->num_clks; i++)
+ nvhost_module_update_rate(mod, i);
+ }
+ mutex_unlock(&client_list_lock);
}
int nvhost_module_init(struct nvhost_module *mod, const char *name,