SR Voltage Control Migration

Objective
On OMAP, several regulators of the external Power IC can be controlled either by software (by means of a control I²C link with the Power IC) or by hardware through the SmartReflex technology of the OMAP SoC (in which case the OMAP SoC communicates with the Power IC through another dedicated I²C link). On OMAP3, two regulators can be controlled by SmartReflex, three of them can be controlled by SmartReflex on OMAP4. At the moment, those regulators are not being handled by the Linux kernel regulator framework, since the concept of having a regulator being controlled by hardware doesn't fit naturally into the regulator framework design. Therefore, the objective of the work is to make this conversion happen.

Design
As SmartReflex is a technology part of the OMAP CPU and not the PowerIC, support for SmartReflex must be independent from the TWL regulator driver (currently in drivers/regulator/twl_regulator.c) : the TWL regulator driver should theorically be usable on a system that doesn't use an OMAP CPU with SmartReflex, and conversely, the SmartReflex support should theorically be usable with other PowerIC than the TWL. Integrating the SmartReflex support directly into the TWL regulator driver is therefore not an option.

However, from the rest of the system, we still want the SmartReflex-controllable regulators to look like normal regulators for the rest of the kernel, so that the regulator_get, regulator_enable, regulator_disable, regulator_put, regulator_set_voltage, regulator_get_voltage API (i.e the so-called consumer API, as visible in include/linux/regulator/consumer.h). The fact that a regulator is controlled by SmartReflex should be hidden behind this normal regulator API.

For these reasons, the proposed design is to add the concept of a TWL external controller, which would be described by the following structure :

struct twlreg_ext_ctrl { int (*set_voltage)(struct twlreg_ext_ctrl *, int min_uV, int max_uV); int (*get_voltage)(struct twlreg_ext_ctrl *, int min_uV, int max_uV); void *data; };

The TWL regulator driver is then modified so that when such an external controller is associated to a regulator, it would call the methods of the external controller to do the voltage set and voltage get operations.

Then, such a structure needs to be attached to the regulator. We have thought of two ways to implement this : static struct regulator_init_data beagle_vdd1 = { .constraints = { .name                  = "VDD1", .min_uV                = 700000, .max_uV                = 1800000, .valid_modes_mask      = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask        = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, },       .num_consumer_supplies  = 1, .consumer_supplies     = & beagle_vdd1_supply, .driver_data           = & reference_to_the_twlreg_ext_ctrl_structure_for_this_regulator, };
 * Attach the twlreg_ext_ctrl structure to the regulator_init_data structure, so that the external controller is known when the regulator is instantiated (see below for the example). Unfortunately, in the current code, at the time the regulators are instantiated, the OMAP voltage layer isn't initialized, so this solution doesn't work with the current initialization ordering. So we implemented the second solution.
 * Add a twlreg_attach_external_controller function to the TWL regulator driver to attach an external controller to a given regulator. This is the solution used at the moment: the OMAP voltage layer, during its initialization, instantiates one twlreg_ext_ctrl structure for each regulator (VDD1 and VDD2 for the moment) and then attaches this external controller to the regulator.

Once the external controller is attached to the regulator, the regulator driver call backs into the external controller hooks, as shown in the following diagram.



Preliminary version of July, 26th

 * http://free-electrons.com/~thomas/pub/omap-regulators/0001-omap-fix-OPP-change-code-after-conversion-from-vdd_i.patch
 * http://free-electrons.com/~thomas/pub/omap-regulators/0002-twl-regulator-extend-for-SMPS-regulators-and-externa.patch
 * http://free-electrons.com/~thomas/pub/omap-regulators/0003-omap3beagle-Instantiate-VDD1-and-VDD2-regulators.patch
 * http://free-electrons.com/~thomas/pub/omap-regulators/0004-omap-Use-the-regulator-API-in-the-OPP-change-code.patch
 * http://free-electrons.com/~thomas/pub/omap-regulators/0005-omap-attach-external-controller-to-VDD1-VDD2.patch

Status in September 2010
The proposed design and patches seem to have gotten a generally good feedback. However, as this patch set heavily depends on the DVFS infrastructure, its integration is blocked for the moment, while the DVFS work lands into one of Kevin's trees.