summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJuan Gutierrez <jgutierrez@ti.com>2012-07-19 17:48:36 -0500
committerAndy Green <andy.green@linaro.org>2012-09-07 13:05:38 +0800
commitf37713fa4dfed356689ef21124d823591db2b4a0 (patch)
treea232cf4b5c5acbfb1e9a901855c95284e05848f6 /drivers
parent46773688add33caceda39062fc1cc358b4c93331 (diff)
rpmsg: resmgr: support resource-data request from rproc
Support data request from remote processor. Currently only maximum frequency query is available for ivahd, iss and fdif. Change-Id: I9bc19f2a299e5756648b0e38aae25e7ce4ac6b02 Signed-off-by: Juan Gutierrez <jgutierrez@ti.com> Signed-off-by: Paul Hunt <hunt@ti.com> Signed-off-by: Fernando Guzman Lugo <fernando.lugo@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/rpmsg/omap_rpmsg_resmgr.c18
-rw-r--r--drivers/rpmsg/rpmsg_resmgr.c58
2 files changed, 76 insertions, 0 deletions
diff --git a/drivers/rpmsg/omap_rpmsg_resmgr.c b/drivers/rpmsg/omap_rpmsg_resmgr.c
index c856eeee73f7..a0e712430db4 100644
--- a/drivers/rpmsg/omap_rpmsg_resmgr.c
+++ b/drivers/rpmsg/omap_rpmsg_resmgr.c
@@ -570,6 +570,21 @@ static int _device_bandwidth(struct device *rdev, void *handle,
return 0;
}
+static unsigned long _get_max_freq(void *handle)
+{
+ struct rprm_gen_device_handle *obj = handle;
+ struct opp *opp;
+ unsigned long maxfreq = ULONG_MAX;
+
+ rcu_read_lock();
+ opp = opp_find_freq_floor(obj->dev, &maxfreq);
+ if (IS_ERR(opp))
+ maxfreq = 0;
+ rcu_read_unlock();
+
+ return maxfreq;
+}
+
static int rprm_iva_request(void **handle, void *data, size_t len)
{
static struct device *dev;
@@ -664,6 +679,7 @@ static struct rprm_res_ops iva_ops = {
.latency = _device_latency,
.bandwidth = _device_bandwidth,
.scale = _device_scale,
+ .get_max_freq = _get_max_freq,
};
static struct rprm_res_ops iva_seq0_ops = {
@@ -682,6 +698,7 @@ static struct rprm_res_ops fdif_ops = {
.latency = _device_latency,
.bandwidth = _device_bandwidth,
.scale = _device_scale,
+ .get_max_freq = _get_max_freq,
};
static struct rprm_res_ops sl2if_ops = {
@@ -694,6 +711,7 @@ static struct rprm_res_ops iss_ops = {
.release = rprm_iss_release,
.latency = _device_latency,
.bandwidth = _device_bandwidth,
+ .get_max_freq = _get_max_freq,
};
static struct rprm_res omap_res[] = {
diff --git a/drivers/rpmsg/rpmsg_resmgr.c b/drivers/rpmsg/rpmsg_resmgr.c
index 7320b284fd0f..19840d28d024 100644
--- a/drivers/rpmsg/rpmsg_resmgr.c
+++ b/drivers/rpmsg/rpmsg_resmgr.c
@@ -321,6 +321,51 @@ err_module:
return ret;
}
+static int _request_data(struct device *dev, struct rprm_elem *e,
+ u32 type, char data[], int len)
+{
+ int ret = 0;
+ unsigned long freq;
+
+ switch (type) {
+ case RPRM_MAX_FREQ:
+ if (len != sizeof freq) {
+ ret = -EINVAL;
+ break;
+ }
+ if (e->res->ops->get_max_freq) {
+ freq = e->res->ops->get_max_freq(e->handle);
+ memcpy(data, &freq, len);
+ } else
+ ret = -EINVAL;
+ break;
+ default:
+ dev_err(dev, "%s: invalid data request %d!\n", __func__, type);
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+static int rprm_req_data(struct rprm *rprm, u32 res_id, u32 type,
+ char data[], int len)
+{
+ int ret = 0;
+ struct rprm_elem *e;
+ struct device *dev = &rprm->rpdev->dev;
+
+ mutex_lock(&rprm->lock);
+ e = idr_find(&rprm->id_list, res_id);
+ if (!e) {
+ ret = -ENOENT;
+ goto out;
+ }
+
+ ret = _request_data(dev, e, type, data, len);
+out:
+ mutex_unlock(&rprm->lock);
+ return ret;
+}
+
static void rprm_cb(struct rpmsg_channel *rpdev, void *data, int len,
void *priv, u32 src)
{
@@ -330,6 +375,7 @@ static void rprm_cb(struct rpmsg_channel *rpdev, void *data, int len,
struct rprm_request *req;
struct rprm_release *rel;
struct rprm_constraint *c;
+ struct rprm_request_data *rd;
char ack_msg[MAX_MSG];
struct rprm_ack *ack = (void *)ack_msg;
struct rprm_request_ack *rack = (void *)ack->data;
@@ -413,6 +459,18 @@ static void rprm_cb(struct rpmsg_channel *rpdev, void *data, int len,
len = sizeof *c;
memcpy(ack->data, c, len);
break;
+ case RPRM_REQ_DATA:
+ len -= sizeof(*rd);
+ if (len < 0) {
+ dev_err(dev, "Bad request data message\n");
+ ret = -EINVAL;
+ break;
+ }
+ rd = (void *)msg->data;
+ ret = rprm_req_data(rprm, rd->res_id, rd->type, ack->data, len);
+ if (ret)
+ dev_err(dev, "request data failed! ret %d\n", ret);
+ break;
default:
dev_err(dev, "Unknow action %d\n", msg->action);
ret = -EINVAL;