regulator: pm8921-regulator: Add regulator driver for PM8921

Create a regulator driver to control all regulators on the Qualcomm
PM8921 PMIC chip.  This chip contains many different types of
regulators with a wide range of abilities and voltage ranges.

Eight different regulator types are available on the PM8921.  These
are managed via 7 different type values in the driver:

LDO      - low drop out regulator (supports both NMOS and PMOS LDOs)
NLDO1200 - 1.2A NMOS LDO (different control structure than other LDOs)
SMPS     - switched-mode power supply
FTSMPS   - fast transient SMPS
VS       - voltage switch
VS300    - 300mA voltage switch (different control structure than
             other switches)
NCP      - negative charge pump

The driver interfaces with the PMIC using Qualcomm's SSBI bus.
Calls to this bus are abtracted through the pm8xxx_readb/writeb API.

Change-Id: I01fb755c6be8e3f32c86fef079b5740edfc39f14
Signed-off-by: David Collins <collinsd@codeaurora.org>
[sboyd: Take only pm8921-core bits]
This commit is contained in:
David Collins 2011-01-14 17:26:22 -08:00 committed by Stephen Boyd
parent 28d08f40ce
commit 9c38a8d17d
2 changed files with 37 additions and 0 deletions

View file

@ -30,6 +30,7 @@
struct pm8921 {
struct device *dev;
struct pm_irq_chip *irq_chip;
struct mfd_cell *mfd_regulators;
};
static int pm8921_readb(const struct device *dev, u16 addr, u8 *val)
@ -182,6 +183,8 @@ static int __devinit pm8921_add_subdevices(const struct pm8921_platform_data
{
int ret = 0, irq_base = 0;
struct pm_irq_chip *irq_chip;
static struct mfd_cell *mfd_regulators;
int i;
if (pdata->irq_pdata) {
pdata->irq_pdata->irq_cdata.nirqs = PM8921_NR_IRQS;
@ -258,6 +261,36 @@ static int __devinit pm8921_add_subdevices(const struct pm8921_platform_data
}
}
/* Add one device for each regulator used by the board. */
if (pdata->num_regulators > 0 && pdata->regulator_pdatas) {
mfd_regulators = kzalloc(sizeof(struct mfd_cell)
* (pdata->num_regulators), GFP_KERNEL);
if (!mfd_regulators) {
pr_err("Cannot allocate %d bytes for pm8921 regulator "
"mfd cells\n", sizeof(struct mfd_cell)
* (pdata->num_regulators));
ret = -ENOMEM;
goto bail;
}
for (i = 0; i < pdata->num_regulators; i++) {
mfd_regulators[i].name = PM8921_REGULATOR_DEV_NAME;
mfd_regulators[i].id = pdata->regulator_pdatas[i].id;
mfd_regulators[i].platform_data =
&(pdata->regulator_pdatas[i]);
mfd_regulators[i].pdata_size =
sizeof(struct pm8921_regulator_platform_data);
}
ret = mfd_add_devices(pmic->dev, 0, mfd_regulators,
pdata->num_regulators, NULL, irq_base);
if (ret) {
pr_err("Failed to add regulator subdevices ret=%d\n",
ret);
kfree(mfd_regulators);
goto bail;
}
pmic->mfd_regulators = mfd_regulators;
}
return 0;
bail:
if (pmic->irq_chip) {
@ -343,6 +376,7 @@ static int __devexit pm8921_remove(struct platform_device *pdev)
pmic->irq_chip = NULL;
}
platform_set_drvdata(pdev, NULL);
kfree(pmic->mfd_regulators);
kfree(pmic);
return 0;

View file

@ -24,6 +24,7 @@
#include <linux/mfd/pm8xxx/rtc.h>
#include <linux/input/pmic8xxx-pwrkey.h>
#include <linux/input/pmic8xxx-keypad.h>
#include <linux/regulator/pm8921-regulator.h>
#define PM8921_NR_IRQS 256
@ -59,6 +60,8 @@ struct pm8921_platform_data {
struct pm8xxx_rtc_platform_data *rtc_pdata;
struct pm8xxx_pwrkey_platform_data *pwrkey_pdata;
struct pm8xxx_keypad_platform_data *keypad_pdata;
struct pm8921_regulator_platform_data *regulator_pdatas;
int num_regulators;
};
#endif