diff options
author | Vandana Salve <vsalve@nvidia.com> | 2011-10-18 18:34:02 +0530 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:49:29 -0800 |
commit | e7a4d6233d300b607bcc1a9153fc0ea69ce65547 (patch) | |
tree | a51a67b41bf65ce85213e5be5d9867aeaa22791d /drivers/video/tegra | |
parent | fd46ce8f4be0adfa61272185c1fd9a4ac15eac98 (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')
-rw-r--r-- | drivers/video/tegra/host/chip_support.h | 9 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_acm.c | 102 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_acm.h | 1 | ||||
-rw-r--r-- | drivers/video/tegra/host/t30/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/tegra/host/t30/acm_t30.c | 142 | ||||
-rw-r--r-- | drivers/video/tegra/host/t30/t30.c | 3 | ||||
-rw-r--r-- | drivers/video/tegra/host/t30/t30.h | 1 |
7 files changed, 89 insertions, 170 deletions
diff --git a/drivers/video/tegra/host/chip_support.h b/drivers/video/tegra/host/chip_support.h index 04ff6951770a..8932552a29a4 100644 --- a/drivers/video/tegra/host/chip_support.h +++ b/drivers/video/tegra/host/chip_support.h @@ -154,15 +154,6 @@ struct nvhost_chip_support { unsigned int idx); } cpuaccess; - struct { - int (*add_client)(struct nvhost_module *mod, void *priv); - void (*remove_client)(struct nvhost_module *mod, void *priv); - int (*get_rate)(struct nvhost_module *mod, - unsigned long *rate, - int index); - int (*set_rate)(struct nvhost_module *mod, void *priv, - unsigned long rate, int index); - } acm; }; 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, diff --git a/drivers/video/tegra/host/nvhost_acm.h b/drivers/video/tegra/host/nvhost_acm.h index 251e1bce6651..34ad622618cc 100644 --- a/drivers/video/tegra/host/nvhost_acm.h +++ b/drivers/video/tegra/host/nvhost_acm.h @@ -94,7 +94,6 @@ int nvhost_module_set_rate(struct nvhost_master *host, struct nvhost_module *mod, void *priv, unsigned long rate, int index); -#define host_acm_op(host) (host->op.acm) static inline bool nvhost_module_powered(struct nvhost_module *mod) { diff --git a/drivers/video/tegra/host/t30/Makefile b/drivers/video/tegra/host/t30/Makefile index 7e77d8af701c..5229b2e21456 100644 --- a/drivers/video/tegra/host/t30/Makefile +++ b/drivers/video/tegra/host/t30/Makefile @@ -3,7 +3,6 @@ nvhost-t30-objs = \ channel_t30.o \ scale3d.o \ debug_t30.o \ - acm_t30.o \ 3dctx_t30.o obj-$(CONFIG_TEGRA_GRHOST) += nvhost-t30.o diff --git a/drivers/video/tegra/host/t30/acm_t30.c b/drivers/video/tegra/host/t30/acm_t30.c deleted file mode 100644 index f209e6043fb4..000000000000 --- a/drivers/video/tegra/host/t30/acm_t30.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * drivers/video/tegra/host/t30/acm_t30.c - * - * Tegra Graphics Host Power Management for Tegra3 - * - * Copyright (c) 2010-2011, NVIDIA Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include <linux/slab.h> -#include <linux/err.h> -#include "../dev.h" -#include "../chip_support.h" -#include "../nvhost_acm.h" -#include "t30.h" -DEFINE_MUTEX(client_list_lock); - -struct nvhost_module_client { - struct list_head node; - unsigned long rate[NVHOST_MODULE_MAX_CLOCKS]; - void *priv; -}; - -int t30_acm_get_rate(struct nvhost_module *mod, unsigned long *rate, - int index) -{ - 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 t30_acm_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 t30_acm_set_rate(struct nvhost_module *mod, void *priv, - unsigned long rate, int 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 = t30_acm_update_rate(mod, index); - mutex_unlock(&client_list_lock); - return ret; -} - -int t30_acm_add_client(struct nvhost_module *mod, void *priv) -{ - 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 t30_acm_remove_client(struct nvhost_module *mod, void *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++) - t30_acm_update_rate(mod, i); - } - mutex_unlock(&client_list_lock); -} - -int nvhost_init_t30_acm(struct nvhost_master *host) -{ - host->op.acm.get_rate = t30_acm_get_rate; - host->op.acm.set_rate = t30_acm_set_rate; - host->op.acm.add_client = t30_acm_add_client; - host->op.acm.remove_client = t30_acm_remove_client; - - return 0; -} diff --git a/drivers/video/tegra/host/t30/t30.c b/drivers/video/tegra/host/t30/t30.c index 00e0f648afcc..1f89824c0e25 100644 --- a/drivers/video/tegra/host/t30/t30.c +++ b/drivers/video/tegra/host/t30/t30.c @@ -46,8 +46,5 @@ int nvhost_init_t30_support(struct nvhost_master *host) err = nvhost_init_t20_cpuaccess_support(host); if (err) return err; - err = nvhost_init_t30_acm(host); - if (err) - return err; return 0; } diff --git a/drivers/video/tegra/host/t30/t30.h b/drivers/video/tegra/host/t30/t30.h index bbc88bbb81f0..4c0c2d175d73 100644 --- a/drivers/video/tegra/host/t30/t30.h +++ b/drivers/video/tegra/host/t30/t30.h @@ -26,6 +26,5 @@ int nvhost_init_t30_channel_support(struct nvhost_master *); int nvhost_init_t30_debug_support(struct nvhost_master *); -int nvhost_init_t30_acm(struct nvhost_master *); #endif /* _NVHOST_T30_H_ */ |