diff options
author | Miguel Vadillo <vadillo@ti.com> | 2010-09-24 12:15:19 -0500 |
---|---|---|
committer | Ricardo Perez Olivares <x0081762@ti.com> | 2010-09-27 17:10:29 -0500 |
commit | 7932474f6363a60a7102dec3a9d51003c0aebb8a (patch) | |
tree | ac06255c6020a4c63399dc1b50c3aac7aa20dae4 | |
parent | 8783e4e98dc368e1d03d44c767cde66e78c073ba (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.c | 109 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/ipu_dev.h | 18 | ||||
-rw-r--r-- | drivers/dsp/syslink/ipu_pm/ipu_pm.c | 104 | ||||
-rw-r--r-- | drivers/dsp/syslink/ipu_pm/ipu_pm.h | 9 |
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); |