* [PATCH 00/12] rework OPP layer to handle device-based OPPs
@ 2010-06-17 0:17 Kevin Hilman
2010-06-17 0:17 ` [PATCH 01/12] OMAP2/3: hwmod: remove '_hwmod' suffix from names Kevin Hilman
` (11 more replies)
0 siblings, 12 replies; 20+ messages in thread
From: Kevin Hilman @ 2010-06-17 0:17 UTC (permalink / raw)
To: linux-omap; +Cc: nm, thara, b-cousson
The current OPP layer is based on a unique identifier (OPP_MPU,
OPP_DSP, OPP_L3) which is not terribly portable or scalable for future
devices.
Since we'd also like to be able to manage OPPs for any device (as
recently agreed upon during an OMAP PM meeting in TI Bangalore[1]), this
patch changes the OPP API to be device-based instead of unique-ID
based. Essentially, this means passing a 'struct device' instead of a
unique ID to determine which set of OPPs to be used.
The main part of this patch is PATCH 08/12 where the OPP API changes
are made. The earlier parts of the series are prep work for this and
the remaining parts are updating users of the OPP API.
Applies on top of current PM branch.
[1] http://omappedia.org/wiki/Proceedings_of_the_PM_SW_Workshop_Jun_2010
Kevin Hilman (12):
OMAP2/3: hwmod: remove '_hwmod' suffix from names
OMAP: hwmod: add class for DSP hwmods
OMAP3: hwmod: add data for OMAP3 IVA2
OMAP: omap_device: ensure hwmod tracks attached omap_device pointer
OMAP: create omap_devices for MPU, DSP, L3
OMAP: voltage: use device_initcall()
OMAP: SR: use device_initcall()
OMAP2: OPP: update API to be device-based
OMAP3: CPUfreq: update to device-based OPP API
OMAP: voltage: update to new device-based OPP API
OMAP: SRF: update to new device-based OPP API
OMAP: SRF: must be initialized before allowing constraints to be set
arch/arm/mach-omap2/cpufreq34xx.c | 180 +++++--------
arch/arm/mach-omap2/devices.c | 2 +
arch/arm/mach-omap2/io.c | 68 ++++-
arch/arm/mach-omap2/omap_hwmod_2420_data.c | 6 +-
arch/arm/mach-omap2/omap_hwmod_2430_data.c | 6 +-
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 49 +++-
arch/arm/mach-omap2/omap_hwmod_common_data.c | 3 +
arch/arm/mach-omap2/omap_hwmod_common_data.h | 1 +
arch/arm/mach-omap2/resource34xx.c | 95 ++++---
arch/arm/mach-omap2/sr_device.c | 2 +-
arch/arm/mach-omap2/voltage.c | 12 +-
arch/arm/plat-omap/cpu-omap.c | 12 +-
arch/arm/plat-omap/include/plat/common.h | 4 +
arch/arm/plat-omap/include/plat/opp.h | 57 ++---
arch/arm/plat-omap/omap-pm-srf.c | 7 +
arch/arm/plat-omap/omap_device.c | 8 +-
arch/arm/plat-omap/opp.c | 396 +++++++++++---------------
17 files changed, 474 insertions(+), 434 deletions(-)
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 01/12] OMAP2/3: hwmod: remove '_hwmod' suffix from names
2010-06-17 0:17 [PATCH 00/12] rework OPP layer to handle device-based OPPs Kevin Hilman
@ 2010-06-17 0:17 ` Kevin Hilman
2010-06-17 14:23 ` Kevin Hilman
2010-06-17 0:17 ` [PATCH 02/12] OMAP: hwmod: add class for DSP hwmods Kevin Hilman
` (10 subsequent siblings)
11 siblings, 1 reply; 20+ messages in thread
From: Kevin Hilman @ 2010-06-17 0:17 UTC (permalink / raw)
To: linux-omap; +Cc: nm, thara, b-cousson
As per new naming convention for hwmods, remove the redundant _hwmod suffix
from all hwmod names.
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
arch/arm/mach-omap2/omap_hwmod_2420_data.c | 6 +++---
arch/arm/mach-omap2/omap_hwmod_2430_data.c | 6 +++---
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 8 ++++----
3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index e5530c5..284fb23 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -59,7 +59,7 @@ static struct omap_hwmod_ocp_if *omap2420_l3_masters[] = {
/* L3 */
static struct omap_hwmod omap2420_l3_hwmod = {
- .name = "l3_hwmod",
+ .name = "l3",
.class = &l3_hwmod_class,
.masters = omap2420_l3_masters,
.masters_cnt = ARRAY_SIZE(omap2420_l3_masters),
@@ -89,7 +89,7 @@ static struct omap_hwmod_ocp_if *omap2420_l4_core_masters[] = {
/* L4 CORE */
static struct omap_hwmod omap2420_l4_core_hwmod = {
- .name = "l4_core_hwmod",
+ .name = "l4_core",
.class = &l4_hwmod_class,
.masters = omap2420_l4_core_masters,
.masters_cnt = ARRAY_SIZE(omap2420_l4_core_masters),
@@ -109,7 +109,7 @@ static struct omap_hwmod_ocp_if *omap2420_l4_wkup_masters[] = {
/* L4 WKUP */
static struct omap_hwmod omap2420_l4_wkup_hwmod = {
- .name = "l4_wkup_hwmod",
+ .name = "l4_wkup",
.class = &l4_hwmod_class,
.masters = omap2420_l4_wkup_masters,
.masters_cnt = ARRAY_SIZE(omap2420_l4_wkup_masters),
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 0852d95..1e780b1 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -59,7 +59,7 @@ static struct omap_hwmod_ocp_if *omap2430_l3_masters[] = {
/* L3 */
static struct omap_hwmod omap2430_l3_hwmod = {
- .name = "l3_hwmod",
+ .name = "l3",
.class = &l3_hwmod_class,
.masters = omap2430_l3_masters,
.masters_cnt = ARRAY_SIZE(omap2430_l3_masters),
@@ -91,7 +91,7 @@ static struct omap_hwmod_ocp_if *omap2430_l4_core_masters[] = {
/* L4 CORE */
static struct omap_hwmod omap2430_l4_core_hwmod = {
- .name = "l4_core_hwmod",
+ .name = "l4_core",
.class = &l4_hwmod_class,
.masters = omap2430_l4_core_masters,
.masters_cnt = ARRAY_SIZE(omap2430_l4_core_masters),
@@ -111,7 +111,7 @@ static struct omap_hwmod_ocp_if *omap2430_l4_wkup_masters[] = {
/* L4 WKUP */
static struct omap_hwmod omap2430_l4_wkup_hwmod = {
- .name = "l4_wkup_hwmod",
+ .name = "l4_wkup",
.class = &l4_hwmod_class,
.masters = omap2430_l4_wkup_masters,
.masters_cnt = ARRAY_SIZE(omap2430_l4_wkup_masters),
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 074347f..f1df4c9 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -73,7 +73,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_l3_masters[] = {
/* L3 */
static struct omap_hwmod omap3xxx_l3_hwmod = {
- .name = "l3_hwmod",
+ .name = "l3",
.class = &l3_hwmod_class,
.masters = omap3xxx_l3_masters,
.masters_cnt = ARRAY_SIZE(omap3xxx_l3_masters),
@@ -141,7 +141,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_core_masters[] = {
/* L4 CORE */
static struct omap_hwmod omap3xxx_l4_core_hwmod = {
- .name = "l4_core_hwmod",
+ .name = "l4_core",
.class = &l4_hwmod_class,
.masters = omap3xxx_l4_core_masters,
.masters_cnt = ARRAY_SIZE(omap3xxx_l4_core_masters),
@@ -161,7 +161,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_per_masters[] = {
/* L4 PER */
static struct omap_hwmod omap3xxx_l4_per_hwmod = {
- .name = "l4_per_hwmod",
+ .name = "l4_per",
.class = &l4_hwmod_class,
.masters = omap3xxx_l4_per_masters,
.masters_cnt = ARRAY_SIZE(omap3xxx_l4_per_masters),
@@ -181,7 +181,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_wkup_masters[] = {
/* L4 WKUP */
static struct omap_hwmod omap3xxx_l4_wkup_hwmod = {
- .name = "l4_wkup_hwmod",
+ .name = "l4_wkup",
.class = &l4_hwmod_class,
.masters = omap3xxx_l4_wkup_masters,
.masters_cnt = ARRAY_SIZE(omap3xxx_l4_wkup_masters),
--
1.7.0.2
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 02/12] OMAP: hwmod: add class for DSP hwmods
2010-06-17 0:17 [PATCH 00/12] rework OPP layer to handle device-based OPPs Kevin Hilman
2010-06-17 0:17 ` [PATCH 01/12] OMAP2/3: hwmod: remove '_hwmod' suffix from names Kevin Hilman
@ 2010-06-17 0:17 ` Kevin Hilman
2010-06-17 0:17 ` [PATCH 03/12] OMAP3: hwmod: add data for OMAP3 IVA2 Kevin Hilman
` (9 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Kevin Hilman @ 2010-06-17 0:17 UTC (permalink / raw)
To: linux-omap; +Cc: nm, thara, b-cousson
Add a new hwmod class for DSP devices. To be used when hwmods
are created for DSP on OMAP3 (a.k.a. IVA2.)
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
arch/arm/mach-omap2/omap_hwmod_common_data.c | 3 +++
arch/arm/mach-omap2/omap_hwmod_common_data.h | 1 +
2 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.c b/arch/arm/mach-omap2/omap_hwmod_common_data.c
index 1e80b91..09f1e98 100644
--- a/arch/arm/mach-omap2/omap_hwmod_common_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_common_data.c
@@ -66,3 +66,6 @@ struct omap_hwmod_class mpu_hwmod_class = {
.name = "mpu"
};
+struct omap_hwmod_class dsp_hwmod_class = {
+ .name = "dsp"
+};
diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.h b/arch/arm/mach-omap2/omap_hwmod_common_data.h
index 3645a28..d03ebfa 100644
--- a/arch/arm/mach-omap2/omap_hwmod_common_data.h
+++ b/arch/arm/mach-omap2/omap_hwmod_common_data.h
@@ -20,5 +20,6 @@
extern struct omap_hwmod_class l3_hwmod_class;
extern struct omap_hwmod_class l4_hwmod_class;
extern struct omap_hwmod_class mpu_hwmod_class;
+extern struct omap_hwmod_class dsp_hwmod_class;
#endif
--
1.7.0.2
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 03/12] OMAP3: hwmod: add data for OMAP3 IVA2
2010-06-17 0:17 [PATCH 00/12] rework OPP layer to handle device-based OPPs Kevin Hilman
2010-06-17 0:17 ` [PATCH 01/12] OMAP2/3: hwmod: remove '_hwmod' suffix from names Kevin Hilman
2010-06-17 0:17 ` [PATCH 02/12] OMAP: hwmod: add class for DSP hwmods Kevin Hilman
@ 2010-06-17 0:17 ` Kevin Hilman
2010-06-17 0:17 ` [PATCH 04/12] OMAP: omap_device: ensure hwmod tracks attached omap_device pointer Kevin Hilman
` (8 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Kevin Hilman @ 2010-06-17 0:17 UTC (permalink / raw)
To: linux-omap; +Cc: nm, thara, b-cousson
Add hwmod data for DSP on OMAP3 (a.k.a. IVA2.)
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 41 ++++++++++++++++++++++++++++
1 files changed, 41 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index f1df4c9..571bb37 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -33,6 +33,7 @@
*/
static struct omap_hwmod omap3xxx_mpu_hwmod;
+static struct omap_hwmod omap3xxx_iva2_hwmod;
static struct omap_hwmod omap3xxx_l3_hwmod;
static struct omap_hwmod omap3xxx_l4_core_hwmod;
static struct omap_hwmod omap3xxx_l4_per_hwmod;
@@ -205,6 +206,45 @@ static struct omap_hwmod omap3xxx_mpu_hwmod = {
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
+/*
+ * IVA2_2 interface data
+ */
+
+static struct omap_hwmod_addr_space omap3xxx_iva2_addrs[] = {
+ {
+ .pa_start = 0x5c000000,
+ .pa_end = 0x5effffff,
+ .flags = ADDR_TYPE_RT
+ },
+};
+
+/* IVA2 <- L3 interface */
+static struct omap_hwmod_ocp_if omap3xxx_l3__iva2 = {
+ .master = &omap3xxx_l3_hwmod,
+ .slave = &omap3xxx_iva2_hwmod,
+ .clk = "iva2_ck",
+ .addr = omap3xxx_iva2_addrs,
+ .addr_cnt = ARRAY_SIZE(omap3xxx_iva2_addrs),
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_iva2_masters[] = {
+ &omap3xxx_l3__iva2,
+};
+
+/*
+ * IVA2 (IVA2)
+ */
+
+static struct omap_hwmod omap3xxx_iva2_hwmod = {
+ .name = "dsp",
+ .class = &dsp_hwmod_class,
+ .main_clk = "iva2_ck",
+ .masters = omap3xxx_iva2_masters,
+ .masters_cnt = ARRAY_SIZE(omap3xxx_iva2_masters),
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+};
+
/* SR common */
static struct omap_hwmod_sysc_fields omap34xx_sr_sysc_fields = {
.clkact_shift = 20,
@@ -373,6 +413,7 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
&omap3xxx_l4_per_hwmod,
&omap3xxx_l4_wkup_hwmod,
&omap3xxx_mpu_hwmod,
+ &omap3xxx_iva2_hwmod,
&omap34xx_sr1_hwmod,
&omap34xx_sr2_hwmod,
&omap36xx_sr1_hwmod,
--
1.7.0.2
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 04/12] OMAP: omap_device: ensure hwmod tracks attached omap_device pointer
2010-06-17 0:17 [PATCH 00/12] rework OPP layer to handle device-based OPPs Kevin Hilman
` (2 preceding siblings ...)
2010-06-17 0:17 ` [PATCH 03/12] OMAP3: hwmod: add data for OMAP3 IVA2 Kevin Hilman
@ 2010-06-17 0:17 ` Kevin Hilman
2010-06-17 0:17 ` [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3 Kevin Hilman
` (7 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Kevin Hilman @ 2010-06-17 0:17 UTC (permalink / raw)
To: linux-omap; +Cc: nm, thara, b-cousson
The omap_hwmod struct has a field to track the omap_device that is
attached to it, but it was not being assigned. Fix by assigning omap_device
pointer when omap_device is built.
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
arch/arm/plat-omap/omap_device.c | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index f899603..6614cba 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -359,8 +359,8 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
struct omap_device *od;
char *pdev_name2;
struct resource *res = NULL;
- int res_count;
- struct omap_hwmod **hwmods;
+ int i, res_count;
+ struct omap_hwmod *oh, **hwmods;
if (!ohs || oh_cnt == 0 || !pdev_name)
return ERR_PTR(-EINVAL);
@@ -416,6 +416,10 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
else
ret = omap_device_register(od);
+ /* each hwmod has a pointer to its attached omap_device */
+ for (i = 0, oh = hwmods[0]; i < oh_cnt; i++, oh++)
+ oh->od = od;
+
if (ret)
goto odbs_exit4;
--
1.7.0.2
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3
2010-06-17 0:17 [PATCH 00/12] rework OPP layer to handle device-based OPPs Kevin Hilman
` (3 preceding siblings ...)
2010-06-17 0:17 ` [PATCH 04/12] OMAP: omap_device: ensure hwmod tracks attached omap_device pointer Kevin Hilman
@ 2010-06-17 0:17 ` Kevin Hilman
2010-06-23 11:01 ` Gopinath, Thara
2010-06-17 0:17 ` [PATCH 06/12] OMAP: voltage: use device_initcall() Kevin Hilman
` (6 subsequent siblings)
11 siblings, 1 reply; 20+ messages in thread
From: Kevin Hilman @ 2010-06-17 0:17 UTC (permalink / raw)
To: linux-omap; +Cc: nm, thara, b-cousson
Create simple omap_devices for the main processors and busses.
This is required to support the forth-coming device-based OPP
approach, where OPPs are managed and tracked at the omap_device and
hwmod level.
Because these omap_devices are based on platform_devices, they cannot
be created until the driver core has been initialized. Therefore, move
the init of these into a device_initcall(). Also, OMAP PM init cannot
be done until after this step as it depends on the OPP layer.
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
arch/arm/mach-omap2/devices.c | 2 +
arch/arm/mach-omap2/io.c | 68 ++++++++++++++++++++++++++++--
arch/arm/plat-omap/include/plat/common.h | 4 ++
3 files changed, 70 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 03e6c9e..62920ac 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -15,6 +15,7 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
@@ -29,6 +30,7 @@
#include <mach/gpio.h>
#include <plat/mmc.h>
#include <plat/dma.h>
+#include <plat/omap_device.h>
#include "mux.h"
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 78d37c0..12a2836 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -44,7 +44,7 @@
#include <plat/clockdomain.h>
#include "clockdomains.h"
-#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
#include "omap3-opp.h"
/*
@@ -311,12 +311,71 @@ static int __init _omap2_init_reprogram_sdrc(void)
return v;
}
-void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
- struct omap_sdrc_params *sdrc_cs1)
+static struct omap_device_pm_latency *pm_lats;
+
+static struct device *mpu_dev; /* FIXME: needs clean SMP support */
+static struct device *dsp_dev;
+static struct device *l3_dev;
+
+struct device *omap_get_mpu_device(void)
+{
+ WARN_ON_ONCE(!mpu_dev);
+ return mpu_dev;
+}
+
+struct device *omap_get_dsp_device(void)
+{
+ WARN_ON_ONCE(!dsp_dev);
+ return dsp_dev;
+}
+
+struct device *omap_get_l3_device(void)
{
+ WARN_ON_ONCE(!l3_dev);
+ return l3_dev;
+}
+
+static int _init_omap_device(struct omap_hwmod *oh, void *user)
+{
+ struct omap_device *od;
+ const char *name = oh->name;
+ struct device **new_dev = (struct device **)user;
+
+ od = omap_device_build(name, 0, oh, NULL, 0, pm_lats, 0, false);
+ if (WARN(IS_ERR(od), "Could not build omap_device for %s\n", name))
+ return -ENODEV;
+
+ *new_dev = &od->pdev.dev;
+
+ return 0;
+}
+
+/*
+ * Build omap_devices for processors and bus.
+ */
+static void omap_init_processor_devices(void)
+{
+ omap_hwmod_for_each_by_class("mpu", _init_omap_device, &mpu_dev);
+ omap_hwmod_for_each_by_class("dsp", _init_omap_device, &dsp_dev);
+ omap_hwmod_for_each_by_class("l3", _init_omap_device, &l3_dev);
+}
+
+static int __init omap2_late_common_init(void)
+{
+ omap_init_processor_devices();
+
/* initialize the opp table if board file has not done so */
omap3_pm_init_opp_table();
+ omap_pm_if_init();
+
+ return 0;
+}
+device_initcall(omap2_late_common_init);
+
+void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
+ struct omap_sdrc_params *sdrc_cs1)
+{
pwrdm_init(powerdomains_omap);
clkdm_init(clockdomains_omap, clkdm_autodeps);
if (cpu_is_omap242x())
@@ -325,6 +384,7 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
omap2430_hwmod_init();
else if (cpu_is_omap34xx())
omap3xxx_hwmod_init();
+
omap2_mux_init();
omap_pm_if_early_init();
@@ -342,7 +402,7 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
omap_serial_early_init();
if (cpu_is_omap24xx() || cpu_is_omap34xx()) /* FIXME: OMAP4 */
omap_hwmod_late_init();
- omap_pm_if_init();
+
if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
_omap2_init_reprogram_sdrc();
diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h
index 5e4afbe..4ac08ca 100644
--- a/arch/arm/plat-omap/include/plat/common.h
+++ b/arch/arm/plat-omap/include/plat/common.h
@@ -89,4 +89,8 @@ void omap2_set_globals_uart(struct omap_globals *);
} \
})
+struct device *omap_get_mpu_device(void);
+struct device *omap_get_dsp_device(void);
+struct device *omap_get_l3_device(void);
+
#endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */
--
1.7.0.2
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 06/12] OMAP: voltage: use device_initcall()
2010-06-17 0:17 [PATCH 00/12] rework OPP layer to handle device-based OPPs Kevin Hilman
` (4 preceding siblings ...)
2010-06-17 0:17 ` [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3 Kevin Hilman
@ 2010-06-17 0:17 ` Kevin Hilman
2010-06-17 0:17 ` [PATCH 07/12] OMAP: SR: " Kevin Hilman
` (5 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Kevin Hilman @ 2010-06-17 0:17 UTC (permalink / raw)
To: linux-omap; +Cc: nm, thara, b-cousson
FIXME: this should be fixed in the SR/voltage v4 series
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
arch/arm/mach-omap2/voltage.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index b6d4f23..6e84ea1 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -1196,4 +1196,4 @@ static int __init omap_voltage_init(void)
}
return 0;
}
-arch_initcall(omap_voltage_init);
+device_initcall(omap_voltage_init);
--
1.7.0.2
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 07/12] OMAP: SR: use device_initcall()
2010-06-17 0:17 [PATCH 00/12] rework OPP layer to handle device-based OPPs Kevin Hilman
` (5 preceding siblings ...)
2010-06-17 0:17 ` [PATCH 06/12] OMAP: voltage: use device_initcall() Kevin Hilman
@ 2010-06-17 0:17 ` Kevin Hilman
2010-06-17 0:17 ` [PATCH 08/12] OMAP2: OPP: update API to be device-based Kevin Hilman
` (4 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Kevin Hilman @ 2010-06-17 0:17 UTC (permalink / raw)
To: linux-omap; +Cc: nm, thara, b-cousson
DROP ME: this should be fixed in SR/voltage v4 series
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
arch/arm/mach-omap2/sr_device.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index 5ca0253..dbf7603 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -174,4 +174,4 @@ static int __init omap_devinit_smartreflex(void)
{
return omap_hwmod_for_each_by_class("smartreflex", sr_dev_init, NULL);
}
-subsys_initcall(omap_devinit_smartreflex);
+device_initcall(omap_devinit_smartreflex);
--
1.7.0.2
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 08/12] OMAP2: OPP: update API to be device-based
2010-06-17 0:17 [PATCH 00/12] rework OPP layer to handle device-based OPPs Kevin Hilman
` (6 preceding siblings ...)
2010-06-17 0:17 ` [PATCH 07/12] OMAP: SR: " Kevin Hilman
@ 2010-06-17 0:17 ` Kevin Hilman
2010-06-17 0:17 ` [PATCH 09/12] OMAP3: CPUfreq: update to device-based OPP API Kevin Hilman
` (3 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Kevin Hilman @ 2010-06-17 0:17 UTC (permalink / raw)
To: linux-omap; +Cc: nm, thara, b-cousson
The current OPP layer is based on a unique identifier (OPP_MPU,
OPP_DSP, OPP_L3) which is not terribly portable or scalable for future
devices.
Since we'd also like to be able to manage OPPs for any device, this
patch changes the OPP API to be device-based instead of unique-ID
based. Essentially, this means passing a 'struct device' instead of a
unique ID to determine which set of OPPs to be used.
While making the API change, I also significantly changed the
internal management of OPPs to use a list per-device and within
each per-device struct, a list to manage OPPs. This resulted in
basically a rewrite of the internals.
Another signifcant change is that I removed the opp_init_list()
function in favor of just using multiple calls to opp_add(). In
combination with the internal list-based implmentation, this permitted
the removal of the need for using termin
Cc: Nishanth Menon <nm@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
arch/arm/mach-omap2/cpufreq34xx.c | 180 ++++++----------
arch/arm/plat-omap/include/plat/opp.h | 57 ++---
arch/arm/plat-omap/opp.c | 396 ++++++++++++++------------------
3 files changed, 261 insertions(+), 372 deletions(-)
diff --git a/arch/arm/mach-omap2/cpufreq34xx.c b/arch/arm/mach-omap2/cpufreq34xx.c
index b9d75cf..9d453b8 100644
--- a/arch/arm/mach-omap2/cpufreq34xx.c
+++ b/arch/arm/mach-omap2/cpufreq34xx.c
@@ -1,5 +1,4 @@
/*
- * arch/arm/mach-omap2/cpufreq34xx.c
* OMAP3 resource init/change_level/validate_level functions
*
* Copyright (C) 2009 - 2010 Texas Instruments Incorporated.
@@ -27,111 +26,80 @@
#include <plat/cpu.h>
#include "omap3-opp.h"
-static struct omap_opp_def __initdata omap34xx_mpu_rate_table[] = {
- /* OPP1 */
- OMAP_OPP_DEF(true, 125000000, 975000),
- /* OPP2 */
- OMAP_OPP_DEF(true, 250000000, 1075000),
- /* OPP3 */
- OMAP_OPP_DEF(true, 500000000, 1200000),
- /* OPP4 */
- OMAP_OPP_DEF(true, 550000000, 1270000),
- /* OPP5 */
- OMAP_OPP_DEF(true, 600000000, 1350000),
- /* Terminator */
- OMAP_OPP_DEF(0, 0, 0)
-};
+static struct omap_opp_def __initdata omap34xx_opp_def_list[] = {
+ /* MPU OPP1 */
+ OMAP_OPP_DEF("mpu", true, 125000000, 975000),
+ /* MPU OPP2 */
+ OMAP_OPP_DEF("mpu", true, 250000000, 1075000),
+ /* MPU OPP3 */
+ OMAP_OPP_DEF("mpu", true, 500000000, 1200000),
+ /* MPU OPP4 */
+ OMAP_OPP_DEF("mpu", true, 550000000, 1270000),
+ /* MPU OPP5 */
+ OMAP_OPP_DEF("mpu", true, 600000000, 1350000),
-static struct omap_opp_def __initdata omap34xx_l3_rate_table[] = {
/*
- * OPP1 - 41.5 MHz is disabled because: The voltage for that OPP is
+ * L3 OPP1 - 41.5 MHz is disabled because: The voltage for that OPP is
* almost the same than the one at 83MHz thus providing very little
* gain for the power point of view. In term of energy it will even
* increase the consumption due to the very negative performance
* impact that frequency will do to the MPU and the whole system in
* general.
*/
- OMAP_OPP_DEF(false, 41500000, 975000),
- /* OPP2 */
- OMAP_OPP_DEF(true, 83000000, 1050000),
- /* OPP3 */
- OMAP_OPP_DEF(true, 166000000, 1150000),
- /* Terminator */
- OMAP_OPP_DEF(0, 0, 0)
-};
-
-static struct omap_opp_def __initdata omap34xx_dsp_rate_table[] = {
- /* OPP1 */
- OMAP_OPP_DEF(true, 90000000, 975000),
- /* OPP2 */
- OMAP_OPP_DEF(true, 180000000, 1075000),
- /* OPP3 */
- OMAP_OPP_DEF(true, 360000000, 1200000),
- /* OPP4 */
- OMAP_OPP_DEF(true, 400000000, 1270000),
- /* OPP5 */
- OMAP_OPP_DEF(true, 430000000, 1350000),
- /* Terminator */
- OMAP_OPP_DEF(0, 0, 0)
+ OMAP_OPP_DEF("l3", false, 41500000, 975000),
+ /* L3 OPP2 */
+ OMAP_OPP_DEF("l3", true, 83000000, 1050000),
+ /* L3 OPP3 */
+ OMAP_OPP_DEF("l3", true, 166000000, 1150000),
+
+
+ /* DSP OPP1 */
+ OMAP_OPP_DEF("dsp", true, 90000000, 975000),
+ /* DSP OPP2 */
+ OMAP_OPP_DEF("dsp", true, 180000000, 1075000),
+ /* DSP OPP3 */
+ OMAP_OPP_DEF("dsp", true, 360000000, 1200000),
+ /* DSP OPP4 */
+ OMAP_OPP_DEF("dsp", true, 400000000, 1270000),
+ /* DSP OPP5 */
+ OMAP_OPP_DEF("dsp", true, 430000000, 1350000),
};
-
-static struct omap_opp_def __initdata omap36xx_mpu_rate_table[] = {
- /* OPP1 - OPP50 */
- OMAP_OPP_DEF(true, 300000000, 930000),
- /* OPP2 - OPP100 */
- OMAP_OPP_DEF(true, 600000000, 1100000),
- /* OPP3 - OPP-Turbo */
- OMAP_OPP_DEF(false, 800000000, 1260000),
- /* OPP4 - OPP-SB */
- OMAP_OPP_DEF(false, 1000000000, 1350000),
- /* Terminator */
- OMAP_OPP_DEF(0, 0, 0)
-};
-
-static struct omap_opp_def __initdata omap36xx_l3_rate_table[] = {
- /* OPP1 - OPP50 */
- OMAP_OPP_DEF(true, 100000000, 930000),
- /* OPP2 - OPP100, OPP-Turbo, OPP-SB */
- OMAP_OPP_DEF(true, 200000000, 1137500),
- /* Terminator */
- OMAP_OPP_DEF(0, 0, 0)
-};
-
-static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
- /* OPP1 - OPP50 */
- OMAP_OPP_DEF(true, 260000000, 930000),
- /* OPP2 - OPP100 */
- OMAP_OPP_DEF(true, 520000000, 1100000),
- /* OPP3 - OPP-Turbo */
- OMAP_OPP_DEF(false, 660000000, 1260000),
- /* OPP4 - OPP-SB */
- OMAP_OPP_DEF(false, 800000000, 1350000),
- /* Terminator */
- OMAP_OPP_DEF(0, 0, 0)
+static u32 omap34xx_opp_def_size = ARRAY_SIZE(omap34xx_opp_def_list);
+
+static struct omap_opp_def __initdata omap36xx_opp_def_list[] = {
+ /* MPU OPP1 - OPP50 */
+ OMAP_OPP_DEF("mpu", true, 300000000, 930000),
+ /* MPU OPP2 - OPP100 */
+ OMAP_OPP_DEF("mpu", true, 600000000, 1100000),
+ /* MPU OPP3 - OPP-Turbo */
+ OMAP_OPP_DEF("mpu", false, 800000000, 1260000),
+ /* MPU OPP4 - OPP-SB */
+ OMAP_OPP_DEF("mpu", false, 1000000000, 1350000),
+
+ /* L3 OPP1 - OPP50 */
+ OMAP_OPP_DEF("l3", true, 100000000, 930000),
+ /* L3 OPP2 - OPP100, OPP-Turbo, OPP-SB */
+ OMAP_OPP_DEF("l3", true, 200000000, 1137500),
+
+ /* DSP OPP1 - OPP50 */
+ OMAP_OPP_DEF("dsp", true, 260000000, 930000),
+ /* DSP OPP2 - OPP100 */
+ OMAP_OPP_DEF("dsp", true, 520000000, 1100000),
+ /* DSP OPP3 - OPP-Turbo */
+ OMAP_OPP_DEF("dsp", false, 660000000, 1260000),
+ /* DSP OPP4 - OPP-SB */
+ OMAP_OPP_DEF("dsp", false, 800000000, 1350000),
};
+static u32 omap36xx_opp_def_size = ARRAY_SIZE(omap36xx_opp_def_list);
/* Temp variable to allow multiple calls */
static u8 __initdata omap3_table_init;
int __init omap3_pm_init_opp_table(void)
{
+ struct omap_opp_def *opp_def, *omap3_opp_def_list;
+ u32 omap3_opp_def_size;
int i, r;
- struct omap_opp_def **omap3_opp_def_list;
- struct omap_opp_def *omap34xx_opp_def_list[] = {
- omap34xx_mpu_rate_table,
- omap34xx_l3_rate_table,
- omap34xx_dsp_rate_table
- };
- struct omap_opp_def *omap36xx_opp_def_list[] = {
- omap36xx_mpu_rate_table,
- omap36xx_l3_rate_table,
- omap36xx_dsp_rate_table
- };
- enum opp_t omap3_opps[] = {
- OPP_MPU,
- OPP_L3,
- OPP_DSP
- };
/*
* Allow multiple calls, but initialize only if not already initalized
@@ -142,34 +110,18 @@ int __init omap3_pm_init_opp_table(void)
omap3_table_init = 1;
omap3_opp_def_list = cpu_is_omap3630() ? omap36xx_opp_def_list :
- omap34xx_opp_def_list;
+ omap34xx_opp_def_list;
+ omap3_opp_def_size = cpu_is_omap3630() ? omap36xx_opp_def_size :
+ omap34xx_opp_def_size;
- for (i = 0; i < ARRAY_SIZE(omap3_opps); i++) {
- r = opp_init_list(omap3_opps[i], omap3_opp_def_list[i]);
+ opp_def = omap3_opp_def_list;
+ for (i = 0; i < omap3_opp_def_size; i++) {
+ r = opp_add(opp_def++);
if (r)
- break;
- }
- if (!r)
- return 0;
-
- /* Cascading error handling - disable all enabled OPPs */
- pr_err("%s: Failed to register %d OPP type\n", __func__,
- omap3_opps[i]);
- i--;
- while (i != -1) {
- struct omap_opp *opp;
- unsigned long freq = 0;
-
- do {
- opp = opp_find_freq_ceil(omap3_opps[i], &freq);
- if (IS_ERR(opp))
- break;
- opp_disable(opp);
- freq++;
- } while (1);
- i--;
+ pr_err("unable to add OPP %ld Hz for %s\n",
+ opp_def->freq, opp_def->hwmod_name);
}
- return r;
+ return 0;
}
diff --git a/arch/arm/plat-omap/include/plat/opp.h b/arch/arm/plat-omap/include/plat/opp.h
index 9f569e3..29e3d03 100644
--- a/arch/arm/plat-omap/include/plat/opp.h
+++ b/arch/arm/plat-omap/include/plat/opp.h
@@ -17,16 +17,7 @@
#include <linux/err.h>
#include <linux/cpufreq.h>
-#ifdef CONFIG_ARCH_OMAP3
-enum opp_t {
- OPP_MPU,
- OPP_L3,
- OPP_DSP,
- OPP_TYPES_MAX
-};
-#else
-#error "You need to populate the OPP types for OMAP chip type."
-#endif
+#include <plat/common.h>
/**
* struct omap_opp_def - OMAP OPP Definition
@@ -46,9 +37,12 @@ enum opp_t {
* of this - but this is handled by the appropriate driver.
*/
struct omap_opp_def {
- bool enabled;
+ char *hwmod_name;
+
unsigned long freq;
unsigned long u_volt;
+
+ bool enabled;
};
/*
@@ -56,8 +50,9 @@ struct omap_opp_def {
* To point at the end of a terminator of a list of OPPs,
* use OMAP_OPP_DEF(0, 0, 0)
*/
-#define OMAP_OPP_DEF(_enabled, _freq, _uv) \
+#define OMAP_OPP_DEF(_hwmod_name, _enabled, _freq, _uv) \
{ \
+ .hwmod_name = _hwmod_name, \
.enabled = _enabled, \
.freq = _freq, \
.u_volt = _uv, \
@@ -71,30 +66,26 @@ unsigned long opp_get_voltage(const struct omap_opp *opp);
unsigned long opp_get_freq(const struct omap_opp *opp);
-int opp_get_opp_count(enum opp_t opp_type);
+int opp_get_opp_count(struct device *dev);
-struct omap_opp *opp_find_freq_exact(enum opp_t opp_type,
+struct omap_opp *opp_find_freq_exact(struct device *dev,
unsigned long freq, bool enabled);
-struct omap_opp *opp_find_freq_floor(enum opp_t opp_type, unsigned long *freq);
-
-struct omap_opp *opp_find_freq_ceil(enum opp_t opp_type, unsigned long *freq);
+struct omap_opp *opp_find_freq_floor(struct device *dev, unsigned long *freq);
+struct omap_opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq);
-int __init opp_init_list(enum opp_t opp_type,
- const struct omap_opp_def *opp_defs);
-
-int opp_add(enum opp_t opp_type, const struct omap_opp_def *opp_def);
+int opp_add(const struct omap_opp_def *opp_def);
int opp_enable(struct omap_opp *opp);
int opp_disable(struct omap_opp *opp);
-struct omap_opp * __deprecated opp_find_by_opp_id(enum opp_t opp_type,
+struct omap_opp *__deprecated opp_find_by_opp_id(struct device *dev,
u8 opp_id);
u8 __deprecated opp_get_opp_id(struct omap_opp *opp);
-void opp_init_cpufreq_table(enum opp_t opp_type,
+void opp_init_cpufreq_table(struct device *dev,
struct cpufreq_frequency_table **table);
#else
static inline unsigned long opp_get_voltage(const struct omap_opp *opp)
@@ -113,31 +104,26 @@ static inline int opp_get_opp_count(struct omap_opp *oppl)
}
static inline struct omap_opp *opp_find_freq_exact(struct omap_opp *oppl,
- unsigned long freq, bool enabled)
+ unsigned long freq,
+ bool enabled)
{
return ERR_PTR(-EINVAL);
}
static inline struct omap_opp *opp_find_freq_floor(struct omap_opp *oppl,
- unsigned long *freq)
+ unsigned long *freq)
{
return ERR_PTR(-EINVAL);
}
static inline struct omap_opp *opp_find_freq_ceil(struct omap_opp *oppl,
- unsigned long *freq)
-{
- return ERR_PTR(-EINVAL);
-}
-
-static inline
-struct omap_opp __init *opp_init_list(const struct omap_opp_def *opp_defs)
+ unsigned long *freq)
{
return ERR_PTR(-EINVAL);
}
static inline struct omap_opp *opp_add(struct omap_opp *oppl,
- const struct omap_opp_def *opp_def)
+ const struct omap_opp_def *opp_def)
{
return ERR_PTR(-EINVAL);
}
@@ -152,7 +138,7 @@ static inline int opp_disable(struct omap_opp *opp)
return 0;
}
-static inline struct omap_opp * __deprecated
+static inline struct omap_opp *__deprecated
opp_find_by_opp_id(struct omap_opp *opps, u8 opp_id)
{
return ERR_PTR(-EINVAL);
@@ -163,7 +149,8 @@ static inline u8 __deprecated opp_get_opp_id(struct omap_opp *opp)
return 0;
}
-static inline void opp_init_cpufreq_table(struct omap_opp *opps,
+static inline
+void opp_init_cpufreq_table(struct omap_opp *opps,
struct cpufreq_frequency_table **table)
{
}
diff --git a/arch/arm/plat-omap/opp.c b/arch/arm/plat-omap/opp.c
index 4833e2d..0273497 100644
--- a/arch/arm/plat-omap/opp.c
+++ b/arch/arm/plat-omap/opp.c
@@ -16,9 +16,12 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/cpufreq.h>
+#include <linux/err.h>
+#include <linux/list.h>
#include <plat/opp_twl_tps.h>
#include <plat/opp.h>
+#include <plat/omap_device.h>
/**
* struct omap_opp - OMAP OPP description structure
@@ -30,17 +33,50 @@
* This structure stores the OPP information for a given domain.
*/
struct omap_opp {
+ struct list_head node;
+
bool enabled;
unsigned long rate;
unsigned long u_volt;
u8 opp_id;
+
+ struct device_opp *dev_opp; /* containing device_opp struct */
};
-/* This maintains pointers to the start of each OPP array. */
-static struct omap_opp *_opp_list[OPP_TYPES_MAX];
+struct device_opp {
+ struct list_head node;
+
+ struct omap_hwmod *oh;
+ struct device *dev;
+
+ struct list_head opp_list;
+ u32 opp_count;
+ u32 enabled_opp_count;
+};
+
+static LIST_HEAD(dev_opp_list);
+
+/**
+ * find_device_opp() - find device_opp struct using device pointer
+ * @dev: device pointer used to lookup device OPPs
+ *
+ * Search list of device OPPs for one containing matching device.
+ *
+ * Returns pointer to 'struct device_opp' if found, otherwise -ENODEV.
+ */
+static struct device_opp *find_device_opp(struct device *dev)
+{
+ struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV);
+
+ list_for_each_entry(tmp_dev_opp, &dev_opp_list, node) {
+ if (tmp_dev_opp->dev == dev) {
+ dev_opp = tmp_dev_opp;
+ break;
+ }
+ }
-/* Detect end of opp array */
-#define OPP_TERM(opp) (!(opp)->rate && !(opp)->u_volt && !(opp)->enabled)
+ return dev_opp;
+}
/**
* opp_get_voltage() - Gets the voltage corresponding to an opp
@@ -55,6 +91,7 @@ unsigned long opp_get_voltage(const struct omap_opp *opp)
pr_err("%s: Invalid parameters being passed\n", __func__);
return 0;
}
+
return opp->u_volt;
}
@@ -71,6 +108,7 @@ unsigned long opp_get_freq(const struct omap_opp *opp)
pr_err("%s: Invalid parameters being passed\n", __func__);
return 0;
}
+
return opp->rate;
}
@@ -82,27 +120,24 @@ unsigned long opp_get_freq(const struct omap_opp *opp)
* Returns the struct omap_opp pointer corresponding to the given OPP
* ID @opp_id, or returns NULL on error.
*/
-struct omap_opp * __deprecated opp_find_by_opp_id(enum opp_t opp_type,
+struct omap_opp * __deprecated opp_find_by_opp_id(struct device *dev,
u8 opp_id)
{
- struct omap_opp *opps;
- int i = 0;
-
- if (unlikely(opp_type >= OPP_TYPES_MAX || !opp_id))
- return ERR_PTR(-EINVAL);
- opps = _opp_list[opp_type];
+ struct device_opp *dev_opp;
+ struct omap_opp *temp_opp, *opp = ERR_PTR(-ENODEV);
- if (!opps)
- return ERR_PTR(-ENOENT);
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp))
+ return opp;
- while (!OPP_TERM(&opps[i])) {
- if (opps[i].enabled && (opps[i].opp_id == opp_id))
- return &opps[i];
-
- i++;
+ list_for_each_entry(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->enabled && temp_opp->opp_id == opp_id) {
+ opp = temp_opp;
+ break;
+ }
}
- return ERR_PTR(-ENOENT);
+ return opp;
}
/**
@@ -117,6 +152,7 @@ u8 __deprecated opp_get_opp_id(struct omap_opp *opp)
pr_err("%s: Invalid parameter being passed\n", __func__);
return 0;
}
+
return opp->opp_id;
}
@@ -127,26 +163,15 @@ u8 __deprecated opp_get_opp_id(struct omap_opp *opp)
* This functions returns the number of opps if there are any OPPs enabled,
* else returns corresponding error value.
*/
-int opp_get_opp_count(enum opp_t opp_type)
+int opp_get_opp_count(struct device *dev)
{
- u8 n = 0;
- struct omap_opp *oppl;
+ struct device_opp *dev_opp;
- if (unlikely(opp_type >= OPP_TYPES_MAX)) {
- pr_err("%s: Invalid parameters being passed\n", __func__);
- return -EINVAL;
- }
-
- oppl = _opp_list[opp_type];
- if (!oppl)
- return -ENOENT;
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp))
+ return -ENODEV;
- while (!OPP_TERM(oppl)) {
- if (oppl->enabled)
- n++;
- oppl++;
- }
- return n;
+ return dev_opp->enabled_opp_count;
}
/**
@@ -163,28 +188,24 @@ int opp_get_opp_count(enum opp_t opp_type)
* for exact matching frequency and is enabled. if false, the match is for exact
* frequency which is disabled.
*/
-struct omap_opp *opp_find_freq_exact(enum opp_t opp_type,
+struct omap_opp *opp_find_freq_exact(struct device *dev,
unsigned long freq, bool enabled)
{
- struct omap_opp *oppl;
-
- if (unlikely(opp_type >= OPP_TYPES_MAX)) {
- pr_err("%s: Invalid parameters being passed\n", __func__);
- return ERR_PTR(-EINVAL);
- }
-
- oppl = _opp_list[opp_type];
+ struct device_opp *dev_opp;
+ struct omap_opp *temp_opp, *opp = ERR_PTR(-ENODEV);
- if (!oppl)
- return ERR_PTR(-ENOENT);
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp))
+ return opp;
- while (!OPP_TERM(oppl)) {
- if ((oppl->rate == freq) && (oppl->enabled == enabled))
+ list_for_each_entry(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->enabled && temp_opp->rate == freq) {
+ opp = temp_opp;
break;
- oppl++;
+ }
}
- return OPP_TERM(oppl) ? ERR_PTR(-ENOENT) : oppl;
+ return opp;
}
/**
@@ -214,33 +235,24 @@ struct omap_opp *opp_find_freq_exact(enum opp_t opp_type,
* freq++; * for next higher match *
* }
*/
-struct omap_opp *opp_find_freq_ceil(enum opp_t opp_type, unsigned long *freq)
+struct omap_opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
{
- struct omap_opp *oppl;
-
- if (unlikely(opp_type >= OPP_TYPES_MAX || !freq ||
- IS_ERR(freq))) {
- pr_err("%s: Invalid parameters being passed\n", __func__);
- return ERR_PTR(-EINVAL);
- }
+ struct device_opp *dev_opp;
+ struct omap_opp *temp_opp, *opp = ERR_PTR(-ENODEV);
- oppl = _opp_list[opp_type];
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp))
+ return opp;
- if (!oppl)
- return ERR_PTR(-ENOENT);
-
- while (!OPP_TERM(oppl)) {
- if (oppl->enabled && oppl->rate >= *freq)
+ list_for_each_entry(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->enabled && temp_opp->rate >= *freq) {
+ opp = temp_opp;
+ *freq = opp->rate;
break;
- oppl++;
+ }
}
- if (OPP_TERM(oppl))
- return ERR_PTR(-ENOENT);
-
- *freq = oppl->rate;
-
- return oppl;
+ return opp;
}
/**
@@ -270,36 +282,24 @@ struct omap_opp *opp_find_freq_ceil(enum opp_t opp_type, unsigned long *freq)
* freq--; * for next lower match *
* }
*/
-struct omap_opp *opp_find_freq_floor(enum opp_t opp_type, unsigned long *freq)
+struct omap_opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
{
- struct omap_opp *prev_opp, *oppl;
-
- if (unlikely(opp_type >= OPP_TYPES_MAX || !freq ||
- IS_ERR(freq))) {
- pr_err("%s: Invalid parameters being passed\n", __func__);
- return ERR_PTR(-EINVAL);
- }
- oppl = _opp_list[opp_type];
+ struct device_opp *dev_opp;
+ struct omap_opp *temp_opp, *opp = ERR_PTR(-ENODEV);
- if (!oppl)
- return ERR_PTR(-ENOENT);
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp))
+ return opp;
- prev_opp = oppl;
- while (!OPP_TERM(oppl)) {
- if (oppl->enabled) {
- if (oppl->rate > *freq)
- break;
- prev_opp = oppl;
+ list_for_each_entry_reverse(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->enabled && temp_opp->rate <= *freq) {
+ opp = temp_opp;
+ *freq = opp->rate;
+ break;
}
- oppl++;
}
- if (prev_opp->rate > *freq)
- return ERR_PTR(-ENOENT);
-
- *freq = prev_opp->rate;
-
- return prev_opp;
+ return opp;
}
/* wrapper to reuse converting opp_def to opp struct */
@@ -313,130 +313,79 @@ static void omap_opp_populate(struct omap_opp *opp,
/**
* opp_add() - Add an OPP table from a table definitions
- * @opp_type: OPP type under which we want to add our new OPP.
- * @opp_def: omap_opp_def to describe the OPP which we want to add to list.
+ * @opp_def: omap_opp_def to describe the OPP which we want to add.
*
* This function adds an opp definition to the opp list and returns status.
*/
-int opp_add(enum opp_t opp_type, const struct omap_opp_def *opp_def)
+int opp_add(const struct omap_opp_def *opp_def)
{
- struct omap_opp *opp, *oppt, *oppr, *oppl;
- u8 n, i, ins;
-
- if (unlikely(opp_type >= OPP_TYPES_MAX || !opp_def ||
- IS_ERR(opp_def))) {
- pr_err("%s: Invalid params being passed\n", __func__);
+ struct omap_hwmod *oh;
+ struct device *dev = NULL;
+ struct device_opp *tmp_dev_opp, *dev_opp = NULL;
+ struct omap_opp *opp, *new_opp;
+ struct platform_device *pdev;
+ struct list_head *head;
+ int i;
+
+ /* find the correct hwmod, and device */
+ if (!opp_def->hwmod_name) {
+ pr_err("%s: missing name of omap_hwmod, ignoring.\n", __func__);
return -EINVAL;
}
-
- n = 0;
- oppl = _opp_list[opp_type];
-
- if (!oppl)
- return -ENOENT;
-
- opp = oppl;
- while (!OPP_TERM(opp)) {
- n++;
- opp++;
- }
-
- /*
- * Allocate enough entries to copy the original list, plus the new
- * OPP, plus the concluding terminator
- */
- oppr = kzalloc(sizeof(struct omap_opp) * (n + 2), GFP_KERNEL);
- if (!oppr) {
- pr_err("%s: No memory for new opp array\n", __func__);
- return -ENOMEM;
+ oh = omap_hwmod_lookup(opp_def->hwmod_name);
+ if (!oh) {
+ pr_warn("%s: no hwmod for %s, cannot add OPPs.\n",
+ __func__, opp_def->hwmod_name);
+ return -EINVAL;
}
+ pdev = &oh->od->pdev;
+ dev = &oh->od->pdev.dev;
- /* Simple insertion sort */
- opp = _opp_list[opp_type];
- oppt = oppr;
- ins = 0;
- i = 1;
- do {
- if (ins || opp->rate < opp_def->freq) {
- memcpy(oppt, opp, sizeof(struct omap_opp));
- opp++;
- } else {
- omap_opp_populate(oppt, opp_def);
- ins++;
+ /* Check for existing list for 'dev' */
+ list_for_each_entry(tmp_dev_opp, &dev_opp_list, node) {
+ if (dev == tmp_dev_opp->dev) {
+ dev_opp = tmp_dev_opp;
+ break;
}
- oppt->opp_id = i;
- oppt++;
- i++;
- } while (!OPP_TERM(opp));
-
- /* If nothing got inserted, this belongs to the end */
- if (!ins) {
- omap_opp_populate(oppt, opp_def);
- oppt->opp_id = i;
- oppt++;
}
- _opp_list[opp_type] = oppr;
+ if (!dev_opp) {
+ /* Allocate a new device OPP table */
+ dev_opp = kzalloc(sizeof(struct device_opp), GFP_KERNEL);
+ if (WARN_ON(!dev_opp))
+ return -ENOMEM;
- /* Terminator implicitly added by kzalloc() */
-
- /* Free the old list */
- kfree(oppl);
-
- return 0;
-}
-
-/**
- * opp_init_list() - Initialize an opp list from the opp definitions
- * @opp_type: OPP type to initialize this list for.
- * @opp_defs: Initial opp definitions to create the list.
- *
- * This function creates a list of opp definitions and returns status.
- * This list can be used to further validation/search/modifications. New
- * opp entries can be added to this list by using opp_add().
- *
- * In the case of error, suitable error code is returned.
- */
-int __init opp_init_list(enum opp_t opp_type,
- const struct omap_opp_def *opp_defs)
-{
- struct omap_opp_def *t = (struct omap_opp_def *)opp_defs;
- struct omap_opp *oppl;
- u8 n = 0, i = 1;
+ dev_opp->oh = oh;
+ dev_opp->dev = &oh->od->pdev.dev;
+ INIT_LIST_HEAD(&dev_opp->opp_list);
- if (unlikely(opp_type >= OPP_TYPES_MAX || !opp_defs ||
- IS_ERR(opp_defs))) {
- pr_err("%s: Invalid params being passed\n", __func__);
- return -EINVAL;
- }
- /* Grab a count */
- while (t->enabled || t->freq || t->u_volt) {
- n++;
- t++;
+ list_add(&dev_opp->node, &dev_opp_list);
}
- /*
- * Allocate enough entries to copy the original list, plus the
- * concluding terminator
- */
- oppl = kzalloc(sizeof(struct omap_opp) * (n + 1), GFP_KERNEL);
- if (!oppl) {
- pr_err("%s: No memory for opp array\n", __func__);
+ /* allocate new OPP node */
+ new_opp = kzalloc(sizeof(struct omap_opp), GFP_KERNEL);
+ if (WARN_ON(!new_opp))
+ /* FIXME: free dev_opp ? */
return -ENOMEM;
- }
-
+ omap_opp_populate(new_opp, opp_def);
- _opp_list[opp_type] = oppl;
- while (n) {
- omap_opp_populate(oppl, opp_defs);
- oppl->opp_id = i;
- n--;
- oppl++;
- opp_defs++;
- i++;
+ /* Insert new OPP in order of increasing frequency */
+ head = &dev_opp->opp_list;
+ list_for_each_entry_reverse(opp, &dev_opp->opp_list, node) {
+ if (new_opp->rate >= opp->rate) {
+ head = &opp->node;
+ break;
+ }
}
+ list_add(&new_opp->node, head);
+ dev_opp->opp_count++;
+ if (new_opp->enabled)
+ dev_opp->enabled_opp_count++;
- /* Terminator implicitly added by kzalloc() */
+ /* renumber (deprecated) OPP IDs based on new order */
+ i = 0;
+ list_for_each_entry(opp, &dev_opp->opp_list, node)
+ opp->opp_id = i++;
return 0;
}
@@ -453,11 +402,18 @@ int __init opp_init_list(enum opp_t opp_type,
*/
int opp_enable(struct omap_opp *opp)
{
+ struct device_opp *dev_opp;
+
if (unlikely(!opp || IS_ERR(opp))) {
pr_err("%s: Invalid parameters being passed\n", __func__);
return -EINVAL;
}
+
+ if (!opp->enabled && opp->dev_opp)
+ opp->dev_opp->enabled_opp_count++;
+
opp->enabled = true;
+
return 0;
}
@@ -477,7 +433,12 @@ int opp_disable(struct omap_opp *opp)
pr_err("%s: Invalid parameters being passed\n", __func__);
return -EINVAL;
}
+
+ if (opp->enabled && opp->dev_opp)
+ opp->dev_opp->enabled_opp_count--;
+
opp->enabled = false;
+
return 0;
}
@@ -489,43 +450,32 @@ int opp_disable(struct omap_opp *opp)
* Generate a cpufreq table for a provided domain - this assumes that the
* opp list is already initialized and ready for usage
*/
-void opp_init_cpufreq_table(enum opp_t opp_type,
+void opp_init_cpufreq_table(struct device *dev,
struct cpufreq_frequency_table **table)
{
- int i = 0, j;
- int opp_num;
- struct cpufreq_frequency_table *freq_table;
+ struct device_opp *dev_opp;
struct omap_opp *opp;
+ struct cpufreq_frequency_table *freq_table;
+ int i = 0;
- if (opp_type >= OPP_TYPES_MAX) {
- pr_warning("%s: failed to initialize frequency"
- "table\n", __func__);
- return;
- }
-
- opp_num = opp_get_opp_count(opp_type);
- if (opp_num < 0) {
- pr_err("%s: no opp table?\n", __func__);
+ dev_opp = find_device_opp(dev);
+ if (WARN_ON(!dev_opp))
return;
- }
- freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) *
- (opp_num + 1), GFP_ATOMIC);
+ freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) *
+ (dev_opp->enabled_opp_count + 1), GFP_ATOMIC);
if (!freq_table) {
- pr_warning("%s: failed to allocate frequency"
- "table\n", __func__);
+ pr_warning("%s: failed to allocate frequency table\n",
+ __func__);
return;
}
- opp = _opp_list[opp_type];
- opp += opp_num;
- for (j = opp_num; j >= 0; j--) {
+ list_for_each_entry(opp, &dev_opp->opp_list, node) {
if (opp->enabled) {
freq_table[i].index = i;
freq_table[i].frequency = opp->rate / 1000;
i++;
}
- opp--;
}
freq_table[i].index = i;
--
1.7.0.2
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 09/12] OMAP3: CPUfreq: update to device-based OPP API
2010-06-17 0:17 [PATCH 00/12] rework OPP layer to handle device-based OPPs Kevin Hilman
` (7 preceding siblings ...)
2010-06-17 0:17 ` [PATCH 08/12] OMAP2: OPP: update API to be device-based Kevin Hilman
@ 2010-06-17 0:17 ` Kevin Hilman
2010-06-17 0:17 ` [PATCH 10/12] OMAP: voltage: update to new " Kevin Hilman
` (2 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Kevin Hilman @ 2010-06-17 0:17 UTC (permalink / raw)
To: linux-omap; +Cc: nm, thara, b-cousson
Update usage of OPP API to use new device-based API. This requires
getting the 'struct device' for the MPU and using that with the OPP
API.
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
arch/arm/plat-omap/cpu-omap.c | 12 ++++++++----
1 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
index 0674405..b086795 100644
--- a/arch/arm/plat-omap/cpu-omap.c
+++ b/arch/arm/plat-omap/cpu-omap.c
@@ -89,6 +89,7 @@ static int omap_target(struct cpufreq_policy *policy,
#endif
#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
unsigned long freq;
+ struct device *mpu_dev = omap_get_mpu_device();
#endif
int ret = 0;
@@ -115,7 +116,7 @@ static int omap_target(struct cpufreq_policy *policy,
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
freq = target_freq * 1000;
- if (opp_find_freq_ceil(OPP_MPU, &freq))
+ if (opp_find_freq_ceil(mpu_dev, &freq))
omap_pm_cpu_set_freq(freq);
#endif
return ret;
@@ -134,10 +135,13 @@ static int __init omap_cpu_init(struct cpufreq_policy *policy)
policy->cur = policy->min = policy->max = omap_getspeed(0);
- if (!cpu_is_omap34xx())
+ if (!cpu_is_omap34xx()) {
clk_init_cpufreq_table(&freq_table);
- else
- opp_init_cpufreq_table(OPP_MPU, &freq_table);
+ } else {
+ struct device *mpu_dev = omap_get_mpu_device();
+
+ opp_init_cpufreq_table(mpu_dev, &freq_table);
+ }
if (freq_table) {
result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
--
1.7.0.2
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 10/12] OMAP: voltage: update to new device-based OPP API
2010-06-17 0:17 [PATCH 00/12] rework OPP layer to handle device-based OPPs Kevin Hilman
` (8 preceding siblings ...)
2010-06-17 0:17 ` [PATCH 09/12] OMAP3: CPUfreq: update to device-based OPP API Kevin Hilman
@ 2010-06-17 0:17 ` Kevin Hilman
2010-06-17 0:17 ` [PATCH 11/12] OMAP: SRF: " Kevin Hilman
2010-06-17 0:17 ` [PATCH 12/12] OMAP: SRF: must be initialized before allowing constraints to be set Kevin Hilman
11 siblings, 0 replies; 20+ messages in thread
From: Kevin Hilman @ 2010-06-17 0:17 UTC (permalink / raw)
To: linux-omap; +Cc: nm, thara, b-cousson
The OPP API has changed to a device-based API. This patch updates
the usage of that API in the voltage layer.
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
arch/arm/mach-omap2/voltage.c | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 6e84ea1..d289691 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -102,7 +102,7 @@ struct vp_reg_val {
* @vp_reg : the register values, shifts, masks for various
* vp registers
* @volt_clk : the clock associated with the vdd.
- * @opp_type : the type of OPP associated with this vdd.
+ * @opp_dev : the 'struct device' associated with this vdd.
* @volt_data_count : Number of distinct voltages supported by this vdd.
* @nominal_volt : Nominal voltaged for this vdd.
* cmdval_reg : Voltage controller cmdval register.
@@ -113,7 +113,7 @@ struct omap_vdd_info{
struct vp_reg_offs vp_offs;
struct vp_reg_val vp_reg;
struct clk *volt_clk;
- int opp_type;
+ struct device *opp_dev;
int volt_data_count;
int id;
unsigned long nominal_volt;
@@ -385,7 +385,7 @@ static void __init omap3_vdd_data_configure(int vdd)
vdd_info[vdd].volt_clk = clk_get(NULL, "dpll1_ck");
WARN(IS_ERR(vdd_info[vdd].volt_clk),
"unable to get clock for VDD%d\n", vdd + 1);
- vdd_info[vdd].opp_type = OPP_MPU;
+ vdd_info[vdd].opp_dev = omap_get_mpu_device();
vdd_info[vdd].vp_reg.tranxdone_status =
OMAP3430_VP1_TRANXDONE_ST_MASK;
vdd_info[vdd].cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET;
@@ -411,7 +411,7 @@ static void __init omap3_vdd_data_configure(int vdd)
vdd_info[vdd].volt_clk = clk_get(NULL, "l3_ick");
WARN(IS_ERR(vdd_info[vdd].volt_clk),
"unable to get clock for VDD%d\n", vdd + 1);
- vdd_info[vdd].opp_type = OPP_L3;
+ vdd_info[vdd].opp_dev = omap_get_l3_device();
vdd_info[vdd].vp_reg.tranxdone_status =
OMAP3430_VP2_TRANXDONE_ST_MASK;
vdd_info[vdd].cmdval_reg = OMAP3_PRM_VC_CMD_VAL_1_OFFSET;
@@ -843,7 +843,7 @@ unsigned long get_curr_voltage(int vdd)
}
freq = vdd_info[vdd].volt_clk->rate;
- opp = opp_find_freq_ceil(vdd_info[vdd].opp_type, &freq);
+ opp = opp_find_freq_ceil(vdd_info[vdd].opp_dev, &freq);
if (IS_ERR(opp)) {
pr_warning("%s: Unable to find OPP for VDD%d freq%ld\n",
__func__, vdd + 1, freq);
--
1.7.0.2
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 11/12] OMAP: SRF: update to new device-based OPP API
2010-06-17 0:17 [PATCH 00/12] rework OPP layer to handle device-based OPPs Kevin Hilman
` (9 preceding siblings ...)
2010-06-17 0:17 ` [PATCH 10/12] OMAP: voltage: update to new " Kevin Hilman
@ 2010-06-17 0:17 ` Kevin Hilman
2010-06-17 0:17 ` [PATCH 12/12] OMAP: SRF: must be initialized before allowing constraints to be set Kevin Hilman
11 siblings, 0 replies; 20+ messages in thread
From: Kevin Hilman @ 2010-06-17 0:17 UTC (permalink / raw)
To: linux-omap; +Cc: nm, thara, b-cousson
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
arch/arm/mach-omap2/resource34xx.c | 95 ++++++++++++++++++++++-------------
1 files changed, 60 insertions(+), 35 deletions(-)
diff --git a/arch/arm/mach-omap2/resource34xx.c b/arch/arm/mach-omap2/resource34xx.c
index 7f39fc3..70b41bc 100644
--- a/arch/arm/mach-omap2/resource34xx.c
+++ b/arch/arm/mach-omap2/resource34xx.c
@@ -170,14 +170,15 @@ static DEFINE_MUTEX(dvfs_mutex);
*
* NOTE: this function is a standin for the timebeing as opp_id is deprecated
*/
-static int __deprecated opp_to_freq(unsigned long *freq, enum opp_t opp_type,
+static int __deprecated opp_to_freq(unsigned long *freq, struct device *dev,
u8 opp_id)
{
struct omap_opp *opp;
- BUG_ON(!freq || opp_type >= OPP_TYPES_MAX);
+ if (WARN_ON(!freq))
+ return -EINVAL;
- opp = opp_find_by_opp_id(opp_type, opp_id);
+ opp = opp_find_by_opp_id(dev, opp_id);
if (IS_ERR(opp))
return -EINVAL;
@@ -189,20 +190,19 @@ static int __deprecated opp_to_freq(unsigned long *freq, enum opp_t opp_type,
/**
* freq_to_opp - convert a frequency back to OPP ID (DEPRECATED)
* @opp_id: opp ID returned back to caller
- * @opp_type: OPP type where we need to look.
+ * @opp_dev: device where we need to look for OPPs
* @freq: frequency we are searching for
*
* return 0 and opp_id is populated if we find the freq, else, we return error
*
* NOTE: this function is a standin for the timebeing as opp_id is deprecated
*/
-static int __deprecated freq_to_opp(u8 *opp_id, enum opp_t opp_type,
+static int __deprecated freq_to_opp(u8 *opp_id, struct device *dev,
unsigned long freq)
{
struct omap_opp *opp;
- BUG_ON(opp_type >= OPP_TYPES_MAX);
- opp = opp_find_freq_ceil(opp_type, &freq);
+ opp = opp_find_freq_ceil(dev, &freq);
if (IS_ERR(opp))
return -EINVAL;
*opp_id = opp_get_opp_id(opp);
@@ -223,10 +223,12 @@ void init_opp(struct shared_resource *resp)
* to the opp set by u-boot.
*/
if (strcmp(resp->name, "vdd1_opp") == 0) {
+ struct device *dev = omap_get_mpu_device();
+
vdd1_resp = resp;
dpll1_clk = clk_get(NULL, "dpll1_ck");
dpll2_clk = clk_get(NULL, "dpll2_ck");
- ret = freq_to_opp(&opp_id, OPP_MPU, dpll1_clk->rate);
+ ret = freq_to_opp(&opp_id, dev, dpll1_clk->rate);
if (ret) {
pr_err("%s: initializing %s failed! !match for %ld\n",
__func__, resp->name, dpll1_clk->rate);
@@ -241,10 +243,12 @@ void init_opp(struct shared_resource *resp)
}
curr_vdd1_opp = opp_id;
} else if (strcmp(resp->name, "vdd2_opp") == 0) {
+ struct device *dev = omap_get_l3_device();
+
vdd2_resp = resp;
dpll3_clk = clk_get(NULL, "dpll3_m2_ck");
l3_clk = clk_get(NULL, "l3_ick");
- ret = freq_to_opp(&opp_id, OPP_L3, l3_clk->rate);
+ ret = freq_to_opp(&opp_id, dev, l3_clk->rate);
if (ret) {
pr_err("%s: initializing %s failed! !match for %ld\n",
__func__, resp->name, l3_clk->rate);
@@ -305,16 +309,20 @@ static int program_opp_freq(int res, int target_level, int current_level)
#ifndef CONFIG_CPU_FREQ
unsigned long mpu_cur_freq;
#endif
+ struct device *l3_dev = omap_get_l3_device();
/* Check if I can actually switch or not */
if (res == VDD1_OPP) {
- ret = opp_to_freq(&mpu_freq, OPP_MPU, target_level);
- ret |= opp_to_freq(&dsp_freq, OPP_DSP, target_level);
+ struct device *mpu_dev = omap_get_mpu_device();
+ struct device *dsp_dev = omap_get_dsp_device();
+
+ ret = opp_to_freq(&mpu_freq, mpu_dev, target_level);
+ ret |= opp_to_freq(&dsp_freq, dsp_dev, target_level);
#ifndef CONFIG_CPU_FREQ
- ret |= opp_to_freq(&mpu_cur_freq, OPP_MPU, current_level);
+ ret |= opp_to_freq(&mpu_cur_freq, mpu_dev, current_level);
#endif
} else {
- ret = opp_to_freq(&l3_freq, OPP_L3, target_level);
+ ret = opp_to_freq(&l3_freq, l3_dev, target_level);
}
/* we would have caught all bad levels earlier.. */
if (unlikely(ret))
@@ -349,14 +357,14 @@ static int program_opp_freq(int res, int target_level, int current_level)
return target_level;
}
-static int program_opp(int res, enum opp_t opp_type, int target_level,
+static int program_opp(int res, struct device *dev, int target_level,
int current_level)
{
int i, ret = 0, raise;
unsigned long freq;
/* See if have a freq associated, if not, invalid opp */
- ret = opp_to_freq(&freq, opp_type, target_level);
+ ret = opp_to_freq(&freq, dev, target_level);
if (unlikely(ret))
return ret;
@@ -379,12 +387,12 @@ static int program_opp(int res, enum opp_t opp_type, int target_level,
* transitioning from good to good OPP
* none of the following should fail..
*/
- oppx = opp_find_freq_exact(opp_type, freq, true);
+ oppx = opp_find_freq_exact(dev, freq, true);
BUG_ON(IS_ERR(oppx));
uvdc_target = opp_get_voltage(oppx);
- BUG_ON(opp_to_freq(&freq, opp_type, current_level));
- oppx = opp_find_freq_exact(opp_type, freq, true);
+ BUG_ON(opp_to_freq(&freq, dev, current_level));
+ oppx = opp_find_freq_exact(dev, freq, true);
BUG_ON(IS_ERR(oppx));
uvdc_current = opp_get_voltage(oppx);
@@ -405,6 +413,9 @@ int resource_set_opp_level(int res, u32 target_level, int flags)
struct cpufreq_freqs freqs_notify;
#endif
struct shared_resource *resp;
+ struct device *mpu_dev = omap_get_mpu_device();
+ struct device *dsp_dev = omap_get_dsp_device();
+ struct device *l3_dev = omap_get_l3_device();
if (res == VDD1_OPP)
resp = vdd1_resp;
@@ -418,10 +429,10 @@ int resource_set_opp_level(int res, u32 target_level, int flags)
/* Check if I can actually switch or not */
if (res == VDD1_OPP) {
- ret = opp_to_freq(&mpu_freq, OPP_MPU, target_level);
- ret |= opp_to_freq(&mpu_old_freq, OPP_MPU, resp->curr_level);
+ ret = opp_to_freq(&mpu_freq, mpu_dev, target_level);
+ ret |= opp_to_freq(&mpu_old_freq, mpu_dev, resp->curr_level);
} else {
- ret = opp_to_freq(&l3_freq, OPP_L3, target_level);
+ ret = opp_to_freq(&l3_freq, l3_dev, target_level);
}
if (ret)
return ret;
@@ -440,7 +451,7 @@ int resource_set_opp_level(int res, u32 target_level, int flags)
/* Send pre notification to CPUFreq */
cpufreq_notify_transition(&freqs_notify, CPUFREQ_PRECHANGE);
#endif
- resp->curr_level = program_opp(res, OPP_MPU, target_level,
+ resp->curr_level = program_opp(res, mpu_dev, target_level,
resp->curr_level);
#ifdef CONFIG_CPU_FREQ
/* Send a post notification to CPUFreq */
@@ -451,7 +462,7 @@ int resource_set_opp_level(int res, u32 target_level, int flags)
mutex_unlock(&dvfs_mutex);
return 0;
}
- resp->curr_level = program_opp(res, OPP_L3, target_level,
+ resp->curr_level = program_opp(res, l3_dev, target_level,
resp->curr_level);
}
mutex_unlock(&dvfs_mutex);
@@ -478,23 +489,24 @@ int set_opp(struct shared_resource *resp, u32 target_level)
} else if (resp == vdd2_resp) {
unsigned long req_l3_freq;
struct omap_opp *oppx = NULL;
+ struct device *l3_dev = omap_get_l3_device();
/* Convert the tput in KiB/s to Bus frequency in MHz */
req_l3_freq = (target_level * 1000)/4;
/* Do I have a best match? */
- oppx = opp_find_freq_ceil(OPP_L3, &req_l3_freq);
+ oppx = opp_find_freq_ceil(l3_dev, &req_l3_freq);
if (IS_ERR(oppx)) {
/* Give me the best we got */
req_l3_freq = ULONG_MAX;
- oppx = opp_find_freq_floor(OPP_L3, &req_l3_freq);
+ oppx = opp_find_freq_floor(l3_dev, &req_l3_freq);
}
/* uh uh.. no OPPs?? */
BUG_ON(IS_ERR(oppx));
target_level = 0;
- ret = freq_to_opp((u8 *)&target_level, OPP_L3, req_l3_freq);
+ ret = freq_to_opp((u8 *)&target_level, l3_dev, req_l3_freq);
/* we dont expect this to fail */
BUG_ON(ret);
@@ -512,10 +524,13 @@ int set_opp(struct shared_resource *resp, u32 target_level)
int validate_opp(struct shared_resource *resp, u32 target_level)
{
unsigned long x;
+ struct device *mpu_dev = omap_get_mpu_device();
+ struct device *dsp_dev = omap_get_dsp_device();
+
if (strcmp(resp->name, "mpu_freq") == 0)
- return opp_to_freq(&x, OPP_MPU, target_level);
+ return opp_to_freq(&x, mpu_dev, target_level);
else if (strcmp(resp->name, "dsp_freq") == 0)
- return opp_to_freq(&x, OPP_DSP, target_level);
+ return opp_to_freq(&x, dsp_dev, target_level);
return 0;
}
@@ -527,6 +542,9 @@ void init_freq(struct shared_resource *resp)
char *linked_res_name;
int ret = -EINVAL;
unsigned long freq = 0;
+ struct device *mpu_dev = omap_get_mpu_device();
+ struct device *dsp_dev = omap_get_dsp_device();
+
resp->no_of_users = 0;
linked_res_name = (char *)resp->resource_data;
@@ -535,14 +553,16 @@ void init_freq(struct shared_resource *resp)
*/
if (strcmp(resp->name, "mpu_freq") == 0)
/* MPU freq in Mhz */
- ret = opp_to_freq(&freq, OPP_MPU, curr_vdd1_opp);
+ ret = opp_to_freq(&freq, mpu_dev, curr_vdd1_opp);
else if (strcmp(resp->name, "dsp_freq") == 0)
/* DSP freq in Mhz */
- ret = opp_to_freq(&freq, OPP_DSP, curr_vdd1_opp);
+ ret = opp_to_freq(&freq, dsp_dev, curr_vdd1_opp);
if (ret)
- pr_err("%s: initializing frequency failed!\n", __func__);
+ pr_err("%s: initializing frequency failed for %s!\n",
+ __func__, resp->name);
resp->curr_level = freq;
+
return;
}
@@ -550,14 +570,16 @@ int set_freq(struct shared_resource *resp, u32 target_level)
{
u8 vdd1_opp;
int ret = -EINVAL;
+ struct device *mpu_dev = omap_get_mpu_device();
+ struct device *dsp_dev = omap_get_dsp_device();
if (strcmp(resp->name, "mpu_freq") == 0) {
- ret = freq_to_opp(&vdd1_opp, OPP_MPU, target_level);
+ ret = freq_to_opp(&vdd1_opp, mpu_dev, target_level);
if (!ret)
ret = resource_request("vdd1_opp", &dummy_mpu_dev,
vdd1_opp);
} else if (strcmp(resp->name, "dsp_freq") == 0) {
- ret = freq_to_opp(&vdd1_opp, OPP_DSP, target_level);
+ ret = freq_to_opp(&vdd1_opp, dsp_dev, target_level);
if (!ret)
ret = resource_request("vdd1_opp", &dummy_dsp_dev,
vdd1_opp);
@@ -570,9 +592,12 @@ int set_freq(struct shared_resource *resp, u32 target_level)
int validate_freq(struct shared_resource *resp, u32 target_level)
{
u8 x;
+ struct device *mpu_dev = omap_get_mpu_device();
+ struct device *dsp_dev = omap_get_dsp_device();
+
if (strcmp(resp->name, "mpu_freq") == 0)
- return freq_to_opp(&x, OPP_MPU, target_level);
+ return freq_to_opp(&x, mpu_dev, target_level);
else if (strcmp(resp->name, "dsp_freq") == 0)
- return freq_to_opp(&x, OPP_DSP, target_level);
+ return freq_to_opp(&x, dsp_dev, target_level);
return 0;
}
--
1.7.0.2
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 12/12] OMAP: SRF: must be initialized before allowing constraints to be set
2010-06-17 0:17 [PATCH 00/12] rework OPP layer to handle device-based OPPs Kevin Hilman
` (10 preceding siblings ...)
2010-06-17 0:17 ` [PATCH 11/12] OMAP: SRF: " Kevin Hilman
@ 2010-06-17 0:17 ` Kevin Hilman
11 siblings, 0 replies; 20+ messages in thread
From: Kevin Hilman @ 2010-06-17 0:17 UTC (permalink / raw)
To: linux-omap; +Cc: nm, thara, b-cousson
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
arch/arm/plat-omap/omap-pm-srf.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-omap/omap-pm-srf.c b/arch/arm/plat-omap/omap-pm-srf.c
index 5ebcda3..bf9163e 100644
--- a/arch/arm/plat-omap/omap-pm-srf.c
+++ b/arch/arm/plat-omap/omap-pm-srf.c
@@ -29,6 +29,8 @@
#define LAT_RES_POSTAMBLE "_latency"
#define MAX_LATENCY_RES_NAME 30
+static int initialized;
+
/**
* get_lat_res_name - gets the latency resource name given a power domain name
* @pwrdm_name: Name of the power domain.
@@ -52,6 +54,9 @@ void get_lat_res_name(const char *pwrdm_name, char **lat_name, int size)
void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t)
{
+ if (!initialized)
+ return;
+
if (!dev || t < -1) {
WARN_ON(1);
return;
@@ -291,6 +296,8 @@ int __init omap_pm_if_early_init(void)
int __init omap_pm_if_init(void)
{
resource_init(resources_omap);
+ initialized = 1;
+
return 0;
}
--
1.7.0.2
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH 01/12] OMAP2/3: hwmod: remove '_hwmod' suffix from names
2010-06-17 0:17 ` [PATCH 01/12] OMAP2/3: hwmod: remove '_hwmod' suffix from names Kevin Hilman
@ 2010-06-17 14:23 ` Kevin Hilman
0 siblings, 0 replies; 20+ messages in thread
From: Kevin Hilman @ 2010-06-17 14:23 UTC (permalink / raw)
To: linux-omap; +Cc: nm, thara, b-cousson
Kevin Hilman <khilman@deeprootsystems.com> writes:
> As per new naming convention for hwmods, remove the redundant _hwmod suffix
> from all hwmod names.
>
> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
This duplicates a patch already done by Benoit[1], but mine
incorrectly renames l3. I'll drop mine in favor of Benoit's version.
Kevin
[1] https://patchwork.kernel.org/patch/101953/
^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3
2010-06-17 0:17 ` [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3 Kevin Hilman
@ 2010-06-23 11:01 ` Gopinath, Thara
2010-06-23 14:48 ` Kevin Hilman
0 siblings, 1 reply; 20+ messages in thread
From: Gopinath, Thara @ 2010-06-23 11:01 UTC (permalink / raw)
To: Kevin Hilman, linux-omap@vger.kernel.org; +Cc: Menon, Nishanth, Cousson, Benoit
>>-----Original Message-----
>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>Sent: Thursday, June 17, 2010 5:47 AM
>>To: linux-omap@vger.kernel.org
>>Cc: Menon, Nishanth; Gopinath, Thara; Cousson, Benoit
>>Subject: [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3
>>
>>Create simple omap_devices for the main processors and busses.
>>
>>This is required to support the forth-coming device-based OPP
>>approach, where OPPs are managed and tracked at the omap_device and
>>hwmod level.
>>
>>Because these omap_devices are based on platform_devices, they cannot
>>be created until the driver core has been initialized. Therefore, move
>>the init of these into a device_initcall(). Also, OMAP PM init cannot
>>be done until after this step as it depends on the OPP layer.
>>
>>Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
>>---
>> arch/arm/mach-omap2/devices.c | 2 +
>> arch/arm/mach-omap2/io.c | 68 ++++++++++++++++++++++++++++--
>> arch/arm/plat-omap/include/plat/common.h | 4 ++
>> 3 files changed, 70 insertions(+), 4 deletions(-)
>>
>>diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
>>index 03e6c9e..62920ac 100644
>>--- a/arch/arm/mach-omap2/devices.c
>>+++ b/arch/arm/mach-omap2/devices.c
>>@@ -15,6 +15,7 @@
>> #include <linux/platform_device.h>
>> #include <linux/io.h>
>> #include <linux/clk.h>
>>+#include <linux/err.h>
>>
>> #include <mach/hardware.h>
>> #include <mach/irqs.h>
>>@@ -29,6 +30,7 @@
>> #include <mach/gpio.h>
>> #include <plat/mmc.h>
>> #include <plat/dma.h>
>>+#include <plat/omap_device.h>
>>
>> #include "mux.h"
>>
>>diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
>>index 78d37c0..12a2836 100644
>>--- a/arch/arm/mach-omap2/io.c
>>+++ b/arch/arm/mach-omap2/io.c
>>@@ -44,7 +44,7 @@
>>
>> #include <plat/clockdomain.h>
>> #include "clockdomains.h"
>>-#include <plat/omap_hwmod.h>
>>+#include <plat/omap_device.h>
>>
>> #include "omap3-opp.h"
>> /*
>>@@ -311,12 +311,71 @@ static int __init _omap2_init_reprogram_sdrc(void)
>> return v;
>> }
>>
>>-void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
>>- struct omap_sdrc_params *sdrc_cs1)
>>+static struct omap_device_pm_latency *pm_lats;
>>+
>>+static struct device *mpu_dev; /* FIXME: needs clean SMP support */
>>+static struct device *dsp_dev;
>>+static struct device *l3_dev;
>>+
>>+struct device *omap_get_mpu_device(void)
>>+{
>>+ WARN_ON_ONCE(!mpu_dev);
>>+ return mpu_dev;
>>+}
>>+
>>+struct device *omap_get_dsp_device(void)
>>+{
>>+ WARN_ON_ONCE(!dsp_dev);
>>+ return dsp_dev;
>>+}
>>+
>>+struct device *omap_get_l3_device(void)
>> {
>>+ WARN_ON_ONCE(!l3_dev);
>>+ return l3_dev;
>>+}
>>+
>>+static int _init_omap_device(struct omap_hwmod *oh, void *user)
>>+{
>>+ struct omap_device *od;
>>+ const char *name = oh->name;
>>+ struct device **new_dev = (struct device **)user;
>>+
>>+ od = omap_device_build(name, 0, oh, NULL, 0, pm_lats, 0, false);
>>+ if (WARN(IS_ERR(od), "Could not build omap_device for %s\n", name))
>>+ return -ENODEV;
>>+
>>+ *new_dev = &od->pdev.dev;
>>+
>>+ return 0;
>>+}
>>+
>>+/*
>>+ * Build omap_devices for processors and bus.
>>+ */
>>+static void omap_init_processor_devices(void)
>>+{
>>+ omap_hwmod_for_each_by_class("mpu", _init_omap_device, &mpu_dev);
>>+ omap_hwmod_for_each_by_class("dsp", _init_omap_device, &dsp_dev);
>>+ omap_hwmod_for_each_by_class("l3", _init_omap_device, &l3_dev);
>>+}
>>+
>>+static int __init omap2_late_common_init(void)
>>+{
>>+ omap_init_processor_devices();
>>+
>> /* initialize the opp table if board file has not done so */
>> omap3_pm_init_opp_table();
>>
>>+ omap_pm_if_init();
>>+
>>+ return 0;
>>+}
>>+device_initcall(omap2_late_common_init);
Hello Kevin,
Any particular reason for making this a late init and not keeping this a part of init_common_hw?
The reason is the board files also have an option of calling/ overriding omap3_pm_init_opp_table. This happens really early in init_irq. (Refer board_3430sdp.c). So if a board file calls into
omap3_pm_init_opp_table, the opp initializations will happen before the omap_device pointers are build for mpu, iva and l3. So the dev pointers stored as part of dev_opp tables will be screwed up.
My personal preference would be to call the omap_init_processor_devices just after hwmod_late_init. This will remove any race conditions as above.
Regards
Thara
>>+
>>+void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
>>+ struct omap_sdrc_params *sdrc_cs1)
>>+{
>> pwrdm_init(powerdomains_omap);
>> clkdm_init(clockdomains_omap, clkdm_autodeps);
>> if (cpu_is_omap242x())
>>@@ -325,6 +384,7 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
>> omap2430_hwmod_init();
>> else if (cpu_is_omap34xx())
>> omap3xxx_hwmod_init();
>>+
>> omap2_mux_init();
>> omap_pm_if_early_init();
>>
>>@@ -342,7 +402,7 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
>> omap_serial_early_init();
>> if (cpu_is_omap24xx() || cpu_is_omap34xx()) /* FIXME: OMAP4 */
>> omap_hwmod_late_init();
>>- omap_pm_if_init();
>>+
>> if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
>> omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
>> _omap2_init_reprogram_sdrc();
>>diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h
>>index 5e4afbe..4ac08ca 100644
>>--- a/arch/arm/plat-omap/include/plat/common.h
>>+++ b/arch/arm/plat-omap/include/plat/common.h
>>@@ -89,4 +89,8 @@ void omap2_set_globals_uart(struct omap_globals *);
>> } \
>> })
>>
>>+struct device *omap_get_mpu_device(void);
>>+struct device *omap_get_dsp_device(void);
>>+struct device *omap_get_l3_device(void);
>>+
>> #endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */
>>--
>>1.7.0.2
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3
2010-06-23 11:01 ` Gopinath, Thara
@ 2010-06-23 14:48 ` Kevin Hilman
2010-06-23 15:03 ` Gopinath, Thara
0 siblings, 1 reply; 20+ messages in thread
From: Kevin Hilman @ 2010-06-23 14:48 UTC (permalink / raw)
To: Gopinath, Thara
Cc: linux-omap@vger.kernel.org, Menon, Nishanth, Cousson, Benoit
"Gopinath, Thara" <thara@ti.com> writes:
>>>-----Original Message-----
>>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>>Sent: Thursday, June 17, 2010 5:47 AM
>>>To: linux-omap@vger.kernel.org
>>>Cc: Menon, Nishanth; Gopinath, Thara; Cousson, Benoit
>>>Subject: [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3
>>>
>>>Create simple omap_devices for the main processors and busses.
>>>
>>>This is required to support the forth-coming device-based OPP
>>>approach, where OPPs are managed and tracked at the omap_device and
>>>hwmod level.
>>>
>>>Because these omap_devices are based on platform_devices, they cannot
>>>be created until the driver core has been initialized. Therefore, move
>>>the init of these into a device_initcall(). Also, OMAP PM init cannot
>>>be done until after this step as it depends on the OPP layer.
>>>
>>>Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
[...]
>>>+
>>>+static int __init omap2_late_common_init(void)
>>>+{
>>>+ omap_init_processor_devices();
>>>+
>>> /* initialize the opp table if board file has not done so */
>>> omap3_pm_init_opp_table();
>>>
>>>+ omap_pm_if_init();
>>>+
>>>+ return 0;
>>>+}
>>>+device_initcall(omap2_late_common_init);
> Hello Kevin,
>
> Any particular reason for making this a late init and not keeping
> this a part of init_common_hw? The reason is the board files also
> have an option of calling/ overriding omap3_pm_init_opp_table. This
> happens really early in init_irq. (Refer board_3430sdp.c). So if a
> board file calls into omap3_pm_init_opp_table, the opp
> initializations will happen before the omap_device pointers are
> build for mpu, iva and l3. So the dev pointers stored as part of
> dev_opp tables will be screwed up. My personal preference would be
> to call the omap_init_processor_devices just after
> hwmod_late_init. This will remove any race conditions as above.
I agree, I changed this yesterday and the current pm-wip/hwmods is
doing exactly this.
The initial reason for the late initcall was because omap_device_build
creates platform_devices and devices, but the driver core was not
yet initialized at this point.
To fix, I now create these devices as early platform devices so that
the init sequence can remain the same.
I'll be posting an updated version of this series today.
Kevin
^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3
2010-06-23 14:48 ` Kevin Hilman
@ 2010-06-23 15:03 ` Gopinath, Thara
2010-06-23 17:46 ` Kevin Hilman
0 siblings, 1 reply; 20+ messages in thread
From: Gopinath, Thara @ 2010-06-23 15:03 UTC (permalink / raw)
To: Kevin Hilman; +Cc: linux-omap@vger.kernel.org, Menon, Nishanth, Cousson, Benoit
>>-----Original Message-----
>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>Sent: Wednesday, June 23, 2010 8:19 PM
>>To: Gopinath, Thara
>>Cc: linux-omap@vger.kernel.org; Menon, Nishanth; Cousson, Benoit
>>Subject: Re: [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3
>>
>>"Gopinath, Thara" <thara@ti.com> writes:
>>
>>>>>-----Original Message-----
>>>>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>>>>Sent: Thursday, June 17, 2010 5:47 AM
>>>>>To: linux-omap@vger.kernel.org
>>>>>Cc: Menon, Nishanth; Gopinath, Thara; Cousson, Benoit
>>>>>Subject: [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3
>>>>>
>>>>>Create simple omap_devices for the main processors and busses.
>>>>>
>>>>>This is required to support the forth-coming device-based OPP
>>>>>approach, where OPPs are managed and tracked at the omap_device and
>>>>>hwmod level.
>>>>>
>>>>>Because these omap_devices are based on platform_devices, they cannot
>>>>>be created until the driver core has been initialized. Therefore, move
>>>>>the init of these into a device_initcall(). Also, OMAP PM init cannot
>>>>>be done until after this step as it depends on the OPP layer.
>>>>>
>>>>>Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
>>[...]
>>
>>>>>+
>>>>>+static int __init omap2_late_common_init(void)
>>>>>+{
>>>>>+ omap_init_processor_devices();
>>>>>+
>>>>> /* initialize the opp table if board file has not done so */
>>>>> omap3_pm_init_opp_table();
>>>>>
>>>>>+ omap_pm_if_init();
>>>>>+
>>>>>+ return 0;
>>>>>+}
>>>>>+device_initcall(omap2_late_common_init);
>>> Hello Kevin,
>>>
>>> Any particular reason for making this a late init and not keeping
>>> this a part of init_common_hw? The reason is the board files also
>>> have an option of calling/ overriding omap3_pm_init_opp_table. This
>>> happens really early in init_irq. (Refer board_3430sdp.c). So if a
>>> board file calls into omap3_pm_init_opp_table, the opp
>>> initializations will happen before the omap_device pointers are
>>> build for mpu, iva and l3. So the dev pointers stored as part of
>>> dev_opp tables will be screwed up. My personal preference would be
>>> to call the omap_init_processor_devices just after
>>> hwmod_late_init. This will remove any race conditions as above.
>>
>>I agree, I changed this yesterday and the current pm-wip/hwmods is
>>doing exactly this.
>>
>>The initial reason for the late initcall was because omap_device_build
>>creates platform_devices and devices, but the driver core was not
>>yet initialized at this point.
>>
>>To fix, I now create these devices as early platform devices so that
>>the init sequence can remain the same.
>>
>>I'll be posting an updated version of this series today.
But then early platform devices do not create a dev pointer. So you do two initializations, eh?
Regards
Thara
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3
2010-06-23 15:03 ` Gopinath, Thara
@ 2010-06-23 17:46 ` Kevin Hilman
2010-06-24 6:23 ` Gopinath, Thara
0 siblings, 1 reply; 20+ messages in thread
From: Kevin Hilman @ 2010-06-23 17:46 UTC (permalink / raw)
To: Gopinath, Thara
Cc: linux-omap@vger.kernel.org, Menon, Nishanth, Cousson, Benoit
"Gopinath, Thara" <thara@ti.com> writes:
>>>-----Original Message-----
>>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>>Sent: Wednesday, June 23, 2010 8:19 PM
>>>To: Gopinath, Thara
>>>Cc: linux-omap@vger.kernel.org; Menon, Nishanth; Cousson, Benoit
>>>Subject: Re: [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3
>>>
>>>"Gopinath, Thara" <thara@ti.com> writes:
>>>
>>>>>>-----Original Message-----
>>>>>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>>>>>Sent: Thursday, June 17, 2010 5:47 AM
>>>>>>To: linux-omap@vger.kernel.org
>>>>>>Cc: Menon, Nishanth; Gopinath, Thara; Cousson, Benoit
>>>>>>Subject: [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3
>>>>>>
>>>>>>Create simple omap_devices for the main processors and busses.
>>>>>>
>>>>>>This is required to support the forth-coming device-based OPP
>>>>>>approach, where OPPs are managed and tracked at the omap_device and
>>>>>>hwmod level.
>>>>>>
>>>>>>Because these omap_devices are based on platform_devices, they cannot
>>>>>>be created until the driver core has been initialized. Therefore, move
>>>>>>the init of these into a device_initcall(). Also, OMAP PM init cannot
>>>>>>be done until after this step as it depends on the OPP layer.
>>>>>>
>>>>>>Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
>>>[...]
>>>
>>>>>>+
>>>>>>+static int __init omap2_late_common_init(void)
>>>>>>+{
>>>>>>+ omap_init_processor_devices();
>>>>>>+
>>>>>> /* initialize the opp table if board file has not done so */
>>>>>> omap3_pm_init_opp_table();
>>>>>>
>>>>>>+ omap_pm_if_init();
>>>>>>+
>>>>>>+ return 0;
>>>>>>+}
>>>>>>+device_initcall(omap2_late_common_init);
>>>> Hello Kevin,
>>>>
>>>> Any particular reason for making this a late init and not keeping
>>>> this a part of init_common_hw? The reason is the board files also
>>>> have an option of calling/ overriding omap3_pm_init_opp_table. This
>>>> happens really early in init_irq. (Refer board_3430sdp.c). So if a
>>>> board file calls into omap3_pm_init_opp_table, the opp
>>>> initializations will happen before the omap_device pointers are
>>>> build for mpu, iva and l3. So the dev pointers stored as part of
>>>> dev_opp tables will be screwed up. My personal preference would be
>>>> to call the omap_init_processor_devices just after
>>>> hwmod_late_init. This will remove any race conditions as above.
>>>
>>>I agree, I changed this yesterday and the current pm-wip/hwmods is
>>>doing exactly this.
>>>
>>>The initial reason for the late initcall was because omap_device_build
>>>creates platform_devices and devices, but the driver core was not
>>>yet initialized at this point.
>>>
>>>To fix, I now create these devices as early platform devices so that
>>>the init sequence can remain the same.
>>>
>>>I'll be posting an updated version of this series today.
>
> But then early platform devices do not create a dev pointer. So you do
> two initializations, eh?
The early platform_device indeed has a struct device (it is a struct
inside the platfor_device.) The difference is that the struct device
has not been fully initialized (no device_add() has been called.)
For our purposes here, that is perfectly OK, as all that matters is that
there is a unique pointer to be used in the OPP layer.
Kevin
^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3
2010-06-23 17:46 ` Kevin Hilman
@ 2010-06-24 6:23 ` Gopinath, Thara
2010-06-24 18:09 ` Kevin Hilman
0 siblings, 1 reply; 20+ messages in thread
From: Gopinath, Thara @ 2010-06-24 6:23 UTC (permalink / raw)
To: Kevin Hilman; +Cc: linux-omap@vger.kernel.org, Menon, Nishanth, Cousson, Benoit
>>-----Original Message-----
>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>Sent: Wednesday, June 23, 2010 11:17 PM
>>To: Gopinath, Thara
>>Cc: linux-omap@vger.kernel.org; Menon, Nishanth; Cousson, Benoit
>>Subject: Re: [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3
>>
>>"Gopinath, Thara" <thara@ti.com> writes:
>>
>>>>>-----Original Message-----
>>>>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>>>>Sent: Wednesday, June 23, 2010 8:19 PM
>>>>>To: Gopinath, Thara
>>>>>Cc: linux-omap@vger.kernel.org; Menon, Nishanth; Cousson, Benoit
>>>>>Subject: Re: [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3
>>>>>
>>>>>"Gopinath, Thara" <thara@ti.com> writes:
>>>>>
>>>>>>>>-----Original Message-----
>>>>>>>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>>>>>>>Sent: Thursday, June 17, 2010 5:47 AM
>>>>>>>>To: linux-omap@vger.kernel.org
>>>>>>>>Cc: Menon, Nishanth; Gopinath, Thara; Cousson, Benoit
>>>>>>>>Subject: [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3
>>>>>>>>
>>>>>>>>Create simple omap_devices for the main processors and busses.
>>>>>>>>
>>>>>>>>This is required to support the forth-coming device-based OPP
>>>>>>>>approach, where OPPs are managed and tracked at the omap_device and
>>>>>>>>hwmod level.
>>>>>>>>
>>>>>>>>Because these omap_devices are based on platform_devices, they cannot
>>>>>>>>be created until the driver core has been initialized. Therefore, move
>>>>>>>>the init of these into a device_initcall(). Also, OMAP PM init cannot
>>>>>>>>be done until after this step as it depends on the OPP layer.
>>>>>>>>
>>>>>>>>Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
>>>>>[...]
>>>>>
>>>>>>>>+
>>>>>>>>+static int __init omap2_late_common_init(void)
>>>>>>>>+{
>>>>>>>>+ omap_init_processor_devices();
>>>>>>>>+
>>>>>>>> /* initialize the opp table if board file has not done so */
>>>>>>>> omap3_pm_init_opp_table();
>>>>>>>>
>>>>>>>>+ omap_pm_if_init();
>>>>>>>>+
>>>>>>>>+ return 0;
>>>>>>>>+}
>>>>>>>>+device_initcall(omap2_late_common_init);
>>>>>> Hello Kevin,
>>>>>>
>>>>>> Any particular reason for making this a late init and not keeping
>>>>>> this a part of init_common_hw? The reason is the board files also
>>>>>> have an option of calling/ overriding omap3_pm_init_opp_table. This
>>>>>> happens really early in init_irq. (Refer board_3430sdp.c). So if a
>>>>>> board file calls into omap3_pm_init_opp_table, the opp
>>>>>> initializations will happen before the omap_device pointers are
>>>>>> build for mpu, iva and l3. So the dev pointers stored as part of
>>>>>> dev_opp tables will be screwed up. My personal preference would be
>>>>>> to call the omap_init_processor_devices just after
>>>>>> hwmod_late_init. This will remove any race conditions as above.
>>>>>
>>>>>I agree, I changed this yesterday and the current pm-wip/hwmods is
>>>>>doing exactly this.
>>>>>
>>>>>The initial reason for the late initcall was because omap_device_build
>>>>>creates platform_devices and devices, but the driver core was not
>>>>>yet initialized at this point.
>>>>>
>>>>>To fix, I now create these devices as early platform devices so that
>>>>>the init sequence can remain the same.
>>>>>
>>>>>I'll be posting an updated version of this series today.
>>>
>>> But then early platform devices do not create a dev pointer. So you do
>>> two initializations, eh?
>>
>>The early platform_device indeed has a struct device (it is a struct
>>inside the platfor_device.) The difference is that the struct device
>>has not been fully initialized (no device_add() has been called.)
>>
>>For our purposes here, that is perfectly OK, as all that matters is that
>>there is a unique pointer to be used in the OPP layer.
Ok. I also think that the initcalls for voltage and sr_device should be moved back to the original.
The order of initialization should be as follows.
1. Build the generic omap devices (like mpu, l3, dsp etc) (part of init_common_hw)
2. Initialize the opp structures. (part of init_common_hw)
3. Intialize the voltage layer. (arch_initcall)
4. Initialize the smartreflex device layer(subsys initcall)
5. Initialize the smartreflex srive.(late initcall)
Regards
Thara
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3
2010-06-24 6:23 ` Gopinath, Thara
@ 2010-06-24 18:09 ` Kevin Hilman
0 siblings, 0 replies; 20+ messages in thread
From: Kevin Hilman @ 2010-06-24 18:09 UTC (permalink / raw)
To: Gopinath, Thara
Cc: linux-omap@vger.kernel.org, Menon, Nishanth, Cousson, Benoit
"Gopinath, Thara" <thara@ti.com> writes:
>>>-----Original Message-----
>>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>>Sent: Wednesday, June 23, 2010 11:17 PM
>>>To: Gopinath, Thara
>>>Cc: linux-omap@vger.kernel.org; Menon, Nishanth; Cousson, Benoit
>>>Subject: Re: [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3
>>>
>>>"Gopinath, Thara" <thara@ti.com> writes:
>>>
>>>>>>-----Original Message-----
>>>>>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>>>>>Sent: Wednesday, June 23, 2010 8:19 PM
>>>>>>To: Gopinath, Thara
>>>>>>Cc: linux-omap@vger.kernel.org; Menon, Nishanth; Cousson, Benoit
>>>>>>Subject: Re: [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3
>>>>>>
>>>>>>"Gopinath, Thara" <thara@ti.com> writes:
>>>>>>
>>>>>>>>>-----Original Message-----
>>>>>>>>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>>>>>>>>Sent: Thursday, June 17, 2010 5:47 AM
>>>>>>>>>To: linux-omap@vger.kernel.org
>>>>>>>>>Cc: Menon, Nishanth; Gopinath, Thara; Cousson, Benoit
>>>>>>>>>Subject: [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3
>>>>>>>>>
>>>>>>>>>Create simple omap_devices for the main processors and busses.
>>>>>>>>>
>>>>>>>>>This is required to support the forth-coming device-based OPP
>>>>>>>>>approach, where OPPs are managed and tracked at the omap_device and
>>>>>>>>>hwmod level.
>>>>>>>>>
>>>>>>>>>Because these omap_devices are based on platform_devices, they cannot
>>>>>>>>>be created until the driver core has been initialized. Therefore, move
>>>>>>>>>the init of these into a device_initcall(). Also, OMAP PM init cannot
>>>>>>>>>be done until after this step as it depends on the OPP layer.
>>>>>>>>>
>>>>>>>>>Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
>>>>>>[...]
>>>>>>
>>>>>>>>>+
>>>>>>>>>+static int __init omap2_late_common_init(void)
>>>>>>>>>+{
>>>>>>>>>+ omap_init_processor_devices();
>>>>>>>>>+
>>>>>>>>> /* initialize the opp table if board file has not done so */
>>>>>>>>> omap3_pm_init_opp_table();
>>>>>>>>>
>>>>>>>>>+ omap_pm_if_init();
>>>>>>>>>+
>>>>>>>>>+ return 0;
>>>>>>>>>+}
>>>>>>>>>+device_initcall(omap2_late_common_init);
>>>>>>> Hello Kevin,
>>>>>>>
>>>>>>> Any particular reason for making this a late init and not keeping
>>>>>>> this a part of init_common_hw? The reason is the board files also
>>>>>>> have an option of calling/ overriding omap3_pm_init_opp_table. This
>>>>>>> happens really early in init_irq. (Refer board_3430sdp.c). So if a
>>>>>>> board file calls into omap3_pm_init_opp_table, the opp
>>>>>>> initializations will happen before the omap_device pointers are
>>>>>>> build for mpu, iva and l3. So the dev pointers stored as part of
>>>>>>> dev_opp tables will be screwed up. My personal preference would be
>>>>>>> to call the omap_init_processor_devices just after
>>>>>>> hwmod_late_init. This will remove any race conditions as above.
>>>>>>
>>>>>>I agree, I changed this yesterday and the current pm-wip/hwmods is
>>>>>>doing exactly this.
>>>>>>
>>>>>>The initial reason for the late initcall was because omap_device_build
>>>>>>creates platform_devices and devices, but the driver core was not
>>>>>>yet initialized at this point.
>>>>>>
>>>>>>To fix, I now create these devices as early platform devices so that
>>>>>>the init sequence can remain the same.
>>>>>>
>>>>>>I'll be posting an updated version of this series today.
>>>>
>>>> But then early platform devices do not create a dev pointer. So you do
>>>> two initializations, eh?
>>>
>>>The early platform_device indeed has a struct device (it is a struct
>>>inside the platfor_device.) The difference is that the struct device
>>>has not been fully initialized (no device_add() has been called.)
>>>
>>>For our purposes here, that is perfectly OK, as all that matters is that
>>>there is a unique pointer to be used in the OPP layer.
>
> Ok. I also think that the initcalls for voltage and sr_device should be moved back to the original.
Agreed, I will drop those initcall change commits I made to the pm-sr
branch.
Kevin
> The order of initialization should be as follows.
>
> 1. Build the generic omap devices (like mpu, l3, dsp etc) (part of init_common_hw)
> 2. Initialize the opp structures. (part of init_common_hw)
> 3. Intialize the voltage layer. (arch_initcall)
> 4. Initialize the smartreflex device layer(subsys initcall)
> 5. Initialize the smartreflex srive.(late initcall)
>
> Regards
> Thara
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2010-06-24 18:09 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-06-17 0:17 [PATCH 00/12] rework OPP layer to handle device-based OPPs Kevin Hilman
2010-06-17 0:17 ` [PATCH 01/12] OMAP2/3: hwmod: remove '_hwmod' suffix from names Kevin Hilman
2010-06-17 14:23 ` Kevin Hilman
2010-06-17 0:17 ` [PATCH 02/12] OMAP: hwmod: add class for DSP hwmods Kevin Hilman
2010-06-17 0:17 ` [PATCH 03/12] OMAP3: hwmod: add data for OMAP3 IVA2 Kevin Hilman
2010-06-17 0:17 ` [PATCH 04/12] OMAP: omap_device: ensure hwmod tracks attached omap_device pointer Kevin Hilman
2010-06-17 0:17 ` [PATCH 05/12] OMAP: create omap_devices for MPU, DSP, L3 Kevin Hilman
2010-06-23 11:01 ` Gopinath, Thara
2010-06-23 14:48 ` Kevin Hilman
2010-06-23 15:03 ` Gopinath, Thara
2010-06-23 17:46 ` Kevin Hilman
2010-06-24 6:23 ` Gopinath, Thara
2010-06-24 18:09 ` Kevin Hilman
2010-06-17 0:17 ` [PATCH 06/12] OMAP: voltage: use device_initcall() Kevin Hilman
2010-06-17 0:17 ` [PATCH 07/12] OMAP: SR: " Kevin Hilman
2010-06-17 0:17 ` [PATCH 08/12] OMAP2: OPP: update API to be device-based Kevin Hilman
2010-06-17 0:17 ` [PATCH 09/12] OMAP3: CPUfreq: update to device-based OPP API Kevin Hilman
2010-06-17 0:17 ` [PATCH 10/12] OMAP: voltage: update to new " Kevin Hilman
2010-06-17 0:17 ` [PATCH 11/12] OMAP: SRF: " Kevin Hilman
2010-06-17 0:17 ` [PATCH 12/12] OMAP: SRF: must be initialized before allowing constraints to be set Kevin Hilman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).