aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2011-06-22 15:34:37 -0700
committerColin Cross <ccross@android.com>2011-06-22 15:34:37 -0700
commit059da53243176a255574e347fd71f9bc1b39140d (patch)
treeb9df8accdcd3374a5a7b6011e2bc19102c5f5706 /arch/arm
parent60c6f44ba237be3c0920d75c3d694ccadfd59fab (diff)
parentc762980fab4f64c2d3cd12c4c2ccbeb611d61b5c (diff)
downloadkernel_samsung_tuna-059da53243176a255574e347fd71f9bc1b39140d.zip
kernel_samsung_tuna-059da53243176a255574e347fd71f9bc1b39140d.tar.gz
kernel_samsung_tuna-059da53243176a255574e347fd71f9bc1b39140d.tar.bz2
Merge branch 'omap-pm-integration' of git://github.com/nmenon/linux-omap-ti-pm into linux-omap-pm-3.0
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-omap2/clock44xx_data.c114
-rw-r--r--arch/arm/mach-omap2/clockdomains44xx_data.c2
-rw-r--r--arch/arm/mach-omap2/dvfs.c19
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c11
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_44xx_data.c89
-rw-r--r--arch/arm/mach-omap2/omap_opp_data.h2
-rw-r--r--arch/arm/mach-omap2/opp.c11
-rw-r--r--arch/arm/mach-omap2/opp4xxx_data.c56
-rw-r--r--arch/arm/mach-omap2/pm.c8
-rw-r--r--arch/arm/mach-omap2/voltagedomains44xx_data.c8
-rw-r--r--arch/arm/plat-omap/Makefile4
-rw-r--r--arch/arm/plat-omap/i2c.c13
-rw-r--r--arch/arm/plat-omap/omap-pm-helper.c321
-rw-r--r--arch/arm/plat-omap/omap-pm-helper.h40
-rw-r--r--arch/arm/plat-omap/omap-pm-interface.c239
-rw-r--r--arch/arm/plat-omap/omap-pm-noop.c372
-rw-r--r--arch/arm/plat-omap/omap-pm.c630
17 files changed, 887 insertions, 1052 deletions
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/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),
};
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);
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 085731c..94573ef 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);
@@ -1381,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
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index e523072..dfdcc4c 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
@@ -885,7 +894,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,
@@ -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
*/
@@ -5401,7 +5481,10 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
&omap44xx_ipu_c1_hwmod,
/* iss class */
-/* &omap44xx_iss_hwmod, */
+ &omap44xx_iss_hwmod,
+
+ /* fdif class */
+ &omap44xx_fdif_hwmod,
/* iva class */
&omap44xx_iva_hwmod,
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/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++;
}
diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c
index 9083c7f..8d14e2f 100644
--- a/arch/arm/mach-omap2/opp4xxx_data.c
+++ b/arch/arm/mach-omap2/opp4xxx_data.c
@@ -116,16 +116,20 @@ 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 */
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
@@ -165,6 +169,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),
@@ -182,9 +219,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 */
@@ -201,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 */
};
/**
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);
}
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;
}
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index e2d8843..f3ab483 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) += omap-pm.o
+obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-interface.o
+obj-$(CONFIG_OMAP_PM) += omap-pm-interface.o omap-pm-helper.o
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);
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..0f71c45
--- /dev/null
+++ b/arch/arm/plat-omap/omap-pm-helper.c
@@ -0,0 +1,321 @@
+/*
+ * 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 <linux/init.h>
+#include <linux/cpufreq.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+
+/* Interface documentation is in mach/omap-pm.h */
+#include <plat/omap-pm.h>
+#include <plat/omap_device.h>
+#include <plat/common.h>
+#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;
+
+ /*
+ * 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);
+
+ 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;
+
+ /*
+ * 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);
+ 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;
+}
+
+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 pwrdm 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: init of interconnect bandwidth users list\n");
+ return ret;
+}
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
new file mode 100644
index 0000000..67319a7
--- /dev/null
+++ b/arch/arm/plat-omap/omap-pm-interface.c
@@ -0,0 +1,239 @@
+/*
+ * 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 <linux/init.h>
+#include <linux/cpufreq.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+
+/* Interface documentation is in mach/omap-pm.h */
+#include <plat/omap-pm.h>
+#include <plat/omap_device.h>
+
+#include "omap-pm-helper.h"
+
+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)
+{
+ 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 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 == -1)
+ 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);
+
+ ret = omap_pm_set_min_bus_tput_helper(dev, agent_id, r);
+
+ 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;
+ };
+
+ 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);
+
+ ret = omap_pm_set_max_dev_wakeup_lat_helper(req_dev, dev, t);
+
+ 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;
+}
+
+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)
+{
+ 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
+ * WARNING: at this point we dont have a reliable context loss reporting
+ * mechanism. Instead, we ensure that we report context loss always.
+ */
+int omap_pm_get_dev_context_loss_count(struct device *dev)
+{
+ static u32 count = 1;
+
+ if (!dev) {
+ WARN_ON(1);
+ return -EINVAL;
+ };
+
+ 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. Roll over to 1
+ */
+ count = (count & ~INT_MAX) ? 1 : count;
+
+ pr_debug("OMAP PM: returning context loss count for dev %s count %ul\n",
+ dev_name(dev), count);
+ return count;
+}
+
+/* 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 omap_pm_if_init_helper();
+}
+
+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 <linux/init.h>
-#include <linux/cpufreq.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-
-/* Interface documentation is in mach/omap-pm.h */
-#include <plat/omap-pm.h>
-#include <plat/omap_device.h>
-
-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.c b/arch/arm/plat-omap/omap-pm.c
deleted file mode 100644
index a2ee551..0000000
--- a/arch/arm/plat-omap/omap-pm.c
+++ /dev/null
@@ -1,630 +0,0 @@
-/*
- * omap-pm.c - OMAP power management interface
- *
- * Copyright (C) 2008-2010 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 <linux/init.h>
-#include <linux/cpufreq.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/list.h>
-
-/* Interface documentation is in mach/omap-pm.h */
-#include <plat/omap-pm.h>
-#include <plat/omap_device.h>
-#include <plat/common.h>
-#include "../mach-omap2/powerdomain.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);
-
-static bool off_mode_enabled;
-
-/* 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.
- */
-int 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;
-}
-
-/*
- * Device-driver-originated constraints (via board-*.c files)
- */
-
-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;
- };
-
- 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;
-}
-
-
-int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, long r)
-{
-
- int ret;
- 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();
- if (!l3_dev) {
- pr_err("Unable to get l3 device pointer");
- 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);
- 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);
- 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(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) {
- 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));
- 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));
- 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;
-}
-
-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) {
- 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;
-}
-
-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
- */
-
-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 ret;
- ret = omap_bus_tput_init();
- if (ret)
- pr_err("Failed to initialize interconnect"
- " 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)
-{
-
- 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);
-
-unlock:
- mutex_unlock(&mpu_tput_mutex);
- return ret;
-}
-EXPORT_SYMBOL(omap_pm_set_min_mpu_freq);