summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel Vadillo <vadillo@ti.com>2010-09-24 12:15:19 -0500
committerRicardo Perez Olivares <x0081762@ti.com>2010-09-27 17:10:29 -0500
commit7932474f6363a60a7102dec3a9d51003c0aebb8a (patch)
treeac06255c6020a4c63399dc1b50c3aac7aa20dae4
parent8783e4e98dc368e1d03d44c767cde66e78c073ba (diff)
syslink:ipu_pm: DFVS support for freq
Fix bug in error message string referencing Signed-off-by: Paul Hunt <hunt@ti.com> Add platform data for DSP resource and fix attributes for MPU and L3 interconnect. Signed-off-by: Paul Hunt <hunt@ti.com> Provide internal APIs for performance and latency constraint frameworks to use to assert these constraints into the system power management. Signed-off-by: Paul Hunt <hunt@ti.com> MPU and CORE freq/lat cstrs Add special handling for MPU and CORE frequency and latency constraints. To specify a constraint to MPU or CORE the api needs to be called passing the following to the api: - IPUPM_SELF - IPUPM_MPU - IPUPM_CORE Signed-off-by: Paul Hunt <hunt@ti.com> DVFS support in ipu_pm Calling the dvfs apis per resource. Included: - ipu[perf|lat] - iss[perf|lat] - ivahd[perf|lat] - L3 bus[lat] - mpu[perf|lat] Pending: - fdif - dsp Note: Latency calls are working but hasnt been tested. Perf/rate calls are working. Signed-off-by: Miguel Vadillo <vadillo@ti.com> Signed-off-by: Paul Hunt <hunt@ti.com> (cherry picked from commit 3c1cdb45bb67d11eda14420a7b8eaacff0c24173)
-rw-r--r--arch/arm/mach-omap2/ipu_dev.c109
-rw-r--r--arch/arm/plat-omap/include/plat/ipu_dev.h18
-rw-r--r--drivers/dsp/syslink/ipu_pm/ipu_pm.c104
-rw-r--r--drivers/dsp/syslink/ipu_pm/ipu_pm.h9
4 files changed, 230 insertions, 10 deletions
diff --git a/arch/arm/mach-omap2/ipu_dev.c b/arch/arm/mach-omap2/ipu_dev.c
index 16c0821f2c87..573da9064960 100644
--- a/arch/arm/mach-omap2/ipu_dev.c
+++ b/arch/arm/mach-omap2/ipu_dev.c
@@ -18,6 +18,7 @@
#include <mach/irqs.h>
#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>
+#include <plat/omap-pm.h>
#include <linux/platform_device.h>
#include <plat/remoteproc.h>
@@ -60,7 +61,7 @@ inline int ipu_pm_module_start(unsigned rsrc)
print_hwmod_state(pd[rsrc].oh);
ret = omap_device_enable(pd[rsrc].pdev);
if (ret)
- pr_err("device enable failed %s", pd->oh_name);
+ pr_err("device enable failed %s", pd[rsrc].oh_name);
return ret;
}
@@ -76,12 +77,100 @@ inline int ipu_pm_module_stop(unsigned rsrc)
print_hwmod_state(pd[rsrc].oh);
ret = omap_device_shutdown(pd[rsrc].pdev);
if (ret)
- pr_err("device disable failed %s", pd->oh_name);
+ pr_err("device disable failed %s", pd[rsrc].oh_name);
return ret;
}
EXPORT_SYMBOL(ipu_pm_module_stop);
+inline int ipu_pm_module_set_rate(unsigned rsrc,
+ unsigned target_rsrc,
+ unsigned rate)
+{
+ int ret;
+ unsigned target;
+ struct device *dp;
+ struct omap_ipupm_mod_platform_data *pd;
+
+ pd = ipupm_get_plat_data();
+
+ if (target_rsrc == IPU_PM_MPU)
+ dp = omap2_get_mpuss_device();
+ else if (target_rsrc == IPU_PM_CORE)
+ dp = omap2_get_l3_device();
+ else {
+ if (target_rsrc == IPU_PM_SELF)
+ target = rsrc;
+ else
+ target = target_rsrc;
+
+ if ((pd[target].caps & IPUPM_CAPS_PERF) == 0) {
+ pr_err("device set rate not supported for %s",
+ pd[target].oh_name);
+ ret = -EINVAL;
+ goto err_ret;
+ } else
+ dp = pd[target].dev;
+ }
+
+ ret = omap_device_set_rate(pd[rsrc].dev, dp, rate);
+ if (ret)
+ pr_err("device set rate failed %s", pd[target_rsrc].oh_name);
+err_ret:
+ return ret;
+}
+EXPORT_SYMBOL(ipu_pm_module_set_rate);
+
+inline int ipu_pm_module_set_latency(unsigned rsrc,
+ unsigned target_rsrc,
+ int latency)
+{
+ int ret = 0;
+ unsigned target;
+ struct omap_ipupm_mod_platform_data *pd;
+
+ pd = ipupm_get_plat_data();
+
+ if (target_rsrc == IPU_PM_MPU) {
+#ifdef CONFIG_OMAP_PM
+ ret = omap_pm_set_max_mpu_wakeup_lat(&pd[rsrc].qos_request,
+ latency);
+#endif
+ if (ret)
+ goto err_ret;
+ } else if (target_rsrc == IPU_PM_CORE) {
+#ifdef CONFIG_OMAP_PM
+ ret = omap_pm_set_max_sdma_lat(&pd[rsrc].qos_request,
+ latency);
+#endif
+ if (ret)
+ goto err_ret;
+ } else {
+ if (target_rsrc == IPU_PM_SELF)
+ target = rsrc;
+ else
+ target = target_rsrc;
+
+ if ((pd[target].caps & IPUPM_CAPS_LAT) == 0) {
+ pr_err("device set latency not supported for %s",
+ pd[target].oh_name);
+ ret = -EINVAL;
+ } else {
+#ifdef CONFIG_OMAP_PM
+ ret = omap_pm_set_max_dev_wakeup_lat(pd[rsrc].dev,
+ pd[target].dev,
+ latency);
+#endif
+ }
+ }
+
+ if (ret)
+ pr_err("module set latency failed %s", pd[target].oh_name);
+err_ret:
+ return ret;
+}
+EXPORT_SYMBOL(ipu_pm_module_set_latency);
+
static struct omap_device *od_iva;
/* FIXME: not in use now
@@ -164,15 +253,14 @@ static struct omap_ipupm_mod_platform_data omap_ipupm_data[] = {
},
{
.name = "omap-ipu-pm",
- .oh_name = "L3",
- .caps = IPUPM_CAPS_START | IPUPM_CAPS_STOP
- | IPUPM_CAPS_EXTINIT,
+ .oh_name = "l3_main_1",
+ .caps = IPUPM_CAPS_LAT | IPUPM_CAPS_EXTINIT,
.ops = &omap_ipupm_ops,
},
{
.name = "omap-ipu-pm",
.oh_name = "mpu",
- .caps = IPUPM_CAPS_START | IPUPM_CAPS_STOP
+ .caps = IPUPM_CAPS_PERF | IPUPM_CAPS_LAT
| IPUPM_CAPS_EXTINIT,
.ops = &omap_ipupm_ops,
},
@@ -182,6 +270,14 @@ static struct omap_ipupm_mod_platform_data omap_ipupm_data[] = {
.caps = IPUPM_CAPS_START | IPUPM_CAPS_STOP,
.ops = &omap_ipupm_ops,
},
+ {
+ .name = "omap-ipu-pm",
+ .oh_name = "dsp",
+ .caps = IPUPM_CAPS_START | IPUPM_CAPS_STOP
+ | IPUPM_CAPS_PERF | IPUPM_CAPS_LAT
+ | IPUPM_CAPS_EXTINIT,
+ .ops = &omap_ipupm_ops,
+ },
};
struct omap_ipupm_mod_platform_data *ipupm_get_plat_data(void)
@@ -242,6 +338,7 @@ static int __init omap_ipussdev_init(void)
if (!status) {
od_iva = od;
omap_ipupm_data[i].pdev = &od->pdev;
+ omap_ipupm_data[i].dev = &od->pdev.dev;
}
}
diff --git a/arch/arm/plat-omap/include/plat/ipu_dev.h b/arch/arm/plat-omap/include/plat/ipu_dev.h
index 8bdd28194cd7..11c0c477867b 100644
--- a/arch/arm/plat-omap/include/plat/ipu_dev.h
+++ b/arch/arm/plat-omap/include/plat/ipu_dev.h
@@ -40,7 +40,7 @@
#define IPU_PM_IOC_MAXNR 3
-#define IPUPM_CAPS_START_BIT 0
+#define IPUPM_CAPS_START_BIT 0
#define IPUPM_CAPS_STOP_BIT 1
#define IPUPM_CAPS_PERF_BIT 2
#define IPUPM_CAPS_LAT_BIT 3
@@ -48,12 +48,16 @@
/* omap_device built elsewhere */
#define IPUPM_CAPS_EXTINIT_BIT 5
#define IPUPM_CAPS_START (1 << IPUPM_CAPS_START_BIT)
-#define IPUPM_CAPS_STOP (1 << IPUPM_CAPS_STOP_BIT)
-#define IPUPM_CAPS_PERF (1 << IPUPM_CAPS_PERF_BIT)
+#define IPUPM_CAPS_STOP (1 << IPUPM_CAPS_STOP_BIT)
+#define IPUPM_CAPS_PERF (1 << IPUPM_CAPS_PERF_BIT)
#define IPUPM_CAPS_LAT (1 << IPUPM_CAPS_LAT_BIT)
#define IPUPM_CAPS_BDW (1 << IPUPM_CAPS_BDW_BIT)
#define IPUPM_CAPS_EXTINIT (1 << IPUPM_CAPS_EXTINIT_BIT)
+#define IPU_PM_SELF 100
+#define IPU_PM_MPU 101
+#define IPU_PM_CORE 102
+
struct omap_ipupm_mod;
struct omap_ipupm_mod_ops {
@@ -63,11 +67,13 @@ struct omap_ipupm_mod_ops {
struct omap_ipupm_mod_platform_data {
struct platform_device *pdev;
+ struct device *dev;
char *name;
char *oh_name;
struct omap_hwmod *oh;
struct kobject kobj;
u32 caps;
+ struct pm_qos_request_list *qos_request;
struct omap_ipupm_mod_ops *ops;
};
@@ -86,5 +92,11 @@ struct ipu_pm_dev {
extern int ipu_pm_module_start(unsigned rsrc);
extern int ipu_pm_module_stop(unsigned rsrc);
+extern int ipu_pm_module_set_rate(unsigned rsrc,
+ unsigned target_rsrc,
+ unsigned rate);
+extern int ipu_pm_module_set_latency(unsigned rsrc,
+ unsigned target_rsrc,
+ int latency);
#endif /* IPU_PM_H */
diff --git a/drivers/dsp/syslink/ipu_pm/ipu_pm.c b/drivers/dsp/syslink/ipu_pm/ipu_pm.c
index 56dfacc83a24..897bdeea458c 100644
--- a/drivers/dsp/syslink/ipu_pm/ipu_pm.c
+++ b/drivers/dsp/syslink/ipu_pm/ipu_pm.c
@@ -245,7 +245,9 @@ static u32 cam2_prev_volt;
static struct ipu_pm_object *pm_handle_appm3;
static struct ipu_pm_object *pm_handle_sysm3;
static struct workqueue_struct *ipu_wq;
+#ifdef CONFIG_OMAP_PM
static struct pm_qos_request_list *pm_qos_handle;
+#endif
static struct omap_rproc *sys_rproc;
static struct omap_rproc *app_rproc;
static struct omap_mbox *ducati_mbox;
@@ -2257,6 +2259,7 @@ static inline int ipu_pm_req_cstr_ipu(int proc_id, u32 rcb_num)
int lat;
int bw;
u32 cstr_flags;
+ int retval;
/* get the handle to proper ipu pm object */
handle = ipu_pm_get_handle(proc_id);
@@ -2279,11 +2282,21 @@ static inline int ipu_pm_req_cstr_ipu(int proc_id, u32 rcb_num)
if (cstr_flags & PM_CSTR_PERF_MASK) {
perf = rcb_p->data[1];
pr_info("Request perfomance Cstr IPU:%d\n", perf);
+ retval = ipu_pm_module_set_rate(rcb_p->sub_type,
+ IPU_PM_CORE,
+ perf);
+ if (retval)
+ return PM_UNSUPPORTED;
}
if (cstr_flags & PM_CSTR_LAT_MASK) {
lat = rcb_p->data[2];
pr_info("Request latency Cstr IPU:%d\n", lat);
+ retval = ipu_pm_module_set_latency(rcb_p->sub_type,
+ IPU_PM_CORE,
+ lat);
+ if (retval)
+ return PM_UNSUPPORTED;
}
if (cstr_flags & PM_CSTR_BW_MASK) {
@@ -2307,6 +2320,7 @@ static inline int ipu_pm_req_cstr_l3_bus(int proc_id, u32 rcb_num)
int lat;
int bw;
u32 cstr_flags;
+ int retval;
/* get the handle to proper ipu pm object */
handle = ipu_pm_get_handle(proc_id);
@@ -2334,6 +2348,11 @@ static inline int ipu_pm_req_cstr_l3_bus(int proc_id, u32 rcb_num)
if (cstr_flags & PM_CSTR_LAT_MASK) {
lat = rcb_p->data[2];
pr_info("Request latency Cstr L3 Bus:%d\n", lat);
+ retval = ipu_pm_module_set_latency(rcb_p->sub_type,
+ IPU_PM_CORE,
+ lat);
+ if (retval)
+ return PM_UNSUPPORTED;
}
if (cstr_flags & PM_CSTR_BW_MASK) {
@@ -2357,6 +2376,7 @@ static inline int ipu_pm_req_cstr_iva_hd(int proc_id, u32 rcb_num)
int lat;
int bw;
u32 cstr_flags;
+ int retval;
/* get the handle to proper ipu pm object */
handle = ipu_pm_get_handle(proc_id);
@@ -2379,11 +2399,21 @@ static inline int ipu_pm_req_cstr_iva_hd(int proc_id, u32 rcb_num)
if (cstr_flags & PM_CSTR_PERF_MASK) {
perf = rcb_p->data[1];
pr_info("Request perfomance Cstr IVA HD:%d\n", perf);
+ retval = ipu_pm_module_set_rate(rcb_p->sub_type,
+ rcb_p->sub_type,
+ perf);
+ if (retval)
+ return PM_UNSUPPORTED;
}
if (cstr_flags & PM_CSTR_LAT_MASK) {
lat = rcb_p->data[2];
pr_info("Request latency Cstr IVA HD:%d\n", lat);
+ retval = ipu_pm_module_set_latency(rcb_p->sub_type,
+ rcb_p->sub_type,
+ lat);
+ if (retval)
+ return PM_UNSUPPORTED;
}
if (cstr_flags & PM_CSTR_BW_MASK) {
@@ -2407,6 +2437,7 @@ static inline int ipu_pm_req_cstr_iss(int proc_id, u32 rcb_num)
int lat;
int bw;
u32 cstr_flags;
+ int retval;
/* get the handle to proper ipu pm object */
handle = ipu_pm_get_handle(proc_id);
@@ -2425,15 +2456,25 @@ static inline int ipu_pm_req_cstr_iss(int proc_id, u32 rcb_num)
/* Get the configurable constraints */
cstr_flags = rcb_p->data[0];
- /* TODO: call the baseport APIs */
+ /* Call the baseport APIs */
if (cstr_flags & PM_CSTR_PERF_MASK) {
perf = rcb_p->data[1];
pr_info("Request perfomance Cstr ISS:%d\n", perf);
+ retval = ipu_pm_module_set_rate(rcb_p->sub_type,
+ IPU_PM_CORE,
+ perf);
+ if (retval)
+ return PM_UNSUPPORTED;
}
if (cstr_flags & PM_CSTR_LAT_MASK) {
lat = rcb_p->data[2];
pr_info("Request latency Cstr ISS:%d\n", lat);
+ retval = ipu_pm_module_set_latency(rcb_p->sub_type,
+ IPU_PM_SELF,
+ lat);
+ if (retval)
+ return PM_UNSUPPORTED;
}
if (cstr_flags & PM_CSTR_BW_MASK) {
@@ -2457,6 +2498,7 @@ static inline int ipu_pm_req_cstr_mpu(int proc_id, u32 rcb_num)
int lat;
int bw;
u32 cstr_flags;
+ int retval;
/* get the handle to proper ipu pm object */
handle = ipu_pm_get_handle(proc_id);
@@ -2479,11 +2521,21 @@ static inline int ipu_pm_req_cstr_mpu(int proc_id, u32 rcb_num)
if (cstr_flags & PM_CSTR_PERF_MASK) {
perf = rcb_p->data[1];
pr_info("Request perfomance Cstr MPU:%d\n", perf);
+ retval = ipu_pm_module_set_rate(rcb_p->sub_type,
+ IPU_PM_MPU,
+ perf);
+ if (retval)
+ return PM_UNSUPPORTED;
}
if (cstr_flags & PM_CSTR_LAT_MASK) {
lat = rcb_p->data[2];
pr_info("Request latency Cstr MPU:%d\n", lat);
+ retval = ipu_pm_module_set_latency(rcb_p->sub_type,
+ IPU_PM_MPU,
+ lat);
+ if (retval)
+ return PM_UNSUPPORTED;
}
if (cstr_flags & PM_CSTR_BW_MASK) {
@@ -2558,6 +2610,7 @@ static inline int ipu_pm_rel_cstr_ipu(int proc_id, u32 rcb_num)
int lat;
int bw;
u32 cstr_flags;
+ int retval;
/* get the handle to proper ipu pm object */
handle = ipu_pm_get_handle(proc_id);
@@ -2580,11 +2633,21 @@ static inline int ipu_pm_rel_cstr_ipu(int proc_id, u32 rcb_num)
if (cstr_flags & PM_CSTR_PERF_MASK) {
perf = rcb_p->data[1];
pr_info("Release perfomance Cstr IPU:%d\n", perf);
+ retval = ipu_pm_module_set_rate(rcb_p->sub_type,
+ IPU_PM_CORE,
+ NO_FREQ_CONSTRAINT);
+ if (retval)
+ return PM_UNSUPPORTED;
}
if (cstr_flags & PM_CSTR_LAT_MASK) {
lat = rcb_p->data[2];
pr_info("Release latency Cstr IPU:%d\n", lat);
+ retval = ipu_pm_module_set_latency(rcb_p->sub_type,
+ IPU_PM_CORE,
+ NO_LAT_CONSTRAINT);
+ if (retval)
+ return PM_UNSUPPORTED;
}
if (cstr_flags & PM_CSTR_BW_MASK) {
@@ -2608,6 +2671,7 @@ static inline int ipu_pm_rel_cstr_l3_bus(int proc_id, u32 rcb_num)
int lat;
int bw;
u32 cstr_flags;
+ int retval;
/* get the handle to proper ipu pm object */
handle = ipu_pm_get_handle(proc_id);
@@ -2635,6 +2699,11 @@ static inline int ipu_pm_rel_cstr_l3_bus(int proc_id, u32 rcb_num)
if (cstr_flags & PM_CSTR_LAT_MASK) {
lat = rcb_p->data[2];
pr_info("Release latency Cstr L3 Bus:%d\n", lat);
+ retval = ipu_pm_module_set_latency(rcb_p->sub_type,
+ IPU_PM_CORE,
+ NO_LAT_CONSTRAINT);
+ if (retval)
+ return PM_UNSUPPORTED;
}
if (cstr_flags & PM_CSTR_BW_MASK) {
@@ -2658,6 +2727,7 @@ static inline int ipu_pm_rel_cstr_iva_hd(int proc_id, u32 rcb_num)
int lat;
int bw;
u32 cstr_flags;
+ int retval;
/* get the handle to proper ipu pm object */
handle = ipu_pm_get_handle(proc_id);
@@ -2680,11 +2750,21 @@ static inline int ipu_pm_rel_cstr_iva_hd(int proc_id, u32 rcb_num)
if (cstr_flags & PM_CSTR_PERF_MASK) {
perf = rcb_p->data[1];
pr_info("Release perfomance Cstr IVA HD:%d\n", perf);
+ retval = ipu_pm_module_set_rate(rcb_p->sub_type,
+ rcb_p->sub_type,
+ NO_FREQ_CONSTRAINT);
+ if (retval)
+ return PM_UNSUPPORTED;
}
if (cstr_flags & PM_CSTR_LAT_MASK) {
lat = rcb_p->data[2];
pr_info("Release latency Cstr IVA HD:%d\n", lat);
+ retval = ipu_pm_module_set_latency(rcb_p->sub_type,
+ rcb_p->sub_type,
+ NO_LAT_CONSTRAINT);
+ if (retval)
+ return PM_UNSUPPORTED;
}
if (cstr_flags & PM_CSTR_BW_MASK) {
@@ -2708,6 +2788,7 @@ static inline int ipu_pm_rel_cstr_iss(int proc_id, u32 rcb_num)
int lat;
int bw;
u32 cstr_flags;
+ int retval;
/* get the handle to proper ipu pm object */
handle = ipu_pm_get_handle(proc_id);
@@ -2730,11 +2811,21 @@ static inline int ipu_pm_rel_cstr_iss(int proc_id, u32 rcb_num)
if (cstr_flags & PM_CSTR_PERF_MASK) {
perf = rcb_p->data[1];
pr_info("Release perfomance Cstr ISS:%d\n", perf);
+ retval = ipu_pm_module_set_rate(rcb_p->sub_type,
+ IPU_PM_CORE,
+ NO_FREQ_CONSTRAINT);
+ if (retval)
+ return PM_UNSUPPORTED;
}
if (cstr_flags & PM_CSTR_LAT_MASK) {
lat = rcb_p->data[2];
pr_info("Release latency Cstr ISS:%d\n", lat);
+ retval = ipu_pm_module_set_latency(rcb_p->sub_type,
+ IPU_PM_SELF,
+ NO_LAT_CONSTRAINT);
+ if (retval)
+ return PM_UNSUPPORTED;
}
if (cstr_flags & PM_CSTR_BW_MASK) {
@@ -2758,6 +2849,7 @@ static inline int ipu_pm_rel_cstr_mpu(int proc_id, u32 rcb_num)
int lat;
int bw;
u32 cstr_flags;
+ int retval;
/* get the handle to proper ipu pm object */
handle = ipu_pm_get_handle(proc_id);
@@ -2780,11 +2872,21 @@ static inline int ipu_pm_rel_cstr_mpu(int proc_id, u32 rcb_num)
if (cstr_flags & PM_CSTR_PERF_MASK) {
perf = rcb_p->data[1];
pr_info("Release perfomance Cstr MPU:%d\n", perf);
+ retval = ipu_pm_module_set_rate(rcb_p->sub_type,
+ IPU_PM_MPU,
+ NO_FREQ_CONSTRAINT);
+ if (retval)
+ return PM_UNSUPPORTED;
}
if (cstr_flags & PM_CSTR_LAT_MASK) {
lat = rcb_p->data[2];
pr_info("Release latency Cstr MPU:%d\n", lat);
+ retval = ipu_pm_module_set_latency(rcb_p->sub_type,
+ IPU_PM_MPU,
+ NO_LAT_CONSTRAINT);
+ if (retval)
+ return PM_UNSUPPORTED;
}
if (cstr_flags & PM_CSTR_BW_MASK) {
diff --git a/drivers/dsp/syslink/ipu_pm/ipu_pm.h b/drivers/dsp/syslink/ipu_pm/ipu_pm.h
index 3a65ccb3ab9e..ac49b2c4a813 100644
--- a/drivers/dsp/syslink/ipu_pm/ipu_pm.h
+++ b/drivers/dsp/syslink/ipu_pm/ipu_pm.h
@@ -101,6 +101,9 @@
#define IPU_PM_MM_MPU_LAT_CONSTRAINT 10
#define IPU_PM_NO_MPU_LAT_CONSTRAINT -1
+#define NO_FREQ_CONSTRAINT 0
+#define NO_LAT_CONSTRAINT -1
+
#define RCB_SIZE 8
@@ -475,6 +478,12 @@ int ipu_pm_module_start(unsigned res_type);
/* Function to stop a module */
int ipu_pm_module_stop(unsigned res_type);
+/* Function to set a module's frequency constraint */
+int ipu_pm_module_set_rate(unsigned rsrc, unsigned target_rsrc, unsigned rate);
+
+/* Function to set a module's latency constraint */
+int ipu_pm_module_set_latency(unsigned rsrc, unsigned target_rsrc, int latency);
+
/* Function to get ducati state flag from share memory */
u32 ipu_pm_get_state(int proc_id);