Skip to contentSkip to conversation

arm: omap: smps regulator support

PATCH Superseded Tero Kristo 4 participants 11 messages Feb 16, 2012 – Feb 17, 2012

Subsystems (5)

v9 of 10 Superseded Latest is v10 →

lore
Share & tools
lore
#0 lore raw

v9 cover arm: omap: smps regulator support

Hi,

Following changes compared to previous version:

- updated to work with mainline
- added acked-by Samuel Ortiz to patch 4 MFD part (no changes done to that part of code since previous version)
- changed min_uV parameter name from patch 4/5 to target_uV

Tested with omap3 beagle: changed + measured voltages manually for vdd1 and vdd2.

-Tero

#1 lore raw

PATCH v9 1/5 TEMP: arm: OMAP3: beagle rev-c4: enable OPP6

Beagleboard rev-c4 has a speed sorted OMAP3530 chip which can run at 720MHz.

---
 arch/arm/mach-omap2/board-omap3beagle.c |   29 +++++++++++++++++++++++++++++
 arch/arm/mach-omap2/opp3xxx_data.c      |    4 ++++
 2 files changed, 33 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/board-omap3beagle.c +29 -0
index 7ffcd28..97678e5 100644
@@ -484,6 +484,35 @@ static void __init beagle_opp_init(void)
 		return;
 	}
 
+	if (omap3_beagle_version == OMAP3BEAGLE_BOARD_C4) {
+		struct device *mpu_dev, *iva_dev;
+
+		mpu_dev = omap_device_get_by_hwmod_name("mpu");
+		iva_dev = omap_device_get_by_hwmod_name("iva");
+
+		if (!mpu_dev || !iva_dev) {
+			pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n",
+				__func__, mpu_dev, iva_dev);
+			return;
+		}
+		/* Enable MPU 720MHz opp */
+		r = opp_enable(mpu_dev, 720000000);
+
+		/* Enable IVA 520MHz opp */
+		r |= opp_enable(iva_dev, 520000000);
+
+		if (r) {
+			pr_err("%s: failed to enable higher opp %d\n",
+				__func__, r);
+			/*
+			 * Cleanup - disable the higher freqs - we dont care
+			 * about the results
+			 */
+			opp_disable(mpu_dev, 720000000);
+			opp_disable(iva_dev, 520000000);
+		}
+	}
+
 	/* Custom OPP enabled for all xM versions */
 	if (cpu_is_omap3630()) {
 		struct device *mpu_dev, *iva_dev;
arch/arm/mach-omap2/opp3xxx_data.c +4 -0
index d95f3f9..a0f5fe1 100644
@@ -98,6 +98,8 @@ static struct omap_opp_def __initdata omap34xx_opp_def_list[] = {
 	OPP_INITIALIZER("mpu", true, 550000000, OMAP3430_VDD_MPU_OPP4_UV),
 	/* MPU OPP5 */
 	OPP_INITIALIZER("mpu", true, 600000000, OMAP3430_VDD_MPU_OPP5_UV),
+	/* MPU OPP6 : omap3530 high speed grade only */
+	OPP_INITIALIZER("mpu", false, 720000000, OMAP3430_VDD_MPU_OPP5_UV),
 
 	/*
 	 * L3 OPP1 - 41.5 MHz is disabled because: The voltage for that OPP is
@@ -123,6 +125,8 @@ static struct omap_opp_def __initdata omap34xx_opp_def_list[] = {
 	OPP_INITIALIZER("iva", true, 400000000, OMAP3430_VDD_MPU_OPP4_UV),
 	/* DSP OPP5 */
 	OPP_INITIALIZER("iva", true, 430000000, OMAP3430_VDD_MPU_OPP5_UV),
+	/* DSP OPP6 : omap3530 high speed grade only */
+	OPP_INITIALIZER("iva", false, 520000000, OMAP3430_VDD_MPU_OPP5_UV),
 };
 
 static struct omap_opp_def __initdata omap36xx_opp_def_list[] = {
Signature · 1 line
1.7.4.1
#2 lore raw

PATCH v9 2/5 arm: omap3: voltage: fix channel configuration

In reply to Tero Kristo

OMAP3 uses the default settings for VDD1 channel, otherwise the settings will overlap with VDD2 and attempting to modify VDD1 voltage will actually change VDD2 voltage.

---
 arch/arm/mach-omap2/vc3xxx_data.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/vc3xxx_data.c +1 -0
index a5ec7f8f..5d8eaf3 100644
@@ -46,6 +46,7 @@ static struct omap_vc_common omap3_vc_common = {
 };
 
 struct omap_vc_channel omap3_vc_mpu = {
+	.flags = OMAP_VC_CHANNEL_DEFAULT,
 	.common = &omap3_vc_common,
 	.smps_sa_reg	 = OMAP3_PRM_VC_SMPS_SA_OFFSET,
 	.smps_volra_reg	 = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
Signature · 1 line
1.7.4.1
#3 lore raw

PATCH v9 3/5 arm: omap3: add common twl configurations for vdd1 and vdd2

In reply to Tero Kristo

VDD1 and VDD2 are the core voltage regulators on OMAP3. VDD1 is used to control MPU/IVA voltage, and VDD2 is used for CORE. These regulators are needed by DVFS.

Voltage ranges for VDD1 and VDD2 are taken from twl4030/twl5030 data manual.

---
 arch/arm/mach-omap2/twl-common.c |   36 ++++++++++++++++++++++++++++++++++++
 1 files changed, 36 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/twl-common.c +36 -0
index 10b20c6..5f62e51 100644
@@ -126,6 +126,38 @@ static struct regulator_init_data omap3_vpll2_idata = {
 	.consumer_supplies		= omap3_vpll2_supplies,
 };
 
+static struct regulator_consumer_supply omap3_vdd1_supply[] = {
+	REGULATOR_SUPPLY("vcc", "mpu.0"),
+};
+
+static struct regulator_consumer_supply omap3_vdd2_supply[] = {
+	REGULATOR_SUPPLY("vcc", "l3_main.0"),
+};
+
+static struct regulator_init_data omap3_vdd1 = {
+	.constraints = {
+		.name			= "VDD1",
+		.min_uV			= 600000,
+		.max_uV			= 1450000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE,
+	},
+	.num_consumer_supplies		= ARRAY_SIZE(omap3_vdd1_supply),
+	.consumer_supplies		= omap3_vdd1_supply,
+};
+
+static struct regulator_init_data omap3_vdd2 = {
+	.constraints = {
+		.name			= "VDD2",
+		.min_uV			= 600000,
+		.max_uV			= 1450000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE,
+	},
+	.num_consumer_supplies		= ARRAY_SIZE(omap3_vdd2_supply),
+	.consumer_supplies		= omap3_vdd2_supply,
+};
+
 void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
 				  u32 pdata_flags, u32 regulators_flags)
 {
@@ -133,6 +165,10 @@ void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
 		pmic_data->irq_base = TWL4030_IRQ_BASE;
 	if (!pmic_data->irq_end)
 		pmic_data->irq_end = TWL4030_IRQ_END;
+	if (!pmic_data->vdd1)
+		pmic_data->vdd1 = &omap3_vdd1;
+	if (!pmic_data->vdd2)
+		pmic_data->vdd2 = &omap3_vdd2;
 
 	/* Common platform data configurations */
 	if (pdata_flags & TWL_COMMON_PDATA_USB && !pmic_data->usb)
Signature · 1 line
1.7.4.1
#4 lore raw

PATCH v9 3/5 arm: omap3: add common twl configurations for vdd1 and vdd2

Quoted 5 lines · Tero Kristo

VDD1 and VDD2 are the core voltage regulators on OMAP3. VDD1 is used to control MPU/IVA voltage, and VDD2 is used for CORE. These regulators are needed by DVFS.

Voltage ranges for VDD1 and VDD2 are taken from twl4030/twl5030 data manual.

Please provide documentation version referenced, else we will loose track of details at a later point of time.

Also should we rename VDD1 with vdd_mpu_iva and VDD2 as vdd_core to be readable?

Regards,
Nishanth Menon

Quoted 68 lines

---
?arch/arm/mach-omap2/twl-common.c | ? 36 ++++++++++++++++++++++++++++++++++++ ?1 files changed, 36 insertions(+), 0 deletions(-)

arch/arm/mach-omap2/twl-common.c +36 -0
index 10b20c6..5f62e51 100644
@@ -126,6 +126,38 @@ static struct regulator_init_data omap3_vpll2_idata = {
 ? ? ? ?.consumer_supplies ? ? ? ? ? ? ?= omap3_vpll2_supplies,
 ?};
 
+static struct regulator_consumer_supply omap3_vdd1_supply[] = {
+ ? ? ? REGULATOR_SUPPLY("vcc", "mpu.0"),
+};
+
+static struct regulator_consumer_supply omap3_vdd2_supply[] = {
+ ? ? ? REGULATOR_SUPPLY("vcc", "l3_main.0"),
+};
+
+static struct regulator_init_data omap3_vdd1 = {
+ ? ? ? .constraints = {
+ ? ? ? ? ? ? ? .name ? ? ? ? ? ? ? ? ? = "VDD1",
+ ? ? ? ? ? ? ? .min_uV ? ? ? ? ? ? ? ? = 600000,
+ ? ? ? ? ? ? ? .max_uV ? ? ? ? ? ? ? ? = 1450000,
+ ? ? ? ? ? ? ? .valid_modes_mask ? ? ? = REGULATOR_MODE_NORMAL,
+ ? ? ? ? ? ? ? .valid_ops_mask ? ? ? ? = REGULATOR_CHANGE_VOLTAGE,
+ ? ? ? },
+ ? ? ? .num_consumer_supplies ? ? ? ? ?= ARRAY_SIZE(omap3_vdd1_supply),
+ ? ? ? .consumer_supplies ? ? ? ? ? ? ?= omap3_vdd1_supply,
+};
+
+static struct regulator_init_data omap3_vdd2 = {
+ ? ? ? .constraints = {
+ ? ? ? ? ? ? ? .name ? ? ? ? ? ? ? ? ? = "VDD2",
+ ? ? ? ? ? ? ? .min_uV ? ? ? ? ? ? ? ? = 600000,
+ ? ? ? ? ? ? ? .max_uV ? ? ? ? ? ? ? ? = 1450000,
+ ? ? ? ? ? ? ? .valid_modes_mask ? ? ? = REGULATOR_MODE_NORMAL,
+ ? ? ? ? ? ? ? .valid_ops_mask ? ? ? ? = REGULATOR_CHANGE_VOLTAGE,
+ ? ? ? },
+ ? ? ? .num_consumer_supplies ? ? ? ? ?= ARRAY_SIZE(omap3_vdd2_supply),
+ ? ? ? .consumer_supplies ? ? ? ? ? ? ?= omap3_vdd2_supply,
+};
+
 ?void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?u32 pdata_flags, u32 regulators_flags)
 ?{
@@ -133,6 +165,10 @@ void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
 ? ? ? ? ? ? ? ?pmic_data->irq_base = TWL4030_IRQ_BASE;
 ? ? ? ?if (!pmic_data->irq_end)
 ? ? ? ? ? ? ? ?pmic_data->irq_end = TWL4030_IRQ_END;
+ ? ? ? if (!pmic_data->vdd1)
+ ? ? ? ? ? ? ? pmic_data->vdd1 = &omap3_vdd1;
+ ? ? ? if (!pmic_data->vdd2)
+ ? ? ? ? ? ? ? pmic_data->vdd2 = &omap3_vdd2;
 

? ? ? ?/* Common platform data configurations */
? ? ? ?if (pdata_flags & TWL_COMMON_PDATA_USB && !pmic_data->usb) --
1.7.4.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

#5 lore raw

PATCH v9 3/5 arm: omap3: add common twl configurations for vdd1 and vdd2

Quoted 9 lines · Nishanth
Quoted 5 lines · Tero Kristo

VDD1 and VDD2 are the core voltage regulators on OMAP3. VDD1 is used to control MPU/IVA voltage, and VDD2 is used for CORE. These regulators are needed by DVFS.

Voltage ranges for VDD1 and VDD2 are taken from twl4030/twl5030 data manual.

Please provide documentation version referenced, else we will loose track of details at a later point of time.

How should this be marked down? There are too many naming conventions for the TI docs, and I couldn't find any example from kernel commit logs for this. Personally I was using twl5030 es1.2 DM rev E / twl4030 es3.1 DM rev L. Or should the literature code be used? Or is there also some numerical version info available somewhere?

Quoted 2 lines

Also should we rename VDD1 with vdd_mpu_iva and VDD2 as vdd_core to be readable?

This can be changed if needed, it is just a name. regulator/twl-regulator.c is using vdd1 / vdd2 though, and also pmic_data struct uses these. All the other regulators use Vxx type naming also. These are the names I see on my board through sys/class/regulator:

dummy
VDD1
VDD2
VMMC1
VDAC
VDVI
VSIM

-Tero

Quoted 71 lines

Regards,
Nishanth Menon

Quoted 68 lines
---
 arch/arm/mach-omap2/twl-common.c |   36 ++++++++++++++++++++++++++++++++++++
 1 files changed, 36 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/twl-common.c +36 -1
index 10b20c6..5f62e51 100644
@@ -126,6 +126,38 @@ static struct regulator_init_data omap3_vpll2_idata = {
       .consumer_supplies              = omap3_vpll2_supplies,
 };
 
+static struct regulator_consumer_supply omap3_vdd1_supply[] = {
+       REGULATOR_SUPPLY("vcc", "mpu.0"),
+};
+
+static struct regulator_consumer_supply omap3_vdd2_supply[] = {
+       REGULATOR_SUPPLY("vcc", "l3_main.0"),
+};
+
+static struct regulator_init_data omap3_vdd1 = {
+       .constraints = {
+               .name                   = "VDD1",
+               .min_uV                 = 600000,
+               .max_uV                 = 1450000,
+               .valid_modes_mask       = REGULATOR_MODE_NORMAL,
+               .valid_ops_mask         = REGULATOR_CHANGE_VOLTAGE,
+       },
+       .num_consumer_supplies          = ARRAY_SIZE(omap3_vdd1_supply),
+       .consumer_supplies              = omap3_vdd1_supply,
+};
+
+static struct regulator_init_data omap3_vdd2 = {
+       .constraints = {
+               .name                   = "VDD2",
+               .min_uV                 = 600000,
+               .max_uV                 = 1450000,
+               .valid_modes_mask       = REGULATOR_MODE_NORMAL,
+               .valid_ops_mask         = REGULATOR_CHANGE_VOLTAGE,
+       },
+       .num_consumer_supplies          = ARRAY_SIZE(omap3_vdd2_supply),
+       .consumer_supplies              = omap3_vdd2_supply,
+};
+
 void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
                                 u32 pdata_flags, u32 regulators_flags)
 {
@@ -133,6 +165,10 @@ void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
               pmic_data->irq_base = TWL4030_IRQ_BASE;
       if (!pmic_data->irq_end)
               pmic_data->irq_end = TWL4030_IRQ_END;
+       if (!pmic_data->vdd1)
+               pmic_data->vdd1 = &omap3_vdd1;
+       if (!pmic_data->vdd2)
+               pmic_data->vdd2 = &omap3_vdd2;
 
       /* Common platform data configurations */
       if (pdata_flags & TWL_COMMON_PDATA_USB && !pmic_data->usb)
--

1.7.4.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

#6 lore raw

PATCH v9 3/5 arm: omap3: add common twl configurations for vdd1 and vdd2

Regards,
Nishanth Menon

Quoted 8 lines · Tero Kristo
Quoted 7 lines · Nishanth
Quoted 5 lines · Tero Kristo

VDD1 and VDD2 are the core voltage regulators on OMAP3. VDD1 is used to control MPU/IVA voltage, and VDD2 is used for CORE. These regulators are needed by DVFS.

Voltage ranges for VDD1 and VDD2 are taken from twl4030/twl5030 data manual.

Quoted 8 lines
Quoted 2 lines

Please provide documentation version referenced, else we will loose track of details at a later point of time.

How should this be marked down? There are too many naming conventions for the TI docs, and I couldn't find any example from kernel commit logs for this. Personally I was using twl5030 es1.2 DM rev E / twl4030 es3.1 DM rev L. Or should the literature code be used? Or is there also some numerical version info available somewhere?

Literature code is the best one. Adding, along with it, a human readable "TWL4030 ES3.1 DM rev L"
is even better :)

Quoted 8 lines
Quoted 1 line

Also should we rename VDD1 with vdd_mpu_iva and VDD2 as vdd_core to be readable?

This can be changed if needed, it is just a name. regulator/twl-regulator.c is using vdd1 / vdd2 though, and also pmic_data struct uses these. All the other regulators use Vxx type naming also. These are the names I see on my board through sys/class/regulator:

Quoted 7 lines

dummy
VDD1
VDD2
VMMC1
VDAC
VDVI
VSIM

no strong opinions on this - thinking from OMAP perspective, I read vdd_mpu,core,iva. from TWL perspective,
4030/5030 - VDD1,2
6030: VCORE1,2,3
6032: SMPS1...5
so I guess it is fine as long as it is in context.

#7 lore raw

PATCH v9 3/5 arm: omap3: add common twl configurations for vdd1 and vdd2

Hi Tero,

Quoted 37 lines · Nishanth
Quoted 8 lines · Tero Kristo
Quoted 7 lines · Nishanth
Quoted 5 lines · Tero Kristo

VDD1 and VDD2 are the core voltage regulators on OMAP3. VDD1 is used to control MPU/IVA voltage, and VDD2 is used for CORE. These regulators are needed by DVFS.

Voltage ranges for VDD1 and VDD2 are taken from twl4030/twl5030 data manual.

Quoted 8 lines
Quoted 2 lines

Please provide documentation version referenced, else we will loose track of details at a later point of time.

How should this be marked down? There are too many naming conventions for the TI docs, and I couldn't find any example from kernel commit logs for this. Personally I was using twl5030 es1.2 DM rev E / twl4030 es3.1 DM rev L. Or should the literature code be used? Or is there also some numerical version info available somewhere?

Literature code is the best one. Adding, along with it, a human readable "TWL4030 ES3.1 DM rev L"
is even better :)

Quoted 8 lines
Quoted 1 line

Also should we rename VDD1 with vdd_mpu_iva and VDD2 as vdd_core to be readable?

This can be changed if needed, it is just a name. regulator/twl-regulator.c is using vdd1 / vdd2 though, and also pmic_data struct uses these. All the other regulators use Vxx type naming also. These are the names I see on my board through sys/class/regulator:

Quoted 7 lines

dummy
VDD1
VDD2
VMMC1
VDAC
VDVI
VSIM

Quoted 6 lines

no strong opinions on this - thinking from OMAP perspective, I read vdd_mpu,core,iva. from TWL perspective,
4030/5030 - VDD1,2
6030: VCORE1,2,3
6032: SMPS1...5
so I guess it is fine as long as it is in context.

Yes, you should take care of using the proper name depending of the context.

For TWL point of view this is just 2 generic SMPS outputs so VDD1 and VDD2 are the only relevant name you can use.

As far as OMAP3 is concern, the power rails were named as well vdd1 and vdd2, but it was so confusing that we changed that on OMAP4 and maybe on 3630 to vdd_mpu, vdd_iva and vdd_core.

So using this terminology for OMAP power rails is strongly recommended.

Regards,
Benoit

#8 lore raw

PATCH v9 4/5 regulator: twl4030: add support for external voltage get/set

In reply to Tero Kristo

This is needed for SMPS regulators, which use the OMAP voltage processor for voltage get/set functions instead of the normal I2C channel. For this purpose, regulator_init_data->driver_data contents are expanded, it is now a struct which contains function pointers for the set/get voltage operations, a data pointer for these, and the previously used features bitmask.

---
 drivers/mfd/twl-core.c            |   16 ++++++++++++++-
 drivers/regulator/twl-regulator.c |   39 ++++++++++++++++++++++++++++++++----
 include/linux/i2c/twl.h           |    7 ++++++
 3 files changed, 56 insertions(+), 6 deletions(-)
drivers/mfd/twl-core.c +15 -1
index e04e04d..fae5f76 100644
@@ -619,6 +619,8 @@ add_regulator_linked(int num, struct regulator_init_data *pdata,
 		unsigned num_consumers, unsigned long features)
 {
 	unsigned sub_chip_id;
+	struct twl_regulator_driver_data drv_data;
+
 	/* regulator framework demands init_data ... */
 	if (!pdata)
 		return NULL;
@@ -628,7 +630,19 @@ add_regulator_linked(int num, struct regulator_init_data *pdata,
 		pdata->num_consumer_supplies = num_consumers;
 	}
 
-	pdata->driver_data = (void *)features;
+	if (pdata->driver_data) {
+		/* If we have existing drv_data, just add the flags */
+		struct twl_regulator_driver_data *tmp;
+		tmp = pdata->driver_data;
+		tmp->features |= features;
+	} else {
+		/* add new driver data struct, used only during init */
+		drv_data.features = features;
+		drv_data.set_voltage = NULL;
+		drv_data.get_voltage = NULL;
+		drv_data.data = NULL;
+		pdata->driver_data = &drv_data;
+	}
 
 	/* NOTE:  we currently ignore regulator IRQs, e.g. for short circuits */
 	sub_chip_id = twl_map[TWL_MODULE_PM_MASTER].sid;
drivers/regulator/twl-regulator.c +34 -5
index 181a2cf..0afc9e1a 100644
@@ -58,6 +58,16 @@ struct twlreg_info {
 
 	/* chip specific features */
 	unsigned long 		features;
+
+	/*
+	 * optional override functions for voltage set/get
+	 * these are currently only used for SMPS regulators
+	 */
+	int			(*get_voltage)(void *data);
+	int			(*set_voltage)(void *data, int target_uV);
+
+	/* data passed from board for external get/set voltage */
+	void			*data;
 };
 
 
@@ -522,15 +532,25 @@ twl4030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
 	struct twlreg_info *info = rdev_get_drvdata(rdev);
 	int vsel = DIV_ROUND_UP(min_uV - 600000, 12500);
 
-	twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS_4030,
-		vsel);
+	if (info->set_voltage) {
+		return info->set_voltage(info->data, min_uV);
+	} else {
+		twlreg_write(info, TWL_MODULE_PM_RECEIVER,
+			VREG_VOLTAGE_SMPS_4030, vsel);
+	}
+
 	return 0;
 }
 
 static int twl4030smps_get_voltage(struct regulator_dev *rdev)
 {
 	struct twlreg_info *info = rdev_get_drvdata(rdev);
-	int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER,
+	int vsel;
+
+	if (info->get_voltage)
+		return info->get_voltage(info->data);
+
+	vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER,
 		VREG_VOLTAGE_SMPS_4030);
 
 	return vsel * 12500 + 600000;
@@ -1052,6 +1072,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
 	struct regulator_init_data	*initdata;
 	struct regulation_constraints	*c;
 	struct regulator_dev		*rdev;
+	struct twl_regulator_driver_data	*drvdata;
 
 	for (i = 0, info = NULL; i < ARRAY_SIZE(twl_regs); i++) {
 		if (twl_regs[i].desc.id != pdev->id)
@@ -1066,8 +1087,16 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
 	if (!initdata)
 		return -EINVAL;
 
-	/* copy the features into regulator data */
-	info->features = (unsigned long)initdata->driver_data;
+	drvdata = initdata->driver_data;
+
+	if (!drvdata)
+		return -EINVAL;
+
+	/* copy the driver data into regulator data */
+	info->features = drvdata->features;
+	info->data = drvdata->data;
+	info->set_voltage = drvdata->set_voltage;
+	info->get_voltage = drvdata->get_voltage;
 
 	/* Constrain board-specific capabilities according to what
 	 * this driver and the chip itself can actually do.
include/linux/i2c/twl.h +7 -0
index 78d3465..08a82d3 100644
@@ -749,6 +749,13 @@ struct twl4030_platform_data {
 	struct regulator_init_data		*vio6025;
 };
 
+struct twl_regulator_driver_data {
+	int		(*set_voltage)(void *data, int target_uV);
+	int		(*get_voltage)(void *data);
+	void		*data;
+	unsigned long	features;
+};
+
 /*----------------------------------------------------------------------*/
 
 int twl4030_sih_setup(int module);
Signature · 1 line
1.7.4.1
#9 lore raw

PATCH v9 4/5 regulator: twl4030: add support for external voltage get/set

Quoted 6 lines · Tero Kristo

This is needed for SMPS regulators, which use the OMAP voltage processor for voltage get/set functions instead of the normal I2C channel. For this purpose, regulator_init_data->driver_data contents are expanded, it is now a struct which contains function pointers for the set/get voltage operations, a data pointer for these, and the previously used features bitmask.

Applied, thanks.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120216/c2f5c412/attachment.sig>

#10 lore raw

PATCH v9 5/5 arm: omap3: twl: add external controllers for core voltage regulators

In reply to Tero Kristo

VDD1 and VDD2 now use voltage processor for controlling the regulators. This is done by passing additional voltdm data during the regulator init.

---
 arch/arm/mach-omap2/twl-common.c |   33 +++++++++++++++++++++++++++++++--
 1 files changed, 31 insertions(+), 2 deletions(-)
arch/arm/mach-omap2/twl-common.c +31 -2
index 5f62e51..0c453e7 100644
@@ -31,12 +31,25 @@
 
 #include "twl-common.h"
 #include "pm.h"
+#include "voltage.h"
 
 static struct i2c_board_info __initdata pmic_i2c_board_info = {
 	.addr		= 0x48,
 	.flags		= I2C_CLIENT_WAKE,
 };
 
+static int twl_set_voltage(void *data, int target_uV)
+{
+	struct voltagedomain *voltdm = (struct voltagedomain *)data;
+	return voltdm_scale(voltdm, target_uV);
+}
+
+static int twl_get_voltage(void *data)
+{
+	struct voltagedomain *voltdm = (struct voltagedomain *)data;
+	return voltdm_get_voltage(voltdm);
+}
+
 void __init omap_pmic_init(int bus, u32 clkrate,
 			   const char *pmic_type, int pmic_irq,
 			   struct twl4030_platform_data *pmic_data)
@@ -158,6 +171,16 @@ static struct regulator_init_data omap3_vdd2 = {
 	.consumer_supplies		= omap3_vdd2_supply,
 };
 
+static struct twl_regulator_driver_data omap3_vdd1_drvdata = {
+	.get_voltage = twl_get_voltage,
+	.set_voltage = twl_set_voltage,
+};
+
+static struct twl_regulator_driver_data omap3_vdd2_drvdata = {
+	.get_voltage = twl_get_voltage,
+	.set_voltage = twl_set_voltage,
+};
+
 void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
 				  u32 pdata_flags, u32 regulators_flags)
 {
@@ -165,10 +188,16 @@ void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
 		pmic_data->irq_base = TWL4030_IRQ_BASE;
 	if (!pmic_data->irq_end)
 		pmic_data->irq_end = TWL4030_IRQ_END;
-	if (!pmic_data->vdd1)
+	if (!pmic_data->vdd1) {
+		omap3_vdd1.driver_data = &omap3_vdd1_drvdata;
+		omap3_vdd1_drvdata.data = voltdm_lookup("mpu_iva");
 		pmic_data->vdd1 = &omap3_vdd1;
-	if (!pmic_data->vdd2)
+	}
+	if (!pmic_data->vdd2) {
+		omap3_vdd2.driver_data = &omap3_vdd2_drvdata;
+		omap3_vdd2_drvdata.data = voltdm_lookup("core");
 		pmic_data->vdd2 = &omap3_vdd2;
+	}
 
 	/* Common platform data configurations */
 	if (pdata_flags & TWL_COMMON_PDATA_USB && !pmic_data->usb)
Signature · 1 line
1.7.4.1