From 64189c5926a42b146be206100d7f8e85b4812ab9 Mon Sep 17 00:00:00 2001 From: Miguel Vadillo Date: Fri, 17 Jun 2011 10:08:21 -0500 Subject: OMAP: hwmod: avoid writing enwkup for a non SYSC_HAS_ENAWAKEUP module Modules with sysconfig type2 does not have enable wakeup bit, check SYSC_HAS_ENAWAKEUP before writing to it. Acked-by: Benoit Cousson Signed-off-by: Miguel Vadillo --- arch/arm/mach-omap2/omap_hwmod.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 085731c..38e9e6e 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -401,7 +401,8 @@ static int _enable_wakeup(struct omap_hwmod *oh, u32 *v) wakeup_mask = (0x1 << oh->class->sysc->sysc_fields->enwkup_shift); - *v |= wakeup_mask; + if (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) + *v |= wakeup_mask; if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP) _set_slave_idlemode(oh, HWMOD_IDLEMODE_SMART_WKUP, v); @@ -436,7 +437,8 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v) wakeup_mask = (0x1 << oh->class->sysc->sysc_fields->enwkup_shift); - *v &= ~wakeup_mask; + if (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) + *v &= ~wakeup_mask; if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP) _set_slave_idlemode(oh, HWMOD_IDLEMODE_SMART, v); -- cgit v1.1 From 3ae48c37b38c90ec899bcd2292d42ed076f41c10 Mon Sep 17 00:00:00 2001 From: Miguel Vadillo Date: Fri, 17 Jun 2011 10:09:09 -0500 Subject: OMAP: hwmod: enable module in shutdown to access sysconfig When calling the shutdown, the module may be already in idle. In that case, re-enable the module in order to allow the access to the sysconfig register. Signed-off-by: Miguel Vadillo Acked-by: Benoit Cousson --- arch/arm/mach-omap2/omap_hwmod.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 38e9e6e..94573ef 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -1383,8 +1383,11 @@ static int _shutdown(struct omap_hwmod *oh) } } - if (oh->class->sysc) + if (oh->class->sysc) { + if (oh->_state == _HWMOD_STATE_IDLE) + _enable(oh); _shutdown_sysc(oh); + } /* * If an IP contains only one HW reset line, then assert it -- cgit v1.1 From b58901bf1f57b7bacf4a5d76dfd085914ddced6a Mon Sep 17 00:00:00 2001 From: Axel Haslam Date: Thu, 2 Jun 2011 22:38:23 -0500 Subject: HACK: OMAP4: hwmod: Dont enable idle for aess On previous kernels, wrong hwmod register addres was preventing smartidle mode from being enabled. Now that the register addres is corrected and when Smartidle is set, ABE pwrdm does not hit retention, preventing system from hitting CSWR. This issue is being root caused by TI hardware team. Acked-by: Misael Lopez Signed-off-by: Axel Haslam --- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index e523072..8f91816 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -885,7 +885,7 @@ static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod = { static struct omap_hwmod_class_sysconfig omap44xx_aess_sysc = { .rev_offs = 0x0000, .sysc_offs = 0x0010, - .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE), + .sysc_flags = 0, .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), .sysc_fields = &omap_hwmod_sysc_type2, -- cgit v1.1 From a29aa84ff596d2ff11253e4cb5853b3c5b1988a8 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Mon, 20 Jun 2011 18:44:13 +0530 Subject: OMAP: dvfs: Create a dvfs_info per voltdm and not per device Allocating dvfs_info for every device instead of doing it for every voltage domain causes devices registered using omap_dvfs_register_device() to disappear. Signed-off-by: Rajendra Nayak --- arch/arm/mach-omap2/dvfs.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/dvfs.c b/arch/arm/mach-omap2/dvfs.c index 5420eb9..8c82f2c 100644 --- a/arch/arm/mach-omap2/dvfs.c +++ b/arch/arm/mach-omap2/dvfs.c @@ -907,6 +907,7 @@ int __init omap_dvfs_register_device(struct device *dev, char *voltdm_name, struct omap_vdd_dev_list *temp_dev; struct omap_vdd_dvfs_info *dvfs_info; struct clk *clk = NULL; + struct voltagedomain *voltdm; int ret = 0; if (!voltdm_name) { @@ -921,7 +922,14 @@ int __init omap_dvfs_register_device(struct device *dev, char *voltdm_name, /* Lock me to secure structure changes */ mutex_lock(&omap_dvfs_lock); - dvfs_info = _dev_to_dvfs_info(dev); + voltdm = voltdm_lookup(voltdm_name); + if (!voltdm) { + dev_warn(dev, "%s: unable to find voltdm %s!\n", + __func__, voltdm_name); + ret = -EINVAL; + goto out; + } + dvfs_info = _voltdm_to_dvfs_info(voltdm); if (!dvfs_info) { dvfs_info = kzalloc(sizeof(struct omap_vdd_dvfs_info), GFP_KERNEL); @@ -931,14 +939,7 @@ int __init omap_dvfs_register_device(struct device *dev, char *voltdm_name, ret = -ENOMEM; goto out; } - dvfs_info->voltdm = voltdm_lookup(voltdm_name); - if (!dvfs_info->voltdm) { - dev_warn(dev, "%s: unable to find voltdm %s!\n", - __func__, voltdm_name); - kfree(dvfs_info); - ret = -EINVAL; - goto out; - } + dvfs_info->voltdm = voltdm; /* Init the plist */ spin_lock_init(&dvfs_info->user_lock); -- cgit v1.1 From c47435d66cdc612f489cd8e0b613543bea722f86 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Mon, 20 Jun 2011 18:44:17 +0530 Subject: OMAP2+: OPP: Do not skip scanning OPP table if one of them is invalid Let omap_init_opp_table run through all the OPP's instead of returning on seeing the first invalid one. Skip the invalid ones and give a fair chance to the rest to get registered, if they are found to be valid. For every invalid entry in the OPP table, instead of a pr_warn, do a WARN so it gets the attention it needs. Signed-off-by: Rajendra Nayak --- arch/arm/mach-omap2/opp.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c index 3f423bf..1952854 100644 --- a/arch/arm/mach-omap2/opp.c +++ b/arch/arm/mach-omap2/opp.c @@ -59,16 +59,16 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def, struct device *dev; if (!opp_def->hwmod_name) { - pr_err("%s: NULL name of omap_hwmod, failing [%d].\n", - __func__, i); - return -EINVAL; + WARN(1, "%s: NULL name of omap_hwmod, failing" + " [%d].\n", __func__, i); + goto next; } oh = omap_hwmod_lookup(opp_def->hwmod_name); if (!oh || !oh->od) { - pr_warn("%s: no hwmod or odev for %s, [%d] " + WARN(1, "%s: no hwmod or odev for %s, [%d] " "cannot add OPPs.\n", __func__, opp_def->hwmod_name, i); - return -EINVAL; + goto next; } dev = &oh->od->pdev.dev; @@ -93,6 +93,7 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def, dev_err(dev, "%s:%s:err dvfs register %d %d\n", __func__, opp_def->hwmod_name, r, i); } +next: opp_def++; } -- cgit v1.1 From 2a5d74c4a4f21babff12ae800c044f4cb7ad6ad8 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Mon, 20 Jun 2011 18:44:14 +0530 Subject: OMAP4: clock: Define a virtual clock node to do l3 scaling Scaling L3 as part of DVFS on OMAP4 involves multiple CORE DPLL post dividers to be changed, and some in PER DPLL as well. Hide all these from the DVFS/OPP layer by creating a virtual clock node to handle all this internally as part of the clock framework. Also update the OMAP4 OPP table with the name of the virtual clock. Acked-by: Nishanth Menon Signed-off-by: Rajendra Nayak --- arch/arm/mach-omap2/clock44xx_data.c | 114 +++++++++++++++++++++++++++++++++++ arch/arm/mach-omap2/opp4xxx_data.c | 8 +-- arch/arm/mach-omap2/pm.c | 8 ++- 3 files changed, 123 insertions(+), 7 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index 85c551c..d332e7b 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -42,6 +42,10 @@ #define OMAP4430_MODULEMODE_HWCTRL 0 #define OMAP4430_MODULEMODE_SWCTRL 1 +static int omap4_virt_l3_set_rate(struct clk *clk, unsigned long rate); +static long omap4_virt_l3_round_rate(struct clk *clk, unsigned long rate); +static unsigned long omap4_virt_l3_recalc(struct clk *clk); + /* Root clocks */ static struct clk extalt_clkin_ck = { @@ -524,6 +528,15 @@ static struct clk dpll_core_m5x2_ck = { .set_rate = &omap2_clksel_set_rate, }; +static struct clk virt_l3_ck = { + .name = "virt_l3_ck", + .parent = &dpll_core_m5x2_ck, + .ops = &clkops_null, + .set_rate = &omap4_virt_l3_set_rate, + .recalc = &omap4_virt_l3_recalc, + .round_rate = &omap4_virt_l3_round_rate, +}; + static const struct clksel div_core_div[] = { { .parent = &dpll_core_m5x2_ck, .rates = div2_1to2_rates }, { .parent = NULL }, @@ -3208,6 +3221,7 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "dpll_core_m2_ck", &dpll_core_m2_ck, CK_44XX), CLK(NULL, "ddrphy_ck", &ddrphy_ck, CK_44XX), CLK(NULL, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck, CK_44XX), + CLK(NULL, "virt_l3_ck", &virt_l3_ck, CK_44XX), CLK(NULL, "div_core_ck", &div_core_ck, CK_44XX), CLK(NULL, "div_iva_hs_clk", &div_iva_hs_clk, CK_44XX), CLK(NULL, "div_mpu_hs_clk", &div_mpu_hs_clk, CK_44XX), @@ -3452,6 +3466,106 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "smp_twd", &smp_twd, CK_44XX), }; +#define L3_OPP50_RATE 100000000 +#define DPLL_CORE_M3_OPP50_RATE 200000000 +#define DPLL_CORE_M3_OPP100_RATE 320000000 +#define DPLL_CORE_M6_OPP50_RATE 200000000 +#define DPLL_CORE_M6_OPP100_RATE 266600000 +#define DPLL_CORE_M7_OPP50_RATE 133333333 +#define DPLL_CORE_M7_OPP100_RATE 266666666 +#define DPLL_PER_M3_OPP50_RATE 192000000 +#define DPLL_PER_M3_OPP100_RATE 256000000 +#define DPLL_PER_M6_OPP50_RATE 192000000 +#define DPLL_PER_M6_OPP100_RATE 384000000 + +static long omap4_virt_l3_round_rate(struct clk *clk, unsigned long rate) +{ + long parent_rate; + + if (!clk || !clk->parent) + return 0; + + if (clk->parent->round_rate) { + parent_rate = clk->parent->round_rate(clk, rate * 2); + if (parent_rate) + return parent_rate / 2; + } + return 0; +} + +static unsigned long omap4_virt_l3_recalc(struct clk *clk) +{ + if (!clk || !clk->parent) + return 0; + + return clk->parent->rate / 2; +} + +static int omap4_clksel_set_rate(struct clk *clk, unsigned long rate) +{ + int ret = -EINVAL; + + if (!clk->set_rate || !clk->round_rate) + return ret; + + rate = clk->round_rate(clk, rate); + if (rate) { + ret = clk->set_rate(clk, rate); + if (!ret) + propagate_rate(clk); + } + return ret; +} + +struct virt_l3_ck_deps { + unsigned long core_m3_rate; + unsigned long core_m6_rate; + unsigned long core_m7_rate; + unsigned long per_m3_rate; + unsigned long per_m6_rate; +}; + +#define NO_OF_L3_OPPS 2 +#define L3_OPP_50_INDEX 0 +#define L3_OPP_100_INDEX 1 + +static struct virt_l3_ck_deps omap4_virt_l3_clk_deps[NO_OF_L3_OPPS] = { + { /* OPP 50 */ + .core_m3_rate = DPLL_CORE_M3_OPP50_RATE, + .core_m6_rate = DPLL_CORE_M6_OPP50_RATE, + .core_m7_rate = DPLL_CORE_M7_OPP50_RATE, + .per_m3_rate = DPLL_PER_M3_OPP50_RATE, + .per_m6_rate = DPLL_PER_M6_OPP50_RATE, + }, + { /* OPP 100 */ + .core_m3_rate = DPLL_CORE_M3_OPP100_RATE, + .core_m6_rate = DPLL_CORE_M3_OPP100_RATE, + .core_m7_rate = DPLL_CORE_M7_OPP100_RATE, + .per_m3_rate = DPLL_PER_M3_OPP100_RATE, + .per_m6_rate = DPLL_PER_M6_OPP100_RATE, + }, +}; + +static int omap4_virt_l3_set_rate(struct clk *clk, unsigned long rate) +{ + struct virt_l3_ck_deps *l3_deps; + + if (rate <= L3_OPP50_RATE) + l3_deps = &omap4_virt_l3_clk_deps[L3_OPP_50_INDEX]; + else + l3_deps = &omap4_virt_l3_clk_deps[L3_OPP_100_INDEX]; + + omap4_clksel_set_rate(&dpll_core_m3x2_ck, l3_deps->core_m3_rate); + omap4_clksel_set_rate(&dpll_core_m6x2_ck, l3_deps->core_m6_rate); + omap4_clksel_set_rate(&dpll_core_m7x2_ck, l3_deps->core_m7_rate); + omap4_clksel_set_rate(&dpll_per_m3x2_ck, l3_deps->per_m3_rate); + omap4_clksel_set_rate(&dpll_per_m6x2_ck, l3_deps->per_m6_rate); + omap4_clksel_set_rate(&dpll_core_m5x2_ck, rate * 2); + + clk->rate = rate; + return 0; +} + int __init omap4xxx_clk_init(void) { struct omap_clk *c; diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c index 9083c7f..706021d 100644 --- a/arch/arm/mach-omap2/opp4xxx_data.c +++ b/arch/arm/mach-omap2/opp4xxx_data.c @@ -116,9 +116,9 @@ static struct omap_opp_def __initdata omap443x_opp_def_list[] = { /* MPU OPP4 - OPP-SB */ OPP_INITIALIZER("mpu", "dpll_mpu_ck", "mpu", true, 1008000000, OMAP4430_VDD_MPU_OPPNITRO_UV), /* L3 OPP1 - OPP50 */ - OPP_INITIALIZER("l3_main_1", "dpll_core_m5x2_ck", "core", true, 100000000, OMAP4430_VDD_CORE_OPP50_UV), + OPP_INITIALIZER("l3_main_1", "virt_l3_ck", "core", true, 100000000, OMAP4430_VDD_CORE_OPP50_UV), /* L3 OPP2 - OPP100, OPP-Turbo, OPP-SB */ - OPP_INITIALIZER("l3_main_1", "dpll_core_m5x2_ck", "core", true, 200000000, OMAP4430_VDD_CORE_OPP100_UV), + OPP_INITIALIZER("l3_main_1", "virt_l3_ck", "core", true, 200000000, OMAP4430_VDD_CORE_OPP100_UV), /* IVA OPP1 - OPP50 */ OPP_INITIALIZER("iva", "dpll_iva_m5x2_ck", "iva", true, 133000000, OMAP4430_VDD_IVA_OPP50_UV), /* IVA OPP2 - OPP100 */ @@ -182,9 +182,9 @@ static struct omap_opp_def __initdata omap446x_opp_def_list[] = { /* MPU OPP4 - OPP-Nitro SpeedBin */ OPP_INITIALIZER("mpu", "virt_dpll_mpu_ck", "mpu", false, 1500000000, OMAP4460_VDD_MPU_OPPNITRO_UV), /* L3 OPP1 - OPP50 */ - OPP_INITIALIZER("l3_main_1", "dpll_core_m5x2_ck", "core", true, 100000000, OMAP4460_VDD_CORE_OPP50_UV), + OPP_INITIALIZER("l3_main_1", "virt_l3_ck", "core", true, 100000000, OMAP4460_VDD_CORE_OPP50_UV), /* L3 OPP2 - OPP100 */ - OPP_INITIALIZER("l3_main_1", "dpll_core_m5x2_ck", "core", true, 200000000, OMAP4460_VDD_CORE_OPP100_UV), + OPP_INITIALIZER("l3_main_1", "virt_l3_ck", "core", true, 200000000, OMAP4460_VDD_CORE_OPP100_UV), /* IVA OPP1 - OPP50 */ OPP_INITIALIZER("iva", "dpll_iva_m5x2_ck", "iva", true, 133000000, OMAP4460_VDD_IVA_OPP50_UV), /* IVA OPP2 - OPP100 */ diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 4dde946..744431c 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -294,11 +294,13 @@ static void __init omap4_init_voltages(void) if (!cpu_is_omap44xx()) return; - if (cpu_is_omap446x()) + if (cpu_is_omap446x()) { omap2_set_init_voltage("mpu", "virt_dpll_mpu_ck", mpu_dev); - else + omap2_set_init_voltage("core", "virt_l3_ck", l3_dev); + } else { omap2_set_init_voltage("mpu", "dpll_mpu_ck", mpu_dev); - omap2_set_init_voltage("core", "l3_div_ck", l3_dev); + omap2_set_init_voltage("core", "l3_div_ck", l3_dev); + } omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", iva_dev); } -- cgit v1.1 From 6f25b5ac083a68a30fed8de22b84bdfd1573cb8b Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Mon, 20 Jun 2011 18:44:15 +0530 Subject: OMAP4460: OPP: Update MPU and IVA dependency Define new tables for 4460 specific MPU and IVA voltage dependencies. Also uncomment the 4430 specific dependencies since CORE voltage scale is functional now. Acked-by: Nishanth Menon Signed-off-by: Rajendra Nayak --- arch/arm/mach-omap2/omap_opp_data.h | 2 ++ arch/arm/mach-omap2/opp4xxx_data.c | 33 +++++++++++++++++++++++++++ arch/arm/mach-omap2/voltagedomains44xx_data.c | 8 ++----- 3 files changed, 37 insertions(+), 6 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/omap_opp_data.h b/arch/arm/mach-omap2/omap_opp_data.h index 076bcd4..903310f 100644 --- a/arch/arm/mach-omap2/omap_opp_data.h +++ b/arch/arm/mach-omap2/omap_opp_data.h @@ -104,5 +104,7 @@ extern struct omap_volt_data omap446x_vdd_core_volt_data[]; extern struct omap_vdd_dep_info omap443x_vddmpu_dep_info[]; extern struct omap_vdd_dep_info omap443x_vddiva_dep_info[]; +extern struct omap_vdd_dep_info omap446x_vddmpu_dep_info[]; +extern struct omap_vdd_dep_info omap446x_vddiva_dep_info[]; #endif /* __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H */ diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c index 706021d..0b14864 100644 --- a/arch/arm/mach-omap2/opp4xxx_data.c +++ b/arch/arm/mach-omap2/opp4xxx_data.c @@ -165,6 +165,39 @@ struct omap_volt_data omap446x_vdd_core_volt_data[] = { VOLT_DATA_DEFINE(0, 0, 0, 0), }; +/* OMAP 4460 MPU Core VDD dependency table */ +static struct omap_vdd_dep_volt omap446x_vdd_mpu_core_dep_data[] = { + {.main_vdd_volt = OMAP4460_VDD_MPU_OPP50_UV, .dep_vdd_volt = OMAP4460_VDD_CORE_OPP50_UV}, + {.main_vdd_volt = OMAP4460_VDD_MPU_OPP100_UV, .dep_vdd_volt = OMAP4460_VDD_CORE_OPP100_UV}, + {.main_vdd_volt = OMAP4460_VDD_MPU_OPPTURBO_UV, .dep_vdd_volt = OMAP4460_VDD_CORE_OPP100_UV}, + {.main_vdd_volt = OMAP4460_VDD_MPU_OPPNITRO_UV, .dep_vdd_volt = OMAP4460_VDD_CORE_OPP100_UV}, +}; + +struct omap_vdd_dep_info omap446x_vddmpu_dep_info[] = { + { + .name = "core", + .dep_table = omap446x_vdd_mpu_core_dep_data, + .nr_dep_entries = ARRAY_SIZE(omap446x_vdd_mpu_core_dep_data), + }, + {.name = NULL, .dep_table = NULL, .nr_dep_entries = 0}, +}; + +/* OMAP 4460 MPU IVA VDD dependency table */ +static struct omap_vdd_dep_volt omap446x_vdd_iva_core_dep_data[] = { + {.main_vdd_volt = OMAP4460_VDD_IVA_OPP50_UV, .dep_vdd_volt = OMAP4460_VDD_CORE_OPP50_UV}, + {.main_vdd_volt = OMAP4460_VDD_IVA_OPP100_UV, .dep_vdd_volt = OMAP4460_VDD_CORE_OPP100_UV}, + {.main_vdd_volt = OMAP4460_VDD_IVA_OPPTURBO_UV, .dep_vdd_volt = OMAP4460_VDD_CORE_OPP100_UV}, +}; + +struct omap_vdd_dep_info omap446x_vddiva_dep_info[] = { + { + .name = "core", + .dep_table = omap446x_vdd_iva_core_dep_data, + .nr_dep_entries = ARRAY_SIZE(omap446x_vdd_iva_core_dep_data), + }, + {.name = NULL, .dep_table = NULL, .nr_dep_entries = 0}, +}; + static struct omap_opp_def __initdata omap446x_opp_def_list[] = { /* MPU OPP1 - OPP50 */ OPP_INITIALIZER("mpu", "virt_dpll_mpu_ck", "mpu", true, 350000000, OMAP4460_VDD_MPU_OPP50_UV), diff --git a/arch/arm/mach-omap2/voltagedomains44xx_data.c b/arch/arm/mach-omap2/voltagedomains44xx_data.c index b3500e0..5fce5ad 100644 --- a/arch/arm/mach-omap2/voltagedomains44xx_data.c +++ b/arch/arm/mach-omap2/voltagedomains44xx_data.c @@ -114,18 +114,14 @@ void __init omap44xx_voltagedomains_init(void) omap4_vdd_mpu_info.volt_data = omap443x_vdd_mpu_volt_data; omap4_vdd_iva_info.volt_data = omap443x_vdd_iva_volt_data; omap4_vdd_core_info.volt_data = omap443x_vdd_core_volt_data; -#if 0 - /* - * TODO: XXX: we *should* fix O4 core domain clks before doing - * this - already tested dvfs logic.. - */ omap4_vdd_mpu_info.dep_vdd_info = omap443x_vddmpu_dep_info; omap4_vdd_iva_info.dep_vdd_info = omap443x_vddiva_dep_info; -#endif } else if (cpu_is_omap446x()) { omap4_vdd_mpu_info.volt_data = omap446x_vdd_mpu_volt_data; omap4_vdd_iva_info.volt_data = omap446x_vdd_iva_volt_data; omap4_vdd_core_info.volt_data = omap446x_vdd_core_volt_data; + omap4_vdd_mpu_info.dep_vdd_info = omap446x_vddmpu_dep_info; + omap4_vdd_iva_info.dep_vdd_info = omap446x_vddiva_dep_info; } else { return; } -- cgit v1.1 From 59dcd7add4896aa82e23b1fb7a37843afb067c00 Mon Sep 17 00:00:00 2001 From: Girish S G Date: Sat, 18 Jun 2011 23:16:14 -0500 Subject: OMAP: I2C: PM: Adapt to pm_qos framework for requesting mpu lat This patch adapts PM_QoS infrastructure to request MPU latency. PM_QoS provides interface for drivers to register performance expectations such as in this case, MPU wakeup latency. The current I2C driver uses a wrapper around PM_QoS interface to request MPU latency. The resultant behavior was as follows: when ever any i2c transaction took place, every i2c request translates into individual i2c_xfers. Each i2c_xfer in the current I2C driver does the following: allocate memory for a pm_qos request request the qos latency do things that are time critical remove the qos request free the memory Instead, it is possible to make this efficient by: Allocating, adding the request on probe (with the default as disabled), removing the request and freeing the allocated memory on remove. In i2c_xfer, we can do: update the request with required latency do time critical operation update the request with default latency to disable the request. This allows the system to optimize the time critical i2c_xfer path which all drivers which use i2c will use. Acked-by: Todd Poyner Acked-by: Nishanth Menon Signed-off-by: Girish S G --- arch/arm/plat-omap/i2c.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index 5e76d49..f8dc82f 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -113,17 +113,6 @@ static inline int omap1_i2c_add_bus(int bus_id) #ifdef CONFIG_ARCH_OMAP2PLUS -/* - * XXX This function is a temporary compatibility wrapper - only - * needed until the I2C driver can be converted to call - * omap_pm_set_max_dev_wakeup_lat() and handle a return code. - */ -static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t) -{ - static struct pm_qos_request_list *qos_request; - omap_pm_set_max_mpu_wakeup_lat(&qos_request, t); -} - static struct omap_device_pm_latency omap_i2c_latency[] = { [0] = { .deactivate_func = omap_device_idle_hwmods, @@ -160,7 +149,7 @@ static inline int omap2_i2c_add_bus(int bus_id) * Only omap3 has support for constraints */ if (cpu_is_omap34xx() || cpu_is_omap44xx()) - pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat; + pdata->needs_wakeup_latency = true; od = omap_device_build(name, bus_id, oh, pdata, sizeof(struct omap_i2c_bus_platform_data), omap_i2c_latency, ARRAY_SIZE(omap_i2c_latency), 0); -- cgit v1.1 From bb65a731de8185664721eb6deb16a1df2fbb7e72 Mon Sep 17 00:00:00 2001 From: Girish S G Date: Fri, 17 Jun 2011 20:08:55 -0500 Subject: OMAP: PM: Rename omap-pm-noop.c to omap-pm-interface.c Majority of the APIs available in omap-pm-noop.c and omap-pm.c are unused and are deprecated. We retain the header compatibility with upstream, however, the functionality in OMAP PM layer interfaces need to be retained. To prevent code duplication and associated maintenance burden, we rename the current omap-pm-noop as omap-pm-interface and add the deprecation and delta functionality in subsequent patches Acked-by: Nishanth Menon Acked-by: Ambresh K , Acked-by: Axel Haslam Signed-off-by: Girish S G --- arch/arm/plat-omap/Makefile | 2 +- arch/arm/plat-omap/omap-pm-interface.c | 370 ++++++++++++++++++++++++++++++++ arch/arm/plat-omap/omap-pm-noop.c | 372 --------------------------------- 3 files changed, 371 insertions(+), 373 deletions(-) create mode 100644 arch/arm/plat-omap/omap-pm-interface.c delete mode 100644 arch/arm/plat-omap/omap-pm-noop.c (limited to 'arch/arm') diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index e2d8843..df0824a 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -31,5 +31,5 @@ obj-y += $(i2c-omap-m) $(i2c-omap-y) # OMAP mailbox framework obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o -obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o +obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-interface.o obj-$(CONFIG_OMAP_PM) += omap-pm.o diff --git a/arch/arm/plat-omap/omap-pm-interface.c b/arch/arm/plat-omap/omap-pm-interface.c new file mode 100644 index 0000000..f6f36bd --- /dev/null +++ b/arch/arm/plat-omap/omap-pm-interface.c @@ -0,0 +1,370 @@ +/* + * omap-pm-interface.c - OMAP power management interface + * + * This code implements the OMAP power management interface to + * drivers, CPUIdle, CPUFreq, and DSP Bridge. + * + * Copyright (C) 2008-2011 Texas Instruments, Inc. + * Copyright (C) 2008-2009 Nokia Corporation + * Paul Walmsley + * + * Interface developed by (in alphabetical order): + * Karthik Dasu, Tony Lindgren, Rajendra Nayak, Sakari Poussa, Veeramanikandan + * Raju, Anand Sawant, Igor Stoppa, Paul Walmsley, Richard Woodruff + */ + +#undef DEBUG + +#include +#include +#include +#include + +/* Interface documentation is in mach/omap-pm.h */ +#include +#include + +static bool off_mode_enabled; +static int dummy_context_loss_counter; + +/* + * Device-driver-originated constraints (via board-*.c files) + */ + +int omap_pm_set_max_mpu_wakeup_lat(struct pm_qos_request_list **pmqos_req, + long t) +{ + if (!pmqos_req || t < -1) { + WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); + return -EINVAL; + }; + + if (t == -1) + pr_debug("OMAP PM: remove max MPU wakeup latency constraint\n"); + else + pr_debug("OMAP PM: add max MPU wakeup latency constraint:" + "t = %ld usec\n", t); + + /* + * For current Linux, this needs to map the MPU to a + * powerdomain, then go through the list of current max lat + * constraints on the MPU and find the smallest. If + * the latency constraint has changed, the code should + * recompute the state to enter for the next powerdomain + * state. + * + * TI CDP code can call constraint_set here. + */ + + return 0; +} + +int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, long r) +{ + if (!dev || (agent_id != OCP_INITIATOR_AGENT && + agent_id != OCP_TARGET_AGENT)) { + WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); + return -EINVAL; + }; + + if (r == 0) + pr_debug("OMAP PM: remove min bus tput constraint: " + "dev %s for agent_id %d\n", dev_name(dev), agent_id); + else + pr_debug("OMAP PM: add min bus tput constraint: " + "dev %s for agent_id %d: rate %ld KiB\n", + dev_name(dev), agent_id, r); + + /* + * This code should model the interconnect and compute the + * required clock frequency, convert that to a VDD2 OPP ID, then + * set the VDD2 OPP appropriately. + * + * TI CDP code can call constraint_set here on the VDD2 OPP. + */ + + return 0; +} + +int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, + long t) +{ + if (!req_dev || !dev || t < -1) { + WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); + return -EINVAL; + }; + + if (t == -1) + pr_debug("OMAP PM: remove max device latency constraint: " + "dev %s\n", dev_name(dev)); + else + pr_debug("OMAP PM: add max device latency constraint: " + "dev %s, t = %ld usec\n", dev_name(dev), t); + + /* + * For current Linux, this needs to map the device to a + * powerdomain, then go through the list of current max lat + * constraints on that powerdomain and find the smallest. If + * the latency constraint has changed, the code should + * recompute the state to enter for the next powerdomain + * state. Conceivably, this code should also determine + * whether to actually disable the device clocks or not, + * depending on how long it takes to re-enable the clocks. + * + * TI CDP code can call constraint_set here. + */ + + return 0; +} + +int omap_pm_set_max_sdma_lat(struct pm_qos_request_list **qos_request, long t) +{ + if (!qos_request || t < -1) { + WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); + return -EINVAL; + }; + + if (t == -1) + pr_debug("OMAP PM: remove max DMA latency constraint:\n"); + else + pr_debug("OMAP PM: add max DMA latency constraint:" + "t = %ld usec\n", t); + + /* + * For current Linux PM QOS params, this code should scan the + * list of maximum CPU and DMA latencies and select the + * smallest, then set cpu_dma_latency pm_qos_param + * accordingly. + * + * For future Linux PM QOS params, with separate CPU and DMA + * latency params, this code should just set the dma_latency param. + * + * TI CDP code can call constraint_set here. + */ + + return 0; +} + +int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r) +{ + if (!dev || !c || r < 0) { + WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); + return -EINVAL; + } + + if (r == 0) + pr_debug("OMAP PM: remove min clk rate constraint: " + "dev %s\n", dev_name(dev)); + else + pr_debug("OMAP PM: add min clk rate constraint: " + "dev %s, rate = %ld Hz\n", dev_name(dev), r); + + /* + * Code in a real implementation should keep track of these + * constraints on the clock, and determine the highest minimum + * clock rate. It should iterate over each OPP and determine + * whether the OPP will result in a clock rate that would + * satisfy this constraint (and any other PM constraint in effect + * at that time). Once it finds the lowest-voltage OPP that + * meets those conditions, it should switch to it, or return + * an error if the code is not capable of doing so. + */ + + return 0; +} + +/* + * DSP Bridge-specific constraints + */ + +const struct omap_opp *omap_pm_dsp_get_opp_table(void) +{ + pr_debug("OMAP PM: DSP request for OPP table\n"); + + /* + * Return DSP frequency table here: The final item in the + * array should have .rate = .opp_id = 0. + */ + + return NULL; +} + +void omap_pm_dsp_set_min_opp(u8 opp_id) +{ + if (opp_id == 0) { + WARN_ON(1); + return; + } + + pr_debug("OMAP PM: DSP requests minimum VDD1 OPP to be %d\n", opp_id); + + /* + * + * For l-o dev tree, our VDD1 clk is keyed on OPP ID, so we + * can just test to see which is higher, the CPU's desired OPP + * ID or the DSP's desired OPP ID, and use whichever is + * highest. + * + * In CDP12.14+, the VDD1 OPP custom clock that controls the DSP + * rate is keyed on MPU speed, not the OPP ID. So we need to + * map the OPP ID to the MPU speed for use with clk_set_rate() + * if it is higher than the current OPP clock rate. + * + */ +} + + +u8 omap_pm_dsp_get_opp(void) +{ + pr_debug("OMAP PM: DSP requests current DSP OPP ID\n"); + + /* + * For l-o dev tree, call clk_get_rate() on VDD1 OPP clock + * + * CDP12.14+: + * Call clk_get_rate() on the OPP custom clock, map that to an + * OPP ID using the tables defined in board-*.c/chip-*.c files. + */ + + return 0; +} + +/* + * CPUFreq-originated constraint + * + * In the future, this should be handled by custom OPP clocktype + * functions. + */ + +struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void) +{ + pr_debug("OMAP PM: CPUFreq request for frequency table\n"); + + /* + * Return CPUFreq frequency table here: loop over + * all VDD1 clkrates, pull out the mpu_ck frequencies, build + * table + */ + + return NULL; +} + +void omap_pm_cpu_set_freq(unsigned long f) +{ + if (f == 0) { + WARN_ON(1); + return; + } + + pr_debug("OMAP PM: CPUFreq requests CPU frequency to be set to %lu\n", + f); + + /* + * For l-o dev tree, determine whether MPU freq or DSP OPP id + * freq is higher. Find the OPP ID corresponding to the + * higher frequency. Call clk_round_rate() and clk_set_rate() + * on the OPP custom clock. + * + * CDP should just be able to set the VDD1 OPP clock rate here. + */ +} + +unsigned long omap_pm_cpu_get_freq(void) +{ + pr_debug("OMAP PM: CPUFreq requests current CPU frequency\n"); + + /* + * Call clk_get_rate() on the mpu_ck. + */ + + return 0; +} + +/** + * omap_pm_enable_off_mode - notify OMAP PM that off-mode is enabled + * + * Intended for use only by OMAP PM core code to notify this layer + * that off mode has been enabled. + */ +void omap_pm_enable_off_mode(void) +{ + off_mode_enabled = true; +} + +/** + * omap_pm_disable_off_mode - notify OMAP PM that off-mode is disabled + * + * Intended for use only by OMAP PM core code to notify this layer + * that off mode has been disabled. + */ +void omap_pm_disable_off_mode(void) +{ + off_mode_enabled = false; +} + +/* + * Device context loss tracking + */ + +#ifdef CONFIG_ARCH_OMAP2PLUS + +int omap_pm_get_dev_context_loss_count(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + int count; + + if (WARN_ON(!dev)) + return -ENODEV; + + if (dev->parent == &omap_device_parent) { + count = omap_device_get_context_loss_count(pdev); + } else { + WARN_ONCE(off_mode_enabled, "omap_pm: using dummy context loss counter; device %s should be converted to omap_device", + dev_name(dev)); + + count = dummy_context_loss_counter; + + if (off_mode_enabled) { + count++; + /* + * Context loss count has to be a non-negative value. + * Clear the sign bit to get a value range from 0 to + * INT_MAX. + */ + count &= INT_MAX; + dummy_context_loss_counter = count; + } + } + + pr_debug("OMAP PM: context loss count for dev %s = %d\n", + dev_name(dev), count); + + return count; +} + +#else + +int omap_pm_get_dev_context_loss_count(struct device *dev) +{ + return dummy_context_loss_counter; +} + +#endif + +/* Should be called before clk framework init */ +int __init omap_pm_if_early_init(void) +{ + return 0; +} + +/* Must be called after clock framework is initialized */ +int __init omap_pm_if_init(void) +{ + return 0; +} + +void omap_pm_if_exit(void) +{ + /* Deallocate CPUFreq frequency table here */ +} + diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c deleted file mode 100644 index 348f0cc..0000000 --- a/arch/arm/plat-omap/omap-pm-noop.c +++ /dev/null @@ -1,372 +0,0 @@ -/* - * omap-pm-noop.c - OMAP power management interface - dummy version - * - * This code implements the OMAP power management interface to - * drivers, CPUIdle, CPUFreq, and DSP Bridge. It is strictly for - * debug/demonstration use, as it does nothing but printk() whenever a - * function is called (when DEBUG is defined, below) - * - * Copyright (C) 2008-2009 Texas Instruments, Inc. - * Copyright (C) 2008-2009 Nokia Corporation - * Paul Walmsley - * - * Interface developed by (in alphabetical order): - * Karthik Dasu, Tony Lindgren, Rajendra Nayak, Sakari Poussa, Veeramanikandan - * Raju, Anand Sawant, Igor Stoppa, Paul Walmsley, Richard Woodruff - */ - -#undef DEBUG - -#include -#include -#include -#include - -/* Interface documentation is in mach/omap-pm.h */ -#include -#include - -static bool off_mode_enabled; -static int dummy_context_loss_counter; - -/* - * Device-driver-originated constraints (via board-*.c files) - */ - -int omap_pm_set_max_mpu_wakeup_lat(struct pm_qos_request_list **pmqos_req, - long t) -{ - if (!pmqos_req || t < -1) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - }; - - if (t == -1) - pr_debug("OMAP PM: remove max MPU wakeup latency constraint\n"); - else - pr_debug("OMAP PM: add max MPU wakeup latency constraint:" - "t = %ld usec\n", t); - - /* - * For current Linux, this needs to map the MPU to a - * powerdomain, then go through the list of current max lat - * constraints on the MPU and find the smallest. If - * the latency constraint has changed, the code should - * recompute the state to enter for the next powerdomain - * state. - * - * TI CDP code can call constraint_set here. - */ - - return 0; -} - -int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, long r) -{ - if (!dev || (agent_id != OCP_INITIATOR_AGENT && - agent_id != OCP_TARGET_AGENT)) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - }; - - if (r == 0) - pr_debug("OMAP PM: remove min bus tput constraint: " - "dev %s for agent_id %d\n", dev_name(dev), agent_id); - else - pr_debug("OMAP PM: add min bus tput constraint: " - "dev %s for agent_id %d: rate %ld KiB\n", - dev_name(dev), agent_id, r); - - /* - * This code should model the interconnect and compute the - * required clock frequency, convert that to a VDD2 OPP ID, then - * set the VDD2 OPP appropriately. - * - * TI CDP code can call constraint_set here on the VDD2 OPP. - */ - - return 0; -} - -int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, - long t) -{ - if (!req_dev || !dev || t < -1) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - }; - - if (t == -1) - pr_debug("OMAP PM: remove max device latency constraint: " - "dev %s\n", dev_name(dev)); - else - pr_debug("OMAP PM: add max device latency constraint: " - "dev %s, t = %ld usec\n", dev_name(dev), t); - - /* - * For current Linux, this needs to map the device to a - * powerdomain, then go through the list of current max lat - * constraints on that powerdomain and find the smallest. If - * the latency constraint has changed, the code should - * recompute the state to enter for the next powerdomain - * state. Conceivably, this code should also determine - * whether to actually disable the device clocks or not, - * depending on how long it takes to re-enable the clocks. - * - * TI CDP code can call constraint_set here. - */ - - return 0; -} - -int omap_pm_set_max_sdma_lat(struct pm_qos_request_list **qos_request, long t) -{ - if (!qos_request || t < -1) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - }; - - if (t == -1) - pr_debug("OMAP PM: remove max DMA latency constraint:\n"); - else - pr_debug("OMAP PM: add max DMA latency constraint:" - "t = %ld usec\n", t); - - /* - * For current Linux PM QOS params, this code should scan the - * list of maximum CPU and DMA latencies and select the - * smallest, then set cpu_dma_latency pm_qos_param - * accordingly. - * - * For future Linux PM QOS params, with separate CPU and DMA - * latency params, this code should just set the dma_latency param. - * - * TI CDP code can call constraint_set here. - */ - - return 0; -} - -int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r) -{ - if (!dev || !c || r < 0) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - } - - if (r == 0) - pr_debug("OMAP PM: remove min clk rate constraint: " - "dev %s\n", dev_name(dev)); - else - pr_debug("OMAP PM: add min clk rate constraint: " - "dev %s, rate = %ld Hz\n", dev_name(dev), r); - - /* - * Code in a real implementation should keep track of these - * constraints on the clock, and determine the highest minimum - * clock rate. It should iterate over each OPP and determine - * whether the OPP will result in a clock rate that would - * satisfy this constraint (and any other PM constraint in effect - * at that time). Once it finds the lowest-voltage OPP that - * meets those conditions, it should switch to it, or return - * an error if the code is not capable of doing so. - */ - - return 0; -} - -/* - * DSP Bridge-specific constraints - */ - -const struct omap_opp *omap_pm_dsp_get_opp_table(void) -{ - pr_debug("OMAP PM: DSP request for OPP table\n"); - - /* - * Return DSP frequency table here: The final item in the - * array should have .rate = .opp_id = 0. - */ - - return NULL; -} - -void omap_pm_dsp_set_min_opp(u8 opp_id) -{ - if (opp_id == 0) { - WARN_ON(1); - return; - } - - pr_debug("OMAP PM: DSP requests minimum VDD1 OPP to be %d\n", opp_id); - - /* - * - * For l-o dev tree, our VDD1 clk is keyed on OPP ID, so we - * can just test to see which is higher, the CPU's desired OPP - * ID or the DSP's desired OPP ID, and use whichever is - * highest. - * - * In CDP12.14+, the VDD1 OPP custom clock that controls the DSP - * rate is keyed on MPU speed, not the OPP ID. So we need to - * map the OPP ID to the MPU speed for use with clk_set_rate() - * if it is higher than the current OPP clock rate. - * - */ -} - - -u8 omap_pm_dsp_get_opp(void) -{ - pr_debug("OMAP PM: DSP requests current DSP OPP ID\n"); - - /* - * For l-o dev tree, call clk_get_rate() on VDD1 OPP clock - * - * CDP12.14+: - * Call clk_get_rate() on the OPP custom clock, map that to an - * OPP ID using the tables defined in board-*.c/chip-*.c files. - */ - - return 0; -} - -/* - * CPUFreq-originated constraint - * - * In the future, this should be handled by custom OPP clocktype - * functions. - */ - -struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void) -{ - pr_debug("OMAP PM: CPUFreq request for frequency table\n"); - - /* - * Return CPUFreq frequency table here: loop over - * all VDD1 clkrates, pull out the mpu_ck frequencies, build - * table - */ - - return NULL; -} - -void omap_pm_cpu_set_freq(unsigned long f) -{ - if (f == 0) { - WARN_ON(1); - return; - } - - pr_debug("OMAP PM: CPUFreq requests CPU frequency to be set to %lu\n", - f); - - /* - * For l-o dev tree, determine whether MPU freq or DSP OPP id - * freq is higher. Find the OPP ID corresponding to the - * higher frequency. Call clk_round_rate() and clk_set_rate() - * on the OPP custom clock. - * - * CDP should just be able to set the VDD1 OPP clock rate here. - */ -} - -unsigned long omap_pm_cpu_get_freq(void) -{ - pr_debug("OMAP PM: CPUFreq requests current CPU frequency\n"); - - /* - * Call clk_get_rate() on the mpu_ck. - */ - - return 0; -} - -/** - * omap_pm_enable_off_mode - notify OMAP PM that off-mode is enabled - * - * Intended for use only by OMAP PM core code to notify this layer - * that off mode has been enabled. - */ -void omap_pm_enable_off_mode(void) -{ - off_mode_enabled = true; -} - -/** - * omap_pm_disable_off_mode - notify OMAP PM that off-mode is disabled - * - * Intended for use only by OMAP PM core code to notify this layer - * that off mode has been disabled. - */ -void omap_pm_disable_off_mode(void) -{ - off_mode_enabled = false; -} - -/* - * Device context loss tracking - */ - -#ifdef CONFIG_ARCH_OMAP2PLUS - -int omap_pm_get_dev_context_loss_count(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - int count; - - if (WARN_ON(!dev)) - return -ENODEV; - - if (dev->parent == &omap_device_parent) { - count = omap_device_get_context_loss_count(pdev); - } else { - WARN_ONCE(off_mode_enabled, "omap_pm: using dummy context loss counter; device %s should be converted to omap_device", - dev_name(dev)); - - count = dummy_context_loss_counter; - - if (off_mode_enabled) { - count++; - /* - * Context loss count has to be a non-negative value. - * Clear the sign bit to get a value range from 0 to - * INT_MAX. - */ - count &= INT_MAX; - dummy_context_loss_counter = count; - } - } - - pr_debug("OMAP PM: context loss count for dev %s = %d\n", - dev_name(dev), count); - - return count; -} - -#else - -int omap_pm_get_dev_context_loss_count(struct device *dev) -{ - return dummy_context_loss_counter; -} - -#endif - -/* Should be called before clk framework init */ -int __init omap_pm_if_early_init(void) -{ - return 0; -} - -/* Must be called after clock framework is initialized */ -int __init omap_pm_if_init(void) -{ - return 0; -} - -void omap_pm_if_exit(void) -{ - /* Deallocate CPUFreq frequency table here */ -} - -- cgit v1.1 From 3452792f1a7702574e11f028e19a05c9440c4a36 Mon Sep 17 00:00:00 2001 From: Girish S G Date: Tue, 21 Jun 2011 13:10:18 -0500 Subject: OMAP: PM: force omap_pm_get_device_context_loss_count omap_pm_get_device_context_loss_count today tries to use the omap_device based context loss logic to report back to the driver in-order for the driver to optimally implement a save and restore. However, as discussed in: http://marc.info/?l=linux-omap&m=130814255217041&w=2 This is fraught with risk that the drivers at times may never get reliable values. Meanwhile, while the upstream discusses this, we choose the least risky path of reporting an incrementing context loss forcing the drivers to maybe unoptimally keep restoring context. This we ensure by preventing the rollover from ever reaching 0. [nm@ti.com: helped split the original patch] Signed-off-by: Nishanth Menon Signed-off-by: Girish S G --- arch/arm/plat-omap/omap-pm-interface.c | 56 +++++++++++----------------------- 1 file changed, 17 insertions(+), 39 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-omap/omap-pm-interface.c b/arch/arm/plat-omap/omap-pm-interface.c index f6f36bd..4a80205 100644 --- a/arch/arm/plat-omap/omap-pm-interface.c +++ b/arch/arm/plat-omap/omap-pm-interface.c @@ -25,7 +25,6 @@ #include static bool off_mode_enabled; -static int dummy_context_loss_counter; /* * Device-driver-originated constraints (via board-*.c files) @@ -304,53 +303,32 @@ void omap_pm_disable_off_mode(void) /* * Device context loss tracking + * WARNING: at this point we dont have a reliable context loss reporting + * mechanism. Instead, we ensure that we report context loss always. */ - -#ifdef CONFIG_ARCH_OMAP2PLUS - int omap_pm_get_dev_context_loss_count(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - int count; - - if (WARN_ON(!dev)) - return -ENODEV; - - if (dev->parent == &omap_device_parent) { - count = omap_device_get_context_loss_count(pdev); - } else { - WARN_ONCE(off_mode_enabled, "omap_pm: using dummy context loss counter; device %s should be converted to omap_device", - dev_name(dev)); - - count = dummy_context_loss_counter; - - if (off_mode_enabled) { - count++; - /* - * Context loss count has to be a non-negative value. - * Clear the sign bit to get a value range from 0 to - * INT_MAX. - */ - count &= INT_MAX; - dummy_context_loss_counter = count; - } - } + static u32 count = 1; - pr_debug("OMAP PM: context loss count for dev %s = %d\n", - dev_name(dev), count); + if (!dev) { + WARN_ON(1); + return -EINVAL; + }; - return count; -} + count++; -#else + /* + * Context loss count has to be a non-negative value. + * Clear the sign bit to get a value range from 0 to + * INT_MAX. Roll over to 1 + */ + count = (count & ~INT_MAX) ? 1 : count; -int omap_pm_get_dev_context_loss_count(struct device *dev) -{ - return dummy_context_loss_counter; + pr_debug("OMAP PM: returning context loss count for dev %s count %ul\n", + dev_name(dev), count); + return count; } -#endif - /* Should be called before clk framework init */ int __init omap_pm_if_early_init(void) { -- cgit v1.1 From df02c549e9e67f13caf774468a29e5f81ae5ace8 Mon Sep 17 00:00:00 2001 From: Girish S G Date: Tue, 21 Jun 2011 12:53:39 -0500 Subject: OMAP: PM: deprecate pm_qos wrappers omap_pm_set_max_mpu_wakeup_lat and omap_pm_set_max_sdma_lat are now deprecated Drivers are expected to use pm_qos infrastructure to directly set the latencies instead of using the wrapper functions. Note: This is not deprecating the interfaces so much as removing them but allowing existing code to compile. [nm@ti.com: helped split the original patch] Signed-off-by: Nishanth Menon Signed-off-by: Girish S G --- arch/arm/plat-omap/omap-pm-interface.c | 54 +++++----------------------------- arch/arm/plat-omap/omap-pm.c | 43 +++++---------------------- 2 files changed, 16 insertions(+), 81 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-omap/omap-pm-interface.c b/arch/arm/plat-omap/omap-pm-interface.c index 4a80205..ebd3eaa 100644 --- a/arch/arm/plat-omap/omap-pm-interface.c +++ b/arch/arm/plat-omap/omap-pm-interface.c @@ -28,34 +28,15 @@ static bool off_mode_enabled; /* * Device-driver-originated constraints (via board-*.c files) + * WARNING: Device drivers need to now use pm_qos directly. */ - int omap_pm_set_max_mpu_wakeup_lat(struct pm_qos_request_list **pmqos_req, long t) { - if (!pmqos_req || t < -1) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - }; - - if (t == -1) - pr_debug("OMAP PM: remove max MPU wakeup latency constraint\n"); - else - pr_debug("OMAP PM: add max MPU wakeup latency constraint:" - "t = %ld usec\n", t); - - /* - * For current Linux, this needs to map the MPU to a - * powerdomain, then go through the list of current max lat - * constraints on the MPU and find the smallest. If - * the latency constraint has changed, the code should - * recompute the state to enter for the next powerdomain - * state. - * - * TI CDP code can call constraint_set here. - */ + WARN(1, "Deprecated %s: Driver should use pm_qos to add request\n", + __func__); - return 0; + return -EINVAL; } int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, long r) @@ -116,32 +97,13 @@ int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, return 0; } +/* WARNING: Device drivers need to now use pm_qos directly. */ int omap_pm_set_max_sdma_lat(struct pm_qos_request_list **qos_request, long t) { - if (!qos_request || t < -1) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - }; - - if (t == -1) - pr_debug("OMAP PM: remove max DMA latency constraint:\n"); - else - pr_debug("OMAP PM: add max DMA latency constraint:" - "t = %ld usec\n", t); + WARN(1, "Deprecated %s: Driver should use pm_qos to add request\n", + __func__); - /* - * For current Linux PM QOS params, this code should scan the - * list of maximum CPU and DMA latencies and select the - * smallest, then set cpu_dma_latency pm_qos_param - * accordingly. - * - * For future Linux PM QOS params, with separate CPU and DMA - * latency params, this code should just set the dma_latency param. - * - * TI CDP code can call constraint_set here. - */ - - return 0; + return -EINVAL; } int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r) diff --git a/arch/arm/plat-omap/omap-pm.c b/arch/arm/plat-omap/omap-pm.c index a2ee551..f1d3a71 100644 --- a/arch/arm/plat-omap/omap-pm.c +++ b/arch/arm/plat-omap/omap-pm.c @@ -224,33 +224,17 @@ unlock: /* * Device-driver-originated constraints (via board-*.c files) + * WARNING: Device drivers need to now use pm_qos directly. */ - int omap_pm_set_max_mpu_wakeup_lat(struct pm_qos_request_list **qos_request, long t) { - if (!qos_request || t < -1) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - }; + WARN(1, "Deprecated %s: Driver should use pm_qos to add request\n", + __func__); - mutex_lock(&mpu_lat_mutex); - - if (t == -1) { - pm_qos_remove_request(*qos_request); - kfree(*qos_request); - *qos_request = NULL; - } else if (*qos_request == NULL) { - *qos_request = kzalloc(sizeof(struct pm_qos_request_list), GFP_KERNEL); - pm_qos_add_request(*qos_request, PM_QOS_CPU_DMA_LATENCY, t); - } else - pm_qos_update_request(*qos_request, t); - - mutex_unlock(&mpu_lat_mutex); - return 0; + return -EINVAL; } - int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, long r) { @@ -366,25 +350,14 @@ int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, return ret; } +/* WARNING: Device drivers need to now use pm_qos directly. */ int omap_pm_set_max_sdma_lat(struct pm_qos_request_list **qos_request, long t) { - if (!qos_request || t < -1) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - }; + WARN(1, "Deprecated %s: Driver should use pm_qos to add request\n", + __func__); - if (t == -1) { - pm_qos_remove_request(*qos_request); - kfree(*qos_request); - *qos_request = NULL; - } else if (*qos_request == NULL) { - *qos_request = kzalloc(sizeof(struct pm_qos_request_list), GFP_KERNEL); - pm_qos_add_request(*qos_request, PM_QOS_CPU_DMA_LATENCY, t); - } else - pm_qos_update_request(*qos_request, t); - - return 0; + return -EINVAL; } int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r) -- cgit v1.1 From 299e10125d76e570a0aeb2d8506f14368730b4c7 Mon Sep 17 00:00:00 2001 From: Girish S G Date: Sat, 18 Jun 2011 16:49:34 -0500 Subject: OMAP: PM: deprecate functions for which DVFS and OPP can help The following functions should not be used by drivers anymore. omap_pm_dsp_get_opp_table omap_pm_dsp_set_min_opp omap_pm_dsp_get_opp omap_pm_cpu_get_freq_table omap_pm_cpu_set_freq omap_pm_cpu_get_freq omap_pm_set_min_mpu_freq These functions are now made non-functional now that we have OPP and DVFS layers to do the same. Note: This is not deprecating the interfaces so much as removing them but allowing existing code to compile. [nm@ti.com: helped split the original patch] Signed-off-by: Nishanth Menon Signed-off-by: Girish S G --- arch/arm/plat-omap/omap-pm-interface.c | 107 +++++-------------------- arch/arm/plat-omap/omap-pm.c | 141 ++++++--------------------------- 2 files changed, 43 insertions(+), 205 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-omap/omap-pm-interface.c b/arch/arm/plat-omap/omap-pm-interface.c index ebd3eaa..2fc09b0 100644 --- a/arch/arm/plat-omap/omap-pm-interface.c +++ b/arch/arm/plat-omap/omap-pm-interface.c @@ -108,84 +108,37 @@ int omap_pm_set_max_sdma_lat(struct pm_qos_request_list **qos_request, long t) int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r) { - if (!dev || !c || r < 0) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - } - - if (r == 0) - pr_debug("OMAP PM: remove min clk rate constraint: " - "dev %s\n", dev_name(dev)); - else - pr_debug("OMAP PM: add min clk rate constraint: " - "dev %s, rate = %ld Hz\n", dev_name(dev), r); - - /* - * Code in a real implementation should keep track of these - * constraints on the clock, and determine the highest minimum - * clock rate. It should iterate over each OPP and determine - * whether the OPP will result in a clock rate that would - * satisfy this constraint (and any other PM constraint in effect - * at that time). Once it finds the lowest-voltage OPP that - * meets those conditions, it should switch to it, or return - * an error if the code is not capable of doing so. - */ + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); - return 0; + return -EINVAL; } /* * DSP Bridge-specific constraints + * WARNING: Device drivers need to now use opp layer/omap_device_scale directly. */ - const struct omap_opp *omap_pm_dsp_get_opp_table(void) { - pr_debug("OMAP PM: DSP request for OPP table\n"); - - /* - * Return DSP frequency table here: The final item in the - * array should have .rate = .opp_id = 0. - */ + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); - return NULL; + return ERR_PTR(-EINVAL); } void omap_pm_dsp_set_min_opp(u8 opp_id) { - if (opp_id == 0) { - WARN_ON(1); - return; - } - - pr_debug("OMAP PM: DSP requests minimum VDD1 OPP to be %d\n", opp_id); + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); - /* - * - * For l-o dev tree, our VDD1 clk is keyed on OPP ID, so we - * can just test to see which is higher, the CPU's desired OPP - * ID or the DSP's desired OPP ID, and use whichever is - * highest. - * - * In CDP12.14+, the VDD1 OPP custom clock that controls the DSP - * rate is keyed on MPU speed, not the OPP ID. So we need to - * map the OPP ID to the MPU speed for use with clk_set_rate() - * if it is higher than the current OPP clock rate. - * - */ + return; } u8 omap_pm_dsp_get_opp(void) { - pr_debug("OMAP PM: DSP requests current DSP OPP ID\n"); - - /* - * For l-o dev tree, call clk_get_rate() on VDD1 OPP clock - * - * CDP12.14+: - * Call clk_get_rate() on the OPP custom clock, map that to an - * OPP ID using the tables defined in board-*.c/chip-*.c files. - */ + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); return 0; } @@ -199,44 +152,24 @@ u8 omap_pm_dsp_get_opp(void) struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void) { - pr_debug("OMAP PM: CPUFreq request for frequency table\n"); - - /* - * Return CPUFreq frequency table here: loop over - * all VDD1 clkrates, pull out the mpu_ck frequencies, build - * table - */ + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); - return NULL; + return ERR_PTR(-EINVAL); } void omap_pm_cpu_set_freq(unsigned long f) { - if (f == 0) { - WARN_ON(1); - return; - } - - pr_debug("OMAP PM: CPUFreq requests CPU frequency to be set to %lu\n", - f); + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); - /* - * For l-o dev tree, determine whether MPU freq or DSP OPP id - * freq is higher. Find the OPP ID corresponding to the - * higher frequency. Call clk_round_rate() and clk_set_rate() - * on the OPP custom clock. - * - * CDP should just be able to set the VDD1 OPP clock rate here. - */ + return; } unsigned long omap_pm_cpu_get_freq(void) { - pr_debug("OMAP PM: CPUFreq requests current CPU frequency\n"); - - /* - * Call clk_get_rate() on the mpu_ck. - */ + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); return 0; } diff --git a/arch/arm/plat-omap/omap-pm.c b/arch/arm/plat-omap/omap-pm.c index f1d3a71..d98ded9 100644 --- a/arch/arm/plat-omap/omap-pm.c +++ b/arch/arm/plat-omap/omap-pm.c @@ -362,84 +362,36 @@ int omap_pm_set_max_sdma_lat(struct pm_qos_request_list **qos_request, int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r) { - if (!dev || !c || r < 0) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - } - - if (r == 0) - pr_debug("OMAP PM: remove min clk rate constraint: " - "dev %s\n", dev_name(dev)); - else - pr_debug("OMAP PM: add min clk rate constraint: " - "dev %s, rate = %ld Hz\n", dev_name(dev), r); - - /* - * Code in a real implementation should keep track of these - * constraints on the clock, and determine the highest minimum - * clock rate. It should iterate over each OPP and determine - * whether the OPP will result in a clock rate that would - * satisfy this constraint (and any other PM constraint in effect - * at that time). Once it finds the lowest-voltage OPP that - * meets those conditions, it should switch to it, or return - * an error if the code is not capable of doing so. - */ - - return 0; + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); + return -EINVAL; } /* * DSP Bridge-specific constraints + * WARNING: Device drivers need to now use opp layer/omap_device_scale directly. */ - const struct omap_opp *omap_pm_dsp_get_opp_table(void) { - pr_debug("OMAP PM: DSP request for OPP table\n"); - - /* - * Return DSP frequency table here: The final item in the - * array should have .rate = .opp_id = 0. - */ + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); - return NULL; + return ERR_PTR(-EINVAL); } void omap_pm_dsp_set_min_opp(u8 opp_id) { - if (opp_id == 0) { - WARN_ON(1); - return; - } - - pr_debug("OMAP PM: DSP requests minimum VDD1 OPP to be %d\n", opp_id); + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); - /* - * - * For l-o dev tree, our VDD1 clk is keyed on OPP ID, so we - * can just test to see which is higher, the CPU's desired OPP - * ID or the DSP's desired OPP ID, and use whichever is - * highest. - * - * In CDP12.14+, the VDD1 OPP custom clock that controls the DSP - * rate is keyed on MPU speed, not the OPP ID. So we need to - * map the OPP ID to the MPU speed for use with clk_set_rate() - * if it is higher than the current OPP clock rate. - * - */ + return; } u8 omap_pm_dsp_get_opp(void) { - pr_debug("OMAP PM: DSP requests current DSP OPP ID\n"); - - /* - * For l-o dev tree, call clk_get_rate() on VDD1 OPP clock - * - * CDP12.14+: - * Call clk_get_rate() on the OPP custom clock, map that to an - * OPP ID using the tables defined in board-*.c/chip-*.c files. - */ + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); return 0; } @@ -453,44 +405,24 @@ u8 omap_pm_dsp_get_opp(void) struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void) { - pr_debug("OMAP PM: CPUFreq request for frequency table\n"); - - /* - * Return CPUFreq frequency table here: loop over - * all VDD1 clkrates, pull out the mpu_ck frequencies, build - * table - */ + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); - return NULL; + return ERR_PTR(-EINVAL); } void omap_pm_cpu_set_freq(unsigned long f) { - if (f == 0) { - WARN_ON(1); - return; - } - - pr_debug("OMAP PM: CPUFreq requests CPU frequency to be set to %lu\n", - f); + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); - /* - * For l-o dev tree, determine whether MPU freq or DSP OPP id - * freq is higher. Find the OPP ID corresponding to the - * higher frequency. Call clk_round_rate() and clk_set_rate() - * on the OPP custom clock. - * - * CDP should just be able to set the VDD1 OPP clock rate here. - */ + return; } unsigned long omap_pm_cpu_get_freq(void) { - pr_debug("OMAP PM: CPUFreq requests current CPU frequency\n"); - - /* - * Call clk_get_rate() on the mpu_ck. - */ + WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", + __func__); return 0; } @@ -567,37 +499,10 @@ void omap_pm_if_exit(void) int omap_pm_set_min_mpu_freq(struct device *dev, unsigned long f) { + WARN(1, "Deprecated %s: Driver should NOT use this function\n", + __func__); - int ret = 0; - struct device *mpu_dev; - - if (!dev) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - } - - mutex_lock(&mpu_tput_mutex); - - mpu_dev = omap2_get_mpuss_device(); - if (!mpu_dev) { - pr_err("Unable to get MPU device pointer"); - ret = -EINVAL; - goto unlock; - } - - - /* Rescale the frequency if a change is detected with - * the new constraint. - */ - WARN(1, "OMAP PM: %s: constraint not called, needs DVFS", __func__); -#if 0 - ret = omap_device_set_rate(dev, mpu_dev, f); -#endif - if (ret) - pr_err("Unable to set MPU frequency to %ld\n", f); + return -EINVAL; -unlock: - mutex_unlock(&mpu_tput_mutex); - return ret; } EXPORT_SYMBOL(omap_pm_set_min_mpu_freq); -- cgit v1.1 From ef1f8845e5336d02317aa6368c8e1b317fa4abe1 Mon Sep 17 00:00:00 2001 From: Girish S G Date: Sat, 18 Jun 2011 17:09:06 -0500 Subject: OMAP: PM: make bus_tput_init static and init This function is used only in the context of omap-pm and is used only during initialization phase. There is no reason to expose this. [nm@ti.com: helped split the original patch] Signed-off-by: Nishanth Menon Signed-off-by: Girish S G --- arch/arm/plat-omap/omap-pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-omap/omap-pm.c b/arch/arm/plat-omap/omap-pm.c index d98ded9..121e2ed 100644 --- a/arch/arm/plat-omap/omap-pm.c +++ b/arch/arm/plat-omap/omap-pm.c @@ -118,7 +118,7 @@ static struct users *get_user(void) * Returns 0 on sucess, else returns EINVAL if memory * allocation fails. */ -int omap_bus_tput_init(void) +static int __init omap_bus_tput_init(void) { bus_tput = kmalloc(sizeof(struct interconnect_tput), GFP_KERNEL); if (!bus_tput) { -- cgit v1.1 From 9b38f09adc34bcba4c63cbd6bc1942bec29c04d8 Mon Sep 17 00:00:00 2001 From: Girish S G Date: Sat, 18 Jun 2011 17:35:42 -0500 Subject: OMAP: PM: merge omap-pm-interface and omap-pm files Since we now have a lot of redundant code between omap-pm.c and omap-pm-interface.c, we can conslidate the two and use omap-pm-interface.c as the mainfile. omap-pm.c now contains only the functionality needed when CONFIG_OMAP_PM=y. A shared header is introduced to ensure that the function prototypes remain consistent. To maintain git history, we will rename omap-pm.c to omap-pm-helper.c in a subsequent patch [nm@ti.com: helped split the original patch] Signed-off-by: Nishanth Menon Signed-off-by: Girish S G --- arch/arm/plat-omap/Makefile | 2 +- arch/arm/plat-omap/omap-pm-helper.h | 40 ++++++ arch/arm/plat-omap/omap-pm-interface.c | 42 +++---- arch/arm/plat-omap/omap-pm.c | 216 ++------------------------------- 4 files changed, 72 insertions(+), 228 deletions(-) create mode 100644 arch/arm/plat-omap/omap-pm-helper.h (limited to 'arch/arm') diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index df0824a..1f75f18 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -32,4 +32,4 @@ obj-y += $(i2c-omap-m) $(i2c-omap-y) obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-interface.o -obj-$(CONFIG_OMAP_PM) += omap-pm.o +obj-$(CONFIG_OMAP_PM) += omap-pm-interface.o omap-pm.o diff --git a/arch/arm/plat-omap/omap-pm-helper.h b/arch/arm/plat-omap/omap-pm-helper.h new file mode 100644 index 0000000..9c4b5d7 --- /dev/null +++ b/arch/arm/plat-omap/omap-pm-helper.h @@ -0,0 +1,40 @@ +/* + * OMAP PM interface helpers + * + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * Nishanth Menon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __OMAP_PM_HELPER_INTERFACE_H__ +#define __OMAP_PM_HELPER_INTERFACE_H__ + +#ifdef CONFIG_OMAP_PM +int omap_pm_set_min_bus_tput_helper(struct device *dev, u8 agent_id, long r); +int omap_pm_set_max_dev_wakeup_lat_helper(struct device *req_dev, + struct device *dev, long t); +int __init omap_pm_if_init_helper(void); + +#else +static inline int omap_pm_set_min_bus_tput_helper(struct device *dev, + u8 agent_id, long r) +{ + return 0; +} + +static inline int omap_pm_set_max_dev_wakeup_lat_helper(struct device *req_dev, + struct device *dev, long t) +{ + return 0; +} + +static inline int omap_pm_if_init_helper(void) +{ + return 0; +} +#endif /* CONFIG_OMAP_PM */ + +#endif /* __OMAP_PM_HELPER_INTERFACE_H__ */ diff --git a/arch/arm/plat-omap/omap-pm-interface.c b/arch/arm/plat-omap/omap-pm-interface.c index 2fc09b0..c677483 100644 --- a/arch/arm/plat-omap/omap-pm-interface.c +++ b/arch/arm/plat-omap/omap-pm-interface.c @@ -24,6 +24,8 @@ #include #include +#include "omap-pm-helper.h" + static bool off_mode_enabled; /* @@ -41,13 +43,14 @@ int omap_pm_set_max_mpu_wakeup_lat(struct pm_qos_request_list **pmqos_req, int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, long r) { + int ret; if (!dev || (agent_id != OCP_INITIATOR_AGENT && agent_id != OCP_TARGET_AGENT)) { WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); return -EINVAL; }; - if (r == 0) + if (r == -1) pr_debug("OMAP PM: remove min bus tput constraint: " "dev %s for agent_id %d\n", dev_name(dev), agent_id); else @@ -55,20 +58,15 @@ int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, long r) "dev %s for agent_id %d: rate %ld KiB\n", dev_name(dev), agent_id, r); - /* - * This code should model the interconnect and compute the - * required clock frequency, convert that to a VDD2 OPP ID, then - * set the VDD2 OPP appropriately. - * - * TI CDP code can call constraint_set here on the VDD2 OPP. - */ + ret = omap_pm_set_min_bus_tput_helper(dev, agent_id, r); - return 0; + return ret; } int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, long t) { + int ret; if (!req_dev || !dev || t < -1) { WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); return -EINVAL; @@ -81,20 +79,9 @@ int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, pr_debug("OMAP PM: add max device latency constraint: " "dev %s, t = %ld usec\n", dev_name(dev), t); - /* - * For current Linux, this needs to map the device to a - * powerdomain, then go through the list of current max lat - * constraints on that powerdomain and find the smallest. If - * the latency constraint has changed, the code should - * recompute the state to enter for the next powerdomain - * state. Conceivably, this code should also determine - * whether to actually disable the device clocks or not, - * depending on how long it takes to re-enable the clocks. - * - * TI CDP code can call constraint_set here. - */ + ret = omap_pm_set_max_dev_wakeup_lat_helper(req_dev, dev, t); - return 0; + return ret; } /* WARNING: Device drivers need to now use pm_qos directly. */ @@ -134,6 +121,15 @@ void omap_pm_dsp_set_min_opp(u8 opp_id) return; } +int omap_pm_set_min_mpu_freq(struct device *dev, unsigned long f) +{ + WARN(1, "Deprecated %s: Driver should NOT use this function\n", + __func__); + + return -EINVAL; + +} +EXPORT_SYMBOL(omap_pm_set_min_mpu_freq); u8 omap_pm_dsp_get_opp(void) { @@ -233,7 +229,7 @@ int __init omap_pm_if_early_init(void) /* Must be called after clock framework is initialized */ int __init omap_pm_if_init(void) { - return 0; + return omap_pm_if_init_helper(); } void omap_pm_if_exit(void) diff --git a/arch/arm/plat-omap/omap-pm.c b/arch/arm/plat-omap/omap-pm.c index 121e2ed..a6d4aa6 100644 --- a/arch/arm/plat-omap/omap-pm.c +++ b/arch/arm/plat-omap/omap-pm.c @@ -1,7 +1,7 @@ /* * omap-pm.c - OMAP power management interface * - * Copyright (C) 2008-2010 Texas Instruments, Inc. + * Copyright (C) 2008-2011 Texas Instruments, Inc. * Copyright (C) 2008-2009 Nokia Corporation * Vishwanath BS * @@ -27,6 +27,7 @@ #include #include #include "../mach-omap2/powerdomain.h" +#include "omap-pm-helper.h" struct omap_opp *dsp_opps; struct omap_opp *mpu_opps; @@ -36,8 +37,6 @@ static DEFINE_MUTEX(bus_tput_mutex); static DEFINE_MUTEX(mpu_tput_mutex); static DEFINE_MUTEX(mpu_lat_mutex); -static bool off_mode_enabled; - /* Used to model a Interconnect Throughput */ static struct interconnect_tput { /* Total no of users at any point of interconnect */ @@ -222,33 +221,14 @@ unlock: return ret; } -/* - * Device-driver-originated constraints (via board-*.c files) - * WARNING: Device drivers need to now use pm_qos directly. - */ -int omap_pm_set_max_mpu_wakeup_lat(struct pm_qos_request_list **qos_request, - long t) -{ - WARN(1, "Deprecated %s: Driver should use pm_qos to add request\n", - __func__); - - return -EINVAL; -} - -int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, long r) +int omap_pm_set_min_bus_tput_helper(struct device *dev, u8 agent_id, long r) { - int ret; + int ret = 0; struct device *l3_dev; static struct device dummy_l3_dev; unsigned long target_level = 0; - if (!dev || (agent_id != OCP_INITIATOR_AGENT && - agent_id != OCP_TARGET_AGENT)) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - }; - mutex_lock(&bus_tput_mutex); l3_dev = omap2_get_l3_device(); @@ -257,17 +237,11 @@ int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, long r) ret = -EINVAL; goto unlock; } - if (r == -1) { - pr_debug("OMAP PM: remove min bus tput constraint for: " - "interconnect dev %s for agent_id %d\n", dev_name(dev), - agent_id); + + if (r == -1) target_level = remove_req_tput(dev); - } else { - pr_debug("OMAP PM: add min bus tput constraint for: " - "interconnect dev %s for agent_id %d: rate %ld KiB\n", - dev_name(dev), agent_id, r); + else target_level = add_req_tput(dev, r); - } /* Convert the throughput(in KiB/s) into Hz. */ target_level = (target_level * 1000)/4; @@ -284,8 +258,8 @@ unlock: return ret; } -int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, - long t) +int omap_pm_set_max_dev_wakeup_lat_helper(struct device *req_dev, + struct device *dev, long t) { struct omap_device *odev; struct powerdomain *pwrdm_dev; @@ -322,167 +296,16 @@ int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, return -EINVAL; } - if (t == -1) { - pr_debug("OMAP PM: remove max device latency constraint: " - "dev %s, pwrdm %s, req by %s\n", dev_name(dev), - pwrdm_dev->name, dev_name(req_dev)); + if (t == -1) ret = pwrdm_wakeuplat_release_constraint(pwrdm_dev, req_dev); - } else { - pr_debug("OMAP PM: add max device latency constraint: " - "dev %s, t = %ld usec, pwrdm %s, req by %s\n", - dev_name(dev), t, pwrdm_dev->name, dev_name(req_dev)); + else ret = pwrdm_wakeuplat_set_constraint(pwrdm_dev, req_dev, t); - } - - /* - * For current Linux, this needs to map the device to a - * powerdomain, then go through the list of current max lat - * constraints on that powerdomain and find the smallest. If - * the latency constraint has changed, the code should - * recompute the state to enter for the next powerdomain - * state. Conceivably, this code should also determine - * whether to actually disable the device clocks or not, - * depending on how long it takes to re-enable the clocks. - * - * TI CDP code can call constraint_set here. - */ return ret; } -/* WARNING: Device drivers need to now use pm_qos directly. */ -int omap_pm_set_max_sdma_lat(struct pm_qos_request_list **qos_request, - long t) -{ - WARN(1, "Deprecated %s: Driver should use pm_qos to add request\n", - __func__); - - return -EINVAL; -} - -int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r) -{ - WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", - __func__); - return -EINVAL; -} - -/* - * DSP Bridge-specific constraints - * WARNING: Device drivers need to now use opp layer/omap_device_scale directly. - */ -const struct omap_opp *omap_pm_dsp_get_opp_table(void) -{ - WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", - __func__); - - return ERR_PTR(-EINVAL); -} - -void omap_pm_dsp_set_min_opp(u8 opp_id) -{ - WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", - __func__); - - return; -} - - -u8 omap_pm_dsp_get_opp(void) -{ - WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", - __func__); - - return 0; -} - -/* - * CPUFreq-originated constraint - * - * In the future, this should be handled by custom OPP clocktype - * functions. - */ - -struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void) -{ - WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", - __func__); - - return ERR_PTR(-EINVAL); -} - -void omap_pm_cpu_set_freq(unsigned long f) -{ - WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", - __func__); - - return; -} - -unsigned long omap_pm_cpu_get_freq(void) -{ - WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", - __func__); - - return 0; -} - -/** - * omap_pm_enable_off_mode - notify OMAP PM that off-mode is enabled - * - * Intended for use only by OMAP PM core code to notify this layer - * that off mode has been enabled. - */ -void omap_pm_enable_off_mode(void) -{ - off_mode_enabled = true; -} - -/** - * omap_pm_disable_off_mode - notify OMAP PM that off-mode is disabled - * - * Intended for use only by OMAP PM core code to notify this layer - * that off mode has been disabled. - */ -void omap_pm_disable_off_mode(void) -{ - off_mode_enabled = false; -} - -/* - * Device context loss tracking - */ - -int omap_pm_get_dev_context_loss_count(struct device *dev) -{ - static u32 counter = 1; - - if (!dev) { - WARN_ON(1); - return -EINVAL; - }; - - pr_debug("OMAP PM: returning context loss count for dev %s\n", - dev_name(dev)); - - /* - * Map the device to the powerdomain. Return the powerdomain - * off counter. - */ - - /* Let the counter roll-over: its for test only */ - return counter++; -} - - -/* Should be called before clk framework init */ -int __init omap_pm_if_early_init() -{ - return 0; -} - /* Must be called after clock framework is initialized */ -int __init omap_pm_if_init(void) +int __init omap_pm_if_init_helper(void) { int ret; ret = omap_bus_tput_init(); @@ -491,18 +314,3 @@ int __init omap_pm_if_init(void) " bandwidth users list\n"); return ret; } - -void omap_pm_if_exit(void) -{ - /* Deallocate CPUFreq frequency table here */ -} - -int omap_pm_set_min_mpu_freq(struct device *dev, unsigned long f) -{ - WARN(1, "Deprecated %s: Driver should NOT use this function\n", - __func__); - - return -EINVAL; - -} -EXPORT_SYMBOL(omap_pm_set_min_mpu_freq); -- cgit v1.1 From f00763bf138ec273a31c68c76dc22e30ad7f1a8d Mon Sep 17 00:00:00 2001 From: Girish S G Date: Sat, 18 Jun 2011 18:00:09 -0500 Subject: OMAP: PM: rename omap-pm to omap-pm-helper omap-pm does not retain any of it's independent functionality. It is now a helper for omap-pm-interface.c. Hence, rename it to adequately reflect the new role it plays now. [nm@ti.com: helped split the original patch] Signed-off-by: Nishanth Menon Signed-off-by: Girish S G --- arch/arm/plat-omap/Makefile | 2 +- arch/arm/plat-omap/omap-pm-helper.c | 316 ++++++++++++++++++++++++++++++++++++ arch/arm/plat-omap/omap-pm.c | 316 ------------------------------------ 3 files changed, 317 insertions(+), 317 deletions(-) create mode 100644 arch/arm/plat-omap/omap-pm-helper.c delete mode 100644 arch/arm/plat-omap/omap-pm.c (limited to 'arch/arm') diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index 1f75f18..f3ab483 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -32,4 +32,4 @@ obj-y += $(i2c-omap-m) $(i2c-omap-y) obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-interface.o -obj-$(CONFIG_OMAP_PM) += omap-pm-interface.o omap-pm.o +obj-$(CONFIG_OMAP_PM) += omap-pm-interface.o omap-pm-helper.o diff --git a/arch/arm/plat-omap/omap-pm-helper.c b/arch/arm/plat-omap/omap-pm-helper.c new file mode 100644 index 0000000..a6d4aa6 --- /dev/null +++ b/arch/arm/plat-omap/omap-pm-helper.c @@ -0,0 +1,316 @@ +/* + * omap-pm.c - OMAP power management interface + * + * Copyright (C) 2008-2011 Texas Instruments, Inc. + * Copyright (C) 2008-2009 Nokia Corporation + * Vishwanath BS + * + * This code is based on plat-omap/omap-pm-noop.c. + * + * Interface developed by (in alphabetical order): + * Karthik Dasu, Tony Lindgren, Rajendra Nayak, Sakari Poussa, Veeramanikandan + * Raju, Anand Sawant, Igor Stoppa, Paul Walmsley, Richard Woodruff + */ + +#undef DEBUG + +#include +#include +#include +#include +#include +#include +#include + +/* Interface documentation is in mach/omap-pm.h */ +#include +#include +#include +#include "../mach-omap2/powerdomain.h" +#include "omap-pm-helper.h" + +struct omap_opp *dsp_opps; +struct omap_opp *mpu_opps; +struct omap_opp *l3_opps; + +static DEFINE_MUTEX(bus_tput_mutex); +static DEFINE_MUTEX(mpu_tput_mutex); +static DEFINE_MUTEX(mpu_lat_mutex); + +/* Used to model a Interconnect Throughput */ +static struct interconnect_tput { + /* Total no of users at any point of interconnect */ + u8 no_of_users; + /* List of all the current users for interconnect */ + struct list_head users_list; + struct list_head node; + /* Protect interconnect throughput */ + struct mutex throughput_mutex; + /* Target level for interconnect throughput */ + unsigned long target_level; + +} *bus_tput; + +/* Used to represent a user of a interconnect throughput */ +struct users { + /* Device pointer used to uniquely identify the user */ + struct device *dev; + struct list_head node; + /* Current level as requested for interconnect throughput by the user */ + u32 level; +}; + +/* Private/Internal Functions */ + +/** + * user_lookup - look up a user by its device pointer, return a pointer + * @dev: The device to be looked up + * + * Looks for a interconnect user by its device pointer. Returns a + * pointer to + * the struct users if found, else returns NULL. + **/ + +static struct users *user_lookup(struct device *dev) +{ + struct users *usr, *tmp_usr; + + usr = NULL; + list_for_each_entry(tmp_usr, &bus_tput->users_list, node) { + if (tmp_usr->dev == dev) { + usr = tmp_usr; + break; + } + } + + return usr; +} + +/** + * get_user - gets a new users_list struct dynamically + * + * This function allocates dynamcially the user node + * Returns a pointer to users struct on success. On dynamic allocation + * failure + * returns a ERR_PTR(-ENOMEM). + **/ + +static struct users *get_user(void) +{ + struct users *user; + + user = kmalloc(sizeof(struct users), GFP_KERNEL); + if (!user) { + pr_err("%s FATAL ERROR: kmalloc " + "failed\n", __func__); + return ERR_PTR(-ENOMEM); + } + return user; +} + + +/** + * omap_bus_tput_init - Initializes the interconnect throughput + * userlist + * Allocates memory for global throughput variable dynamically. + * Intializes Userlist, no. of users and throughput target level. + * Returns 0 on sucess, else returns EINVAL if memory + * allocation fails. + */ +static int __init omap_bus_tput_init(void) +{ + bus_tput = kmalloc(sizeof(struct interconnect_tput), GFP_KERNEL); + if (!bus_tput) { + pr_err("%s FATAL ERROR: kmalloc failed\n", __func__); + return -EINVAL; + } + INIT_LIST_HEAD(&bus_tput->users_list); + mutex_init(&bus_tput->throughput_mutex); + bus_tput->no_of_users = 0; + bus_tput->target_level = 0; + return 0; +} + + +/** + * add_req_tput - Request for a required level by a device + * @dev: Uniquely identifes the caller + * @level: The requested level for the interconnect bandwidth in KiB/s + * + * This function recomputes the target level of the interconnect + * bandwidth + * based on the level requested by all the users. + * Multiple calls to this function by the same device will + * replace the previous level requested + * Returns the updated level of interconnect throughput. + * In case of Invalid dev or user pointer, it returns 0. + */ +static unsigned long add_req_tput(struct device *dev, unsigned long level) +{ + int ret; + struct users *user; + + if (!dev) { + pr_err("Invalid dev pointer\n"); + ret = 0; + } + mutex_lock(&bus_tput->throughput_mutex); + user = user_lookup(dev); + if (user == NULL) { + user = get_user(); + if (IS_ERR(user)) { + pr_err("Couldn't get user from the list to" + "add new throughput constraint"); + ret = 0; + goto unlock; + } + bus_tput->target_level += level; + bus_tput->no_of_users++; + user->dev = dev; + list_add(&user->node, &bus_tput->users_list); + user->level = level; + } else { + bus_tput->target_level -= user->level; + bus_tput->target_level += level; + user->level = level; + } + ret = bus_tput->target_level; +unlock: + mutex_unlock(&bus_tput->throughput_mutex); + return ret; +} + + +/** + * remove_req_tput - Release a previously requested level of + * a throughput level for interconnect + * @dev: Device pointer to dev + * + * This function recomputes the target level of the interconnect + * throughput after removing + * the level requested by the user. + * Returns 0, if the dev structure is invalid + * else returns modified interconnect throughput rate. + */ +static unsigned long remove_req_tput(struct device *dev) +{ + struct users *user; + int found = 0; + int ret; + + mutex_lock(&bus_tput->throughput_mutex); + list_for_each_entry(user, &bus_tput->users_list, node) { + if (user->dev == dev) { + found = 1; + break; + } + } + if (!found) { + /* No such user exists */ + pr_err("Invalid Device Structure\n"); + ret = 0; + goto unlock; + } + bus_tput->target_level -= user->level; + bus_tput->no_of_users--; + list_del(&user->node); + kfree(user); + ret = bus_tput->target_level; +unlock: + mutex_unlock(&bus_tput->throughput_mutex); + return ret; +} + +int omap_pm_set_min_bus_tput_helper(struct device *dev, u8 agent_id, long r) +{ + + int ret = 0; + struct device *l3_dev; + static struct device dummy_l3_dev; + unsigned long target_level = 0; + + mutex_lock(&bus_tput_mutex); + + l3_dev = omap2_get_l3_device(); + if (!l3_dev) { + pr_err("Unable to get l3 device pointer"); + ret = -EINVAL; + goto unlock; + } + + if (r == -1) + target_level = remove_req_tput(dev); + else + target_level = add_req_tput(dev, r); + + /* Convert the throughput(in KiB/s) into Hz. */ + target_level = (target_level * 1000)/4; + + WARN(1, "OMAP PM: %s: constraint not called, needs DVFS", __func__); +#if 0 + ret = omap_device_scale(&dummy_l3_dev, l3_dev, target_level); +#endif + if (ret) + pr_err("Unable to change level for interconnect bandwidth to %ld\n", + target_level); +unlock: + mutex_unlock(&bus_tput_mutex); + return ret; +} + +int omap_pm_set_max_dev_wakeup_lat_helper(struct device *req_dev, + struct device *dev, long t) +{ + struct omap_device *odev; + struct powerdomain *pwrdm_dev; + struct platform_device *pdev; + int ret = 0; + + if (!req_dev || !dev || t < -1) { + WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); + return -EINVAL; + }; + + /* Look for the devices Power Domain */ + pdev = container_of(dev, struct platform_device, dev); + + /* Try to catch non platform devices. */ + if (pdev->name == NULL) { + pr_err("OMAP-PM: Error: platform device not valid\n"); + return -EINVAL; + } + + odev = to_omap_device(pdev); + if (odev) { + pwrdm_dev = omap_device_get_pwrdm(odev); + } else { + pr_err("OMAP-PM: Error: Could not find omap_device " + "for %s\n", pdev->name); + return -EINVAL; + } + + /* Catch devices with undefined powerdomains. */ + if (!pwrdm_dev) { + pr_err("OMAP-PM: Error: could not find parent " + "powerdomain for %s\n", pdev->name); + return -EINVAL; + } + + if (t == -1) + ret = pwrdm_wakeuplat_release_constraint(pwrdm_dev, req_dev); + else + ret = pwrdm_wakeuplat_set_constraint(pwrdm_dev, req_dev, t); + + return ret; +} + +/* Must be called after clock framework is initialized */ +int __init omap_pm_if_init_helper(void) +{ + int ret; + ret = omap_bus_tput_init(); + if (ret) + pr_err("Failed to initialize interconnect" + " bandwidth users list\n"); + return ret; +} diff --git a/arch/arm/plat-omap/omap-pm.c b/arch/arm/plat-omap/omap-pm.c deleted file mode 100644 index a6d4aa6..0000000 --- a/arch/arm/plat-omap/omap-pm.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - * omap-pm.c - OMAP power management interface - * - * Copyright (C) 2008-2011 Texas Instruments, Inc. - * Copyright (C) 2008-2009 Nokia Corporation - * Vishwanath BS - * - * This code is based on plat-omap/omap-pm-noop.c. - * - * Interface developed by (in alphabetical order): - * Karthik Dasu, Tony Lindgren, Rajendra Nayak, Sakari Poussa, Veeramanikandan - * Raju, Anand Sawant, Igor Stoppa, Paul Walmsley, Richard Woodruff - */ - -#undef DEBUG - -#include -#include -#include -#include -#include -#include -#include - -/* Interface documentation is in mach/omap-pm.h */ -#include -#include -#include -#include "../mach-omap2/powerdomain.h" -#include "omap-pm-helper.h" - -struct omap_opp *dsp_opps; -struct omap_opp *mpu_opps; -struct omap_opp *l3_opps; - -static DEFINE_MUTEX(bus_tput_mutex); -static DEFINE_MUTEX(mpu_tput_mutex); -static DEFINE_MUTEX(mpu_lat_mutex); - -/* Used to model a Interconnect Throughput */ -static struct interconnect_tput { - /* Total no of users at any point of interconnect */ - u8 no_of_users; - /* List of all the current users for interconnect */ - struct list_head users_list; - struct list_head node; - /* Protect interconnect throughput */ - struct mutex throughput_mutex; - /* Target level for interconnect throughput */ - unsigned long target_level; - -} *bus_tput; - -/* Used to represent a user of a interconnect throughput */ -struct users { - /* Device pointer used to uniquely identify the user */ - struct device *dev; - struct list_head node; - /* Current level as requested for interconnect throughput by the user */ - u32 level; -}; - -/* Private/Internal Functions */ - -/** - * user_lookup - look up a user by its device pointer, return a pointer - * @dev: The device to be looked up - * - * Looks for a interconnect user by its device pointer. Returns a - * pointer to - * the struct users if found, else returns NULL. - **/ - -static struct users *user_lookup(struct device *dev) -{ - struct users *usr, *tmp_usr; - - usr = NULL; - list_for_each_entry(tmp_usr, &bus_tput->users_list, node) { - if (tmp_usr->dev == dev) { - usr = tmp_usr; - break; - } - } - - return usr; -} - -/** - * get_user - gets a new users_list struct dynamically - * - * This function allocates dynamcially the user node - * Returns a pointer to users struct on success. On dynamic allocation - * failure - * returns a ERR_PTR(-ENOMEM). - **/ - -static struct users *get_user(void) -{ - struct users *user; - - user = kmalloc(sizeof(struct users), GFP_KERNEL); - if (!user) { - pr_err("%s FATAL ERROR: kmalloc " - "failed\n", __func__); - return ERR_PTR(-ENOMEM); - } - return user; -} - - -/** - * omap_bus_tput_init - Initializes the interconnect throughput - * userlist - * Allocates memory for global throughput variable dynamically. - * Intializes Userlist, no. of users and throughput target level. - * Returns 0 on sucess, else returns EINVAL if memory - * allocation fails. - */ -static int __init omap_bus_tput_init(void) -{ - bus_tput = kmalloc(sizeof(struct interconnect_tput), GFP_KERNEL); - if (!bus_tput) { - pr_err("%s FATAL ERROR: kmalloc failed\n", __func__); - return -EINVAL; - } - INIT_LIST_HEAD(&bus_tput->users_list); - mutex_init(&bus_tput->throughput_mutex); - bus_tput->no_of_users = 0; - bus_tput->target_level = 0; - return 0; -} - - -/** - * add_req_tput - Request for a required level by a device - * @dev: Uniquely identifes the caller - * @level: The requested level for the interconnect bandwidth in KiB/s - * - * This function recomputes the target level of the interconnect - * bandwidth - * based on the level requested by all the users. - * Multiple calls to this function by the same device will - * replace the previous level requested - * Returns the updated level of interconnect throughput. - * In case of Invalid dev or user pointer, it returns 0. - */ -static unsigned long add_req_tput(struct device *dev, unsigned long level) -{ - int ret; - struct users *user; - - if (!dev) { - pr_err("Invalid dev pointer\n"); - ret = 0; - } - mutex_lock(&bus_tput->throughput_mutex); - user = user_lookup(dev); - if (user == NULL) { - user = get_user(); - if (IS_ERR(user)) { - pr_err("Couldn't get user from the list to" - "add new throughput constraint"); - ret = 0; - goto unlock; - } - bus_tput->target_level += level; - bus_tput->no_of_users++; - user->dev = dev; - list_add(&user->node, &bus_tput->users_list); - user->level = level; - } else { - bus_tput->target_level -= user->level; - bus_tput->target_level += level; - user->level = level; - } - ret = bus_tput->target_level; -unlock: - mutex_unlock(&bus_tput->throughput_mutex); - return ret; -} - - -/** - * remove_req_tput - Release a previously requested level of - * a throughput level for interconnect - * @dev: Device pointer to dev - * - * This function recomputes the target level of the interconnect - * throughput after removing - * the level requested by the user. - * Returns 0, if the dev structure is invalid - * else returns modified interconnect throughput rate. - */ -static unsigned long remove_req_tput(struct device *dev) -{ - struct users *user; - int found = 0; - int ret; - - mutex_lock(&bus_tput->throughput_mutex); - list_for_each_entry(user, &bus_tput->users_list, node) { - if (user->dev == dev) { - found = 1; - break; - } - } - if (!found) { - /* No such user exists */ - pr_err("Invalid Device Structure\n"); - ret = 0; - goto unlock; - } - bus_tput->target_level -= user->level; - bus_tput->no_of_users--; - list_del(&user->node); - kfree(user); - ret = bus_tput->target_level; -unlock: - mutex_unlock(&bus_tput->throughput_mutex); - return ret; -} - -int omap_pm_set_min_bus_tput_helper(struct device *dev, u8 agent_id, long r) -{ - - int ret = 0; - struct device *l3_dev; - static struct device dummy_l3_dev; - unsigned long target_level = 0; - - mutex_lock(&bus_tput_mutex); - - l3_dev = omap2_get_l3_device(); - if (!l3_dev) { - pr_err("Unable to get l3 device pointer"); - ret = -EINVAL; - goto unlock; - } - - if (r == -1) - target_level = remove_req_tput(dev); - else - target_level = add_req_tput(dev, r); - - /* Convert the throughput(in KiB/s) into Hz. */ - target_level = (target_level * 1000)/4; - - WARN(1, "OMAP PM: %s: constraint not called, needs DVFS", __func__); -#if 0 - ret = omap_device_scale(&dummy_l3_dev, l3_dev, target_level); -#endif - if (ret) - pr_err("Unable to change level for interconnect bandwidth to %ld\n", - target_level); -unlock: - mutex_unlock(&bus_tput_mutex); - return ret; -} - -int omap_pm_set_max_dev_wakeup_lat_helper(struct device *req_dev, - struct device *dev, long t) -{ - struct omap_device *odev; - struct powerdomain *pwrdm_dev; - struct platform_device *pdev; - int ret = 0; - - if (!req_dev || !dev || t < -1) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - }; - - /* Look for the devices Power Domain */ - pdev = container_of(dev, struct platform_device, dev); - - /* Try to catch non platform devices. */ - if (pdev->name == NULL) { - pr_err("OMAP-PM: Error: platform device not valid\n"); - return -EINVAL; - } - - odev = to_omap_device(pdev); - if (odev) { - pwrdm_dev = omap_device_get_pwrdm(odev); - } else { - pr_err("OMAP-PM: Error: Could not find omap_device " - "for %s\n", pdev->name); - return -EINVAL; - } - - /* Catch devices with undefined powerdomains. */ - if (!pwrdm_dev) { - pr_err("OMAP-PM: Error: could not find parent " - "powerdomain for %s\n", pdev->name); - return -EINVAL; - } - - if (t == -1) - ret = pwrdm_wakeuplat_release_constraint(pwrdm_dev, req_dev); - else - ret = pwrdm_wakeuplat_set_constraint(pwrdm_dev, req_dev, t); - - return ret; -} - -/* Must be called after clock framework is initialized */ -int __init omap_pm_if_init_helper(void) -{ - int ret; - ret = omap_bus_tput_init(); - if (ret) - pr_err("Failed to initialize interconnect" - " bandwidth users list\n"); - return ret; -} -- cgit v1.1 From a854f31c29453d019e398c948a5eae4d72f3ec87 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Sat, 18 Jun 2011 20:37:06 -0500 Subject: OMAP: PM: beautification of omap-pm code Minor Lindent beautification of the code Signed-off-by: Nishanth Menon --- arch/arm/plat-omap/omap-pm-helper.c | 41 ++++++++++++++-------------------- arch/arm/plat-omap/omap-pm-interface.c | 26 ++++++++++----------- 2 files changed, 30 insertions(+), 37 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-omap/omap-pm-helper.c b/arch/arm/plat-omap/omap-pm-helper.c index a6d4aa6..aceec1f 100644 --- a/arch/arm/plat-omap/omap-pm-helper.c +++ b/arch/arm/plat-omap/omap-pm-helper.c @@ -69,8 +69,7 @@ struct users { * Looks for a interconnect user by its device pointer. Returns a * pointer to * the struct users if found, else returns NULL. - **/ - + */ static struct users *user_lookup(struct device *dev) { struct users *usr, *tmp_usr; @@ -93,22 +92,19 @@ static struct users *user_lookup(struct device *dev) * Returns a pointer to users struct on success. On dynamic allocation * failure * returns a ERR_PTR(-ENOMEM). - **/ - + */ static struct users *get_user(void) { struct users *user; - user = kmalloc(sizeof(struct users), GFP_KERNEL); + user = kmalloc(sizeof(struct users), GFP_KERNEL); if (!user) { - pr_err("%s FATAL ERROR: kmalloc " - "failed\n", __func__); + pr_err("%s FATAL ERROR: kmalloc failed\n", __func__); return ERR_PTR(-ENOMEM); } return user; } - /** * omap_bus_tput_init - Initializes the interconnect throughput * userlist @@ -123,7 +119,7 @@ static int __init omap_bus_tput_init(void) if (!bus_tput) { pr_err("%s FATAL ERROR: kmalloc failed\n", __func__); return -EINVAL; - } + } INIT_LIST_HEAD(&bus_tput->users_list); mutex_init(&bus_tput->throughput_mutex); bus_tput->no_of_users = 0; @@ -131,7 +127,6 @@ static int __init omap_bus_tput_init(void) return 0; } - /** * add_req_tput - Request for a required level by a device * @dev: Uniquely identifes the caller @@ -148,7 +143,7 @@ static int __init omap_bus_tput_init(void) static unsigned long add_req_tput(struct device *dev, unsigned long level) { int ret; - struct users *user; + struct users *user; if (!dev) { pr_err("Invalid dev pointer\n"); @@ -160,7 +155,7 @@ static unsigned long add_req_tput(struct device *dev, unsigned long level) user = get_user(); if (IS_ERR(user)) { pr_err("Couldn't get user from the list to" - "add new throughput constraint"); + "add new throughput constraint"); ret = 0; goto unlock; } @@ -174,13 +169,12 @@ static unsigned long add_req_tput(struct device *dev, unsigned long level) bus_tput->target_level += level; user->level = level; } - ret = bus_tput->target_level; + ret = bus_tput->target_level; unlock: mutex_unlock(&bus_tput->throughput_mutex); return ret; } - /** * remove_req_tput - Release a previously requested level of * a throughput level for interconnect @@ -244,22 +238,22 @@ int omap_pm_set_min_bus_tput_helper(struct device *dev, u8 agent_id, long r) target_level = add_req_tput(dev, r); /* Convert the throughput(in KiB/s) into Hz. */ - target_level = (target_level * 1000)/4; + target_level = (target_level * 1000) / 4; WARN(1, "OMAP PM: %s: constraint not called, needs DVFS", __func__); #if 0 ret = omap_device_scale(&dummy_l3_dev, l3_dev, target_level); #endif if (ret) - pr_err("Unable to change level for interconnect bandwidth to %ld\n", - target_level); + pr_err("Failed: change interconnect bandwidth to %ld\n", + target_level); unlock: mutex_unlock(&bus_tput_mutex); return ret; } int omap_pm_set_max_dev_wakeup_lat_helper(struct device *req_dev, - struct device *dev, long t) + struct device *dev, long t) { struct omap_device *odev; struct powerdomain *pwrdm_dev; @@ -284,15 +278,15 @@ int omap_pm_set_max_dev_wakeup_lat_helper(struct device *req_dev, if (odev) { pwrdm_dev = omap_device_get_pwrdm(odev); } else { - pr_err("OMAP-PM: Error: Could not find omap_device " - "for %s\n", pdev->name); + pr_err("OMAP-PM: Error: Could not find omap_device for %s\n", + pdev->name); return -EINVAL; } /* Catch devices with undefined powerdomains. */ if (!pwrdm_dev) { - pr_err("OMAP-PM: Error: could not find parent " - "powerdomain for %s\n", pdev->name); + pr_err("OMAP-PM: Error: could not find parent pwrdm for %s\n", + pdev->name); return -EINVAL; } @@ -310,7 +304,6 @@ int __init omap_pm_if_init_helper(void) int ret; ret = omap_bus_tput_init(); if (ret) - pr_err("Failed to initialize interconnect" - " bandwidth users list\n"); + pr_err("Failed: init of interconnect bandwidth users list\n"); return ret; } diff --git a/arch/arm/plat-omap/omap-pm-interface.c b/arch/arm/plat-omap/omap-pm-interface.c index c677483..67319a7 100644 --- a/arch/arm/plat-omap/omap-pm-interface.c +++ b/arch/arm/plat-omap/omap-pm-interface.c @@ -33,10 +33,10 @@ static bool off_mode_enabled; * WARNING: Device drivers need to now use pm_qos directly. */ int omap_pm_set_max_mpu_wakeup_lat(struct pm_qos_request_list **pmqos_req, - long t) + long t) { WARN(1, "Deprecated %s: Driver should use pm_qos to add request\n", - __func__); + __func__); return -EINVAL; } @@ -45,7 +45,7 @@ int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, long r) { int ret; if (!dev || (agent_id != OCP_INITIATOR_AGENT && - agent_id != OCP_TARGET_AGENT)) { + agent_id != OCP_TARGET_AGENT)) { WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); return -EINVAL; }; @@ -88,7 +88,7 @@ int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, int omap_pm_set_max_sdma_lat(struct pm_qos_request_list **qos_request, long t) { WARN(1, "Deprecated %s: Driver should use pm_qos to add request\n", - __func__); + __func__); return -EINVAL; } @@ -96,7 +96,7 @@ int omap_pm_set_max_sdma_lat(struct pm_qos_request_list **qos_request, long t) int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r) { WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", - __func__); + __func__); return -EINVAL; } @@ -108,7 +108,7 @@ int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r) const struct omap_opp *omap_pm_dsp_get_opp_table(void) { WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", - __func__); + __func__); return ERR_PTR(-EINVAL); } @@ -116,7 +116,7 @@ const struct omap_opp *omap_pm_dsp_get_opp_table(void) void omap_pm_dsp_set_min_opp(u8 opp_id) { WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", - __func__); + __func__); return; } @@ -124,17 +124,18 @@ void omap_pm_dsp_set_min_opp(u8 opp_id) int omap_pm_set_min_mpu_freq(struct device *dev, unsigned long f) { WARN(1, "Deprecated %s: Driver should NOT use this function\n", - __func__); + __func__); return -EINVAL; } + EXPORT_SYMBOL(omap_pm_set_min_mpu_freq); u8 omap_pm_dsp_get_opp(void) { WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", - __func__); + __func__); return 0; } @@ -149,7 +150,7 @@ u8 omap_pm_dsp_get_opp(void) struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void) { WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", - __func__); + __func__); return ERR_PTR(-EINVAL); } @@ -157,7 +158,7 @@ struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void) void omap_pm_cpu_set_freq(unsigned long f) { WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", - __func__); + __func__); return; } @@ -165,7 +166,7 @@ void omap_pm_cpu_set_freq(unsigned long f) unsigned long omap_pm_cpu_get_freq(void) { WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", - __func__); + __func__); return 0; } @@ -236,4 +237,3 @@ void omap_pm_if_exit(void) { /* Deallocate CPUFreq frequency table here */ } - -- cgit v1.1 From 1cd8e6a9fcc517b2875fdfba403b39533e3ff4e2 Mon Sep 17 00:00:00 2001 From: Girish S G Date: Tue, 21 Jun 2011 13:10:38 -0500 Subject: OMAP: PM: omap-pm-helper.c warning fixes Fix below warning: arch/arm/plat-omap/omap-pm-helper.c: In function 'omap_pm_set_min_bus_tput_helper': arch/arm/plat-omap/omap-pm-helper.c:223: warning: unused variable 'dummy_l3_dev' NOTE: even though core dvfs is enabled, we need to get EMIF driver in place before we allow drivers to scale core dvfs. Acked-by: Nishanth Menon Signed-off-by: Girish S G --- arch/arm/plat-omap/omap-pm-helper.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/plat-omap/omap-pm-helper.c b/arch/arm/plat-omap/omap-pm-helper.c index aceec1f..0f71c45 100644 --- a/arch/arm/plat-omap/omap-pm-helper.c +++ b/arch/arm/plat-omap/omap-pm-helper.c @@ -220,7 +220,14 @@ int omap_pm_set_min_bus_tput_helper(struct device *dev, u8 agent_id, long r) int ret = 0; struct device *l3_dev; + + /* + * TODO: This will go away when complete device scaling support for + * L3 is added. + */ +#if 0 static struct device dummy_l3_dev; +#endif unsigned long target_level = 0; mutex_lock(&bus_tput_mutex); @@ -240,13 +247,18 @@ int omap_pm_set_min_bus_tput_helper(struct device *dev, u8 agent_id, long r) /* Convert the throughput(in KiB/s) into Hz. */ target_level = (target_level * 1000) / 4; - WARN(1, "OMAP PM: %s: constraint not called, needs DVFS", __func__); + /* + * TODO: This will go away when complete device scaling support for + * L3 is added. + */ #if 0 ret = omap_device_scale(&dummy_l3_dev, l3_dev, target_level); -#endif if (ret) pr_err("Failed: change interconnect bandwidth to %ld\n", target_level); +#else + WARN(1, "OMAP PM: %s: constraint not called, needs DVFS", __func__); +#endif unlock: mutex_unlock(&bus_tput_mutex); return ret; -- cgit v1.1 From 2c3679d69f4e835f9e2026d55b65644cd0ab0237 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Mon, 20 Jun 2011 18:44:16 +0530 Subject: OMAP4: OPP: Add SGX OPPs Add OMAP4430 and OMAP4460 SGX OPP entries Acked-by: Hemant Hariyani Signed-off-by: Rajendra Nayak --- arch/arm/mach-omap2/opp4xxx_data.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c index 0b14864..8d14e2f 100644 --- a/arch/arm/mach-omap2/opp4xxx_data.c +++ b/arch/arm/mach-omap2/opp4xxx_data.c @@ -125,7 +125,11 @@ static struct omap_opp_def __initdata omap443x_opp_def_list[] = { OPP_INITIALIZER("iva", "dpll_iva_m5x2_ck", "iva", true, 266100000, OMAP4430_VDD_IVA_OPP100_UV), /* IVA OPP3 - OPP-Turbo */ OPP_INITIALIZER("iva", "dpll_iva_m5x2_ck", "iva", false, 332000000, OMAP4430_VDD_IVA_OPPTURBO_UV), - /* TODO: add DSP, aess, fdif, gpu */ + /* SGX OPP1 - OPP50 */ + OPP_INITIALIZER("gpu", "dpll_per_m7x2_ck", "core", true, 153600000, OMAP4430_VDD_CORE_OPP50_UV), + /* SGX OPP2 - OPP100 */ + OPP_INITIALIZER("gpu", "dpll_per_m7x2_ck", "core", true, 307200000, OMAP4430_VDD_CORE_OPP50_UV), + /* TODO: add DSP, aess, fdif */ }; #define OMAP4460_VDD_MPU_OPP50_UV 1025000 @@ -234,7 +238,14 @@ static struct omap_opp_def __initdata omap446x_opp_def_list[] = { /* IVA OPP5 - OPP-Nitro SpeedBin*/ OPP_INITIALIZER("iva", "dpll_iva_m5x2_ck", "iva", false, 500000000, OMAP4460_VDD_IVA_OPPNITRO_UV), - /* TODO: add DSP, aess, fdif, gpu */ + /* SGX OPP1 - OPP50 */ + OPP_INITIALIZER("gpu", "dpll_per_m7x2_ck", "core", true, 153600000, OMAP4460_VDD_CORE_OPP50_UV), + /* SGX OPP2 - OPP100 */ + OPP_INITIALIZER("gpu", "dpll_per_m7x2_ck", "core", true, 307200000, OMAP4460_VDD_CORE_OPP100_UV), + /* SGX OPP3 - OPPOV */ + OPP_INITIALIZER("gpu", "dpll_per_m7x2_ck", "core", true, 384000000, OMAP4460_VDD_CORE_OPP100_OV_UV), + + /* TODO: add DSP, aess, fdif */ }; /** -- cgit v1.1 From 972d7bb544d3197d7fc1a6c6eb0e2c9cc08d5e9d Mon Sep 17 00:00:00 2001 From: Miguel Vadillo Date: Tue, 21 Jun 2011 09:59:45 -0500 Subject: OMAP: clockdomain: set iss clk domain to just SWSUP Since CAM domain(ISS) has no module wake-up dependency with any other clock domain of the device and the dynamic dependency from L3_main_2 is always disabled, the domain needs to be in force wakeup in order to be able to access it for configure(sysconfig) it or use it. Also since there is no clock in the domain managed automatically by the hardware, there is no use to configure automatic clock domain transition. SW should keep the SW_WKUP domain transition as long as a module in the domain is required to be functional. Signed-off-by: Miguel Vadillo Acked-by: Benoit Cousson --- arch/arm/mach-omap2/clockdomains44xx_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c index 6ac8fe2..8d1a061 100644 --- a/arch/arm/mach-omap2/clockdomains44xx_data.c +++ b/arch/arm/mach-omap2/clockdomains44xx_data.c @@ -605,7 +605,7 @@ static struct clockdomain iss_44xx_clkdm = { .clkdm_offs = OMAP4430_CM2_CAM_CAM_CDOFFS, .wkdep_srcs = iss_wkup_sleep_deps, .sleepdep_srcs = iss_wkup_sleep_deps, - .flags = CLKDM_CAN_HWSUP_SWSUP, + .flags = CLKDM_CAN_SWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; -- cgit v1.1 From 8b2db85bb47df036f4188bb956f4e06bb9ce6d99 Mon Sep 17 00:00:00 2001 From: Miguel Vadillo Date: Fri, 17 Jun 2011 10:09:11 -0500 Subject: OMAP4: hwmod: add fdif module Add fdif module to hwmod framework. Signed-off-by: Miguel Vadillo Signed-off-by: Fernando Guzman Lugo Signed-off-by: Benoit Cousson --- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 85 +++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 8f91816..23b0025 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -50,6 +50,7 @@ static struct omap_hwmod omap44xx_dmm_hwmod; static struct omap_hwmod omap44xx_dsp_hwmod; static struct omap_hwmod omap44xx_dss_hwmod; static struct omap_hwmod omap44xx_emif_fw_hwmod; +static struct omap_hwmod omap44xx_fdif_hwmod; static struct omap_hwmod omap44xx_gpu_hwmod; static struct omap_hwmod omap44xx_hsi_hwmod; static struct omap_hwmod omap44xx_ipu_hwmod; @@ -353,6 +354,14 @@ static struct omap_hwmod_ocp_if omap44xx_iss__l3_main_2 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +/* fdif -> l3_main_2 */ +static struct omap_hwmod_ocp_if omap44xx_fdif__l3_main_2 = { + .master = &omap44xx_fdif_hwmod, + .slave = &omap44xx_l3_main_2_hwmod, + .clk = "l3_div_ck", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + /* iva -> l3_main_2 */ static struct omap_hwmod_ocp_if omap44xx_iva__l3_main_2 = { .master = &omap44xx_iva_hwmod, @@ -401,6 +410,7 @@ static struct omap_hwmod_ocp_if *omap44xx_l3_main_2_slaves[] = { &omap44xx_hsi__l3_main_2, &omap44xx_ipu__l3_main_2, &omap44xx_iss__l3_main_2, + &omap44xx_fdif__l3_main_2, &omap44xx_iva__l3_main_2, &omap44xx_l3_main_1__l3_main_2, &omap44xx_gpu__l3_main_2, @@ -641,7 +651,6 @@ static struct omap_hwmod omap44xx_mpu_private_hwmod = { * elm * emif1 * emif2 - * fdif * gpmc * gpu * hdq1w @@ -2033,6 +2042,77 @@ static struct omap_hwmod omap44xx_dss_venc_hwmod = { }; /* + * 'fdif' class + * face detection hw accelerator module + */ + +static struct omap_hwmod_class_sysconfig omap44xx_fdif_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_RESET_STATUS | + SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), + .sysc_fields = &omap_hwmod_sysc_type2, +}; + +static struct omap_hwmod_class omap44xx_fdif_hwmod_class = { + .name = "fdif", + .sysc = &omap44xx_fdif_sysc, +}; + +/* fdif */ +static struct omap_hwmod_irq_info omap44xx_fdif_irqs[] = { + { .irq = 69 + OMAP44XX_IRQ_GIC_START }, +}; + +/* fdif master ports */ +static struct omap_hwmod_ocp_if *omap44xx_fdif_masters[] = { + &omap44xx_fdif__l3_main_2, +}; + +static struct omap_hwmod_addr_space omap44xx_fdif_addrs[] = { + { + .pa_start = 0x4a10a000, + .pa_end = 0x4a10a1ff, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_cfg -> fdif */ +static struct omap_hwmod_ocp_if omap44xx_l3_main_2__fdif = { + .master = &omap44xx_l3_main_2_hwmod, + .slave = &omap44xx_fdif_hwmod, + .clk = "l3_div_ck", + .addr = omap44xx_fdif_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_fdif_addrs), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* fdif slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_fdif_slaves[] = { + &omap44xx_l3_main_2__fdif, +}; + +static struct omap_hwmod omap44xx_fdif_hwmod = { + .name = "fdif", + .class = &omap44xx_fdif_hwmod_class, + .mpu_irqs = omap44xx_fdif_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_fdif_irqs), + .main_clk = "fdif_fck", + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM_CAM_FDIF_CLKCTRL, + }, + }, + .slaves = omap44xx_fdif_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_fdif_slaves), + .masters = omap44xx_fdif_masters, + .masters_cnt = ARRAY_SIZE(omap44xx_fdif_masters), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), +}; + +/* * 'gpio' class * general purpose io module */ @@ -5403,6 +5483,9 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = { /* iss class */ /* &omap44xx_iss_hwmod, */ + /* fdif class */ + &omap44xx_fdif_hwmod, + /* iva class */ &omap44xx_iva_hwmod, &omap44xx_iva_seq0_hwmod, -- cgit v1.1 From 64527025f77fec981b0c93934081f2136468d42a Mon Sep 17 00:00:00 2001 From: Miguel Vadillo Date: Fri, 17 Jun 2011 10:09:12 -0500 Subject: OMAP4: hwmod: enable iss module Enabling iss module in hwmod framework. Signed-off-by: Miguel Vadillo Signed-off-by: Fernando Guzman Lugo Signed-off-by: Benoit Cousson --- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 23b0025..dfdcc4c 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -5481,7 +5481,7 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = { &omap44xx_ipu_c1_hwmod, /* iss class */ -/* &omap44xx_iss_hwmod, */ + &omap44xx_iss_hwmod, /* fdif class */ &omap44xx_fdif_hwmod, -- cgit v1.1