Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 18bcd0c8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6:
  regulator: Add MODULE_DEVICE_TABLE to max8997 and max8998
  regulator: fix tps6524x section mismatch
  regulator: Remove more wm831x-specific IRQ operations
  regulator: add ab8500 enable and raise time delays
  regulator: provide consumer interface for fall/rise time
  regulator: add set_voltage_time_sel infrastructure
  regulator: initialization for ab8500 regulators
  regulator: add support for USB voltage regulator
  regulator: switch the ab3100 to use enable_time()
  Regulator: add suspend-finish API for regulator core.
  regulator: fix typo in Kconfig
  regulator: Convert WM831x regulators to genirq
  regulator: If we fail when setting up a supply say which supply
parents 7b724a22 a51b907b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@
#include <linux/regulator/machine.h>
#include <linux/regulator/ab8500.h>

extern struct ab8500_regulator_reg_init
ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS];
extern struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS];

#endif
+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <linux/amba/serial.h>
#include <linux/spi/spi.h>
#include <linux/mfd/ab8500.h>
#include <linux/regulator/ab8500.h>
#include <linux/mfd/tc3589x.h>
#include <linux/leds-lp5521.h>
#include <linux/input.h>
+1 −1
Original line number Diff line number Diff line
@@ -126,7 +126,7 @@ config REGULATOR_MAX8998
	  and S5PC1XX chips to control VCC_CORE and VCC_USIM voltages.

config REGULATOR_TWL4030
	bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC"
	bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 PMIC"
	depends on TWL4030_CORE
	help
	  This driver supports the voltage regulators provided by
+28 −23
Original line number Diff line number Diff line
@@ -206,29 +206,6 @@ static int ab3100_enable_regulator(struct regulator_dev *reg)
		return err;
	}

	/* Per-regulator power on delay from spec */
	switch (abreg->regreg) {
	case AB3100_LDO_A: /* Fallthrough */
	case AB3100_LDO_C: /* Fallthrough */
	case AB3100_LDO_D: /* Fallthrough */
	case AB3100_LDO_E: /* Fallthrough */
	case AB3100_LDO_H: /* Fallthrough */
	case AB3100_LDO_K:
		udelay(200);
		break;
	case AB3100_LDO_F:
		udelay(600);
		break;
	case AB3100_LDO_G:
		udelay(400);
		break;
	case AB3100_BUCK:
		mdelay(1);
		break;
	default:
		break;
	}

	return 0;
}

@@ -450,11 +427,37 @@ static int ab3100_get_voltage_regulator_external(struct regulator_dev *reg)
	return abreg->plfdata->external_voltage;
}

static int ab3100_enable_time_regulator(struct regulator_dev *reg)
{
	struct ab3100_regulator *abreg = reg->reg_data;

	/* Per-regulator power on delay from spec */
	switch (abreg->regreg) {
	case AB3100_LDO_A: /* Fallthrough */
	case AB3100_LDO_C: /* Fallthrough */
	case AB3100_LDO_D: /* Fallthrough */
	case AB3100_LDO_E: /* Fallthrough */
	case AB3100_LDO_H: /* Fallthrough */
	case AB3100_LDO_K:
		return 200;
	case AB3100_LDO_F:
		return 600;
	case AB3100_LDO_G:
		return 400;
	case AB3100_BUCK:
		return 1000;
	default:
		break;
	}
	return 0;
}

static struct regulator_ops regulator_ops_fixed = {
	.enable      = ab3100_enable_regulator,
	.disable     = ab3100_disable_regulator,
	.is_enabled  = ab3100_is_enabled_regulator,
	.get_voltage = ab3100_get_voltage_regulator,
	.enable_time = ab3100_enable_time_regulator,
};

static struct regulator_ops regulator_ops_variable = {
@@ -464,6 +467,7 @@ static struct regulator_ops regulator_ops_variable = {
	.get_voltage = ab3100_get_voltage_regulator,
	.set_voltage = ab3100_set_voltage_regulator,
	.list_voltage = ab3100_list_voltage_regulator,
	.enable_time = ab3100_enable_time_regulator,
};

static struct regulator_ops regulator_ops_variable_sleepable = {
@@ -474,6 +478,7 @@ static struct regulator_ops regulator_ops_variable_sleepable = {
	.set_voltage = ab3100_set_voltage_regulator,
	.set_suspend_voltage = ab3100_set_suspend_voltage_regulator,
	.list_voltage = ab3100_list_voltage_regulator,
	.enable_time = ab3100_enable_time_regulator,
};

/*
+268 −2
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@
 * AB8500 peripheral regulators
 *
 * AB8500 supports the following regulators:
 *   VAUX1/2/3, VINTCORE, VTVOUT, VAUDIO, VAMIC1/2, VDMIC, VANA
 *   VAUX1/2/3, VINTCORE, VTVOUT, VUSB, VAUDIO, VAMIC1/2, VDMIC, VANA
 */
#include <linux/init.h>
#include <linux/kernel.h>
@@ -38,6 +38,7 @@
 * @voltage_mask: mask to control regulator voltage
 * @voltages: supported voltage table
 * @voltages_len: number of supported voltages for the regulator
 * @delay: startup/set voltage delay in us
 */
struct ab8500_regulator_info {
	struct device		*dev;
@@ -55,6 +56,7 @@ struct ab8500_regulator_info {
	u8 voltage_mask;
	int const *voltages;
	int voltages_len;
	unsigned int delay;
};

/* voltage tables for the vauxn/vintcore supplies */
@@ -290,6 +292,29 @@ static int ab8500_regulator_set_voltage(struct regulator_dev *rdev,
	return ret;
}

static int ab8500_regulator_enable_time(struct regulator_dev *rdev)
{
	struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);

	return info->delay;
}

static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
					     unsigned int old_sel,
					     unsigned int new_sel)
{
	struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
	int ret;

	/* If the regulator isn't on, it won't take time here */
	ret = ab8500_regulator_is_enabled(rdev);
	if (ret < 0)
		return ret;
	if (!ret)
		return 0;
	return info->delay;
}

static struct regulator_ops ab8500_regulator_ops = {
	.enable		= ab8500_regulator_enable,
	.disable	= ab8500_regulator_disable,
@@ -297,6 +322,8 @@ static struct regulator_ops ab8500_regulator_ops = {
	.get_voltage	= ab8500_regulator_get_voltage,
	.set_voltage	= ab8500_regulator_set_voltage,
	.list_voltage	= ab8500_list_voltage,
	.enable_time	= ab8500_regulator_enable_time,
	.set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel,
};

static int ab8500_fixed_get_voltage(struct regulator_dev *rdev)
@@ -317,6 +344,8 @@ static struct regulator_ops ab8500_regulator_fixed_ops = {
	.is_enabled	= ab8500_regulator_is_enabled,
	.get_voltage	= ab8500_fixed_get_voltage,
	.list_voltage	= ab8500_list_voltage,
	.enable_time	= ab8500_regulator_enable_time,
	.set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel,
};

static struct ab8500_regulator_info
@@ -426,12 +455,28 @@ static struct ab8500_regulator_info
			.owner		= THIS_MODULE,
			.n_voltages	= 1,
		},
		.delay			= 10000,
		.fixed_uV		= 2000000,
		.update_bank		= 0x03,
		.update_reg		= 0x80,
		.update_mask		= 0x82,
		.update_val_enable	= 0x02,
	},
	[AB8500_LDO_USB] = {
		.desc = {
			.name           = "LDO-USB",
			.ops            = &ab8500_regulator_fixed_ops,
			.type           = REGULATOR_VOLTAGE,
			.id             = AB8500_LDO_USB,
			.owner          = THIS_MODULE,
			.n_voltages     = 1,
		},
		.fixed_uV               = 3300000,
		.update_bank            = 0x03,
		.update_reg             = 0x82,
		.update_mask            = 0x03,
		.update_val_enable      = 0x01,
	},
	[AB8500_LDO_AUDIO] = {
		.desc = {
			.name		= "LDO-AUDIO",
@@ -511,6 +556,186 @@ static struct ab8500_regulator_info

};

struct ab8500_reg_init {
	u8 bank;
	u8 addr;
	u8 mask;
};

#define REG_INIT(_id, _bank, _addr, _mask)	\
	[_id] = {				\
		.bank = _bank,			\
		.addr = _addr,			\
		.mask = _mask,			\
	}

static struct ab8500_reg_init ab8500_reg_init[] = {
	/*
	 * 0x30, VanaRequestCtrl
	 * 0x0C, VpllRequestCtrl
	 * 0xc0, VextSupply1RequestCtrl
	 */
	REG_INIT(AB8500_REGUREQUESTCTRL2,	0x03, 0x04, 0xfc),
	/*
	 * 0x03, VextSupply2RequestCtrl
	 * 0x0c, VextSupply3RequestCtrl
	 * 0x30, Vaux1RequestCtrl
	 * 0xc0, Vaux2RequestCtrl
	 */
	REG_INIT(AB8500_REGUREQUESTCTRL3,	0x03, 0x05, 0xff),
	/*
	 * 0x03, Vaux3RequestCtrl
	 * 0x04, SwHPReq
	 */
	REG_INIT(AB8500_REGUREQUESTCTRL4,	0x03, 0x06, 0x07),
	/*
	 * 0x08, VanaSysClkReq1HPValid
	 * 0x20, Vaux1SysClkReq1HPValid
	 * 0x40, Vaux2SysClkReq1HPValid
	 * 0x80, Vaux3SysClkReq1HPValid
	 */
	REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID1,	0x03, 0x07, 0xe8),
	/*
	 * 0x10, VextSupply1SysClkReq1HPValid
	 * 0x20, VextSupply2SysClkReq1HPValid
	 * 0x40, VextSupply3SysClkReq1HPValid
	 */
	REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID2,	0x03, 0x08, 0x70),
	/*
	 * 0x08, VanaHwHPReq1Valid
	 * 0x20, Vaux1HwHPReq1Valid
	 * 0x40, Vaux2HwHPReq1Valid
	 * 0x80, Vaux3HwHPReq1Valid
	 */
	REG_INIT(AB8500_REGUHWHPREQ1VALID1,	0x03, 0x09, 0xe8),
	/*
	 * 0x01, VextSupply1HwHPReq1Valid
	 * 0x02, VextSupply2HwHPReq1Valid
	 * 0x04, VextSupply3HwHPReq1Valid
	 */
	REG_INIT(AB8500_REGUHWHPREQ1VALID2,	0x03, 0x0a, 0x07),
	/*
	 * 0x08, VanaHwHPReq2Valid
	 * 0x20, Vaux1HwHPReq2Valid
	 * 0x40, Vaux2HwHPReq2Valid
	 * 0x80, Vaux3HwHPReq2Valid
	 */
	REG_INIT(AB8500_REGUHWHPREQ2VALID1,	0x03, 0x0b, 0xe8),
	/*
	 * 0x01, VextSupply1HwHPReq2Valid
	 * 0x02, VextSupply2HwHPReq2Valid
	 * 0x04, VextSupply3HwHPReq2Valid
	 */
	REG_INIT(AB8500_REGUHWHPREQ2VALID2,	0x03, 0x0c, 0x07),
	/*
	 * 0x20, VanaSwHPReqValid
	 * 0x80, Vaux1SwHPReqValid
	 */
	REG_INIT(AB8500_REGUSWHPREQVALID1,	0x03, 0x0d, 0xa0),
	/*
	 * 0x01, Vaux2SwHPReqValid
	 * 0x02, Vaux3SwHPReqValid
	 * 0x04, VextSupply1SwHPReqValid
	 * 0x08, VextSupply2SwHPReqValid
	 * 0x10, VextSupply3SwHPReqValid
	 */
	REG_INIT(AB8500_REGUSWHPREQVALID2,	0x03, 0x0e, 0x1f),
	/*
	 * 0x02, SysClkReq2Valid1
	 * ...
	 * 0x80, SysClkReq8Valid1
	 */
	REG_INIT(AB8500_REGUSYSCLKREQVALID1,	0x03, 0x0f, 0xfe),
	/*
	 * 0x02, SysClkReq2Valid2
	 * ...
	 * 0x80, SysClkReq8Valid2
	 */
	REG_INIT(AB8500_REGUSYSCLKREQVALID2,	0x03, 0x10, 0xfe),
	/*
	 * 0x02, VTVoutEna
	 * 0x04, Vintcore12Ena
	 * 0x38, Vintcore12Sel
	 * 0x40, Vintcore12LP
	 * 0x80, VTVoutLP
	 */
	REG_INIT(AB8500_REGUMISC1,		0x03, 0x80, 0xfe),
	/*
	 * 0x02, VaudioEna
	 * 0x04, VdmicEna
	 * 0x08, Vamic1Ena
	 * 0x10, Vamic2Ena
	 */
	REG_INIT(AB8500_VAUDIOSUPPLY,		0x03, 0x83, 0x1e),
	/*
	 * 0x01, Vamic1_dzout
	 * 0x02, Vamic2_dzout
	 */
	REG_INIT(AB8500_REGUCTRL1VAMIC,		0x03, 0x84, 0x03),
	/*
	 * 0x0c, VanaRegu
	 * 0x03, VpllRegu
	 */
	REG_INIT(AB8500_VPLLVANAREGU,		0x04, 0x06, 0x0f),
	/*
	 * 0x01, VrefDDREna
	 * 0x02, VrefDDRSleepMode
	 */
	REG_INIT(AB8500_VREFDDR,		0x04, 0x07, 0x03),
	/*
	 * 0x03, VextSupply1Regu
	 * 0x0c, VextSupply2Regu
	 * 0x30, VextSupply3Regu
	 * 0x40, ExtSupply2Bypass
	 * 0x80, ExtSupply3Bypass
	 */
	REG_INIT(AB8500_EXTSUPPLYREGU,		0x04, 0x08, 0xff),
	/*
	 * 0x03, Vaux1Regu
	 * 0x0c, Vaux2Regu
	 */
	REG_INIT(AB8500_VAUX12REGU,		0x04, 0x09, 0x0f),
	/*
	 * 0x03, Vaux3Regu
	 */
	REG_INIT(AB8500_VRF1VAUX3REGU,		0x04, 0x0a, 0x03),
	/*
	 * 0x3f, Vsmps1Sel1
	 */
	REG_INIT(AB8500_VSMPS1SEL1,		0x04, 0x13, 0x3f),
	/*
	 * 0x0f, Vaux1Sel
	 */
	REG_INIT(AB8500_VAUX1SEL,		0x04, 0x1f, 0x0f),
	/*
	 * 0x0f, Vaux2Sel
	 */
	REG_INIT(AB8500_VAUX2SEL,		0x04, 0x20, 0x0f),
	/*
	 * 0x07, Vaux3Sel
	 */
	REG_INIT(AB8500_VRF1VAUX3SEL,		0x04, 0x21, 0x07),
	/*
	 * 0x01, VextSupply12LP
	 */
	REG_INIT(AB8500_REGUCTRL2SPARE,		0x04, 0x22, 0x01),
	/*
	 * 0x04, Vaux1Disch
	 * 0x08, Vaux2Disch
	 * 0x10, Vaux3Disch
	 * 0x20, Vintcore12Disch
	 * 0x40, VTVoutDisch
	 * 0x80, VaudioDisch
	 */
	REG_INIT(AB8500_REGUCTRLDISCH,		0x04, 0x43, 0xfc),
	/*
	 * 0x02, VanaDisch
	 * 0x04, VdmicPullDownEna
	 * 0x10, VdmicDisch
	 */
	REG_INIT(AB8500_REGUCTRLDISCH2,		0x04, 0x44, 0x16),
};

static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
{
	struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
@@ -529,9 +754,50 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)

	/* make sure the platform data has the correct size */
	if (pdata->num_regulator != ARRAY_SIZE(ab8500_regulator_info)) {
		dev_err(&pdev->dev, "platform configuration error\n");
		dev_err(&pdev->dev, "Configuration error: size mismatch.\n");
		return -EINVAL;
	}

	/* initialize registers */
	for (i = 0; i < pdata->num_regulator_reg_init; i++) {
		int id;
		u8 value;

		id = pdata->regulator_reg_init[i].id;
		value = pdata->regulator_reg_init[i].value;

		/* check for configuration errors */
		if (id >= AB8500_NUM_REGULATOR_REGISTERS) {
			dev_err(&pdev->dev,
				"Configuration error: id outside range.\n");
			return -EINVAL;
		}
		if (value & ~ab8500_reg_init[id].mask) {
			dev_err(&pdev->dev,
				"Configuration error: value outside mask.\n");
			return -EINVAL;
		}

		/* initialize register */
		err = abx500_mask_and_set_register_interruptible(&pdev->dev,
			ab8500_reg_init[id].bank,
			ab8500_reg_init[id].addr,
			ab8500_reg_init[id].mask,
			value);
		if (err < 0) {
			dev_err(&pdev->dev,
				"Failed to initialize 0x%02x, 0x%02x.\n",
				ab8500_reg_init[id].bank,
				ab8500_reg_init[id].addr);
			return err;
		}
		dev_vdbg(&pdev->dev,
			"  init: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
			ab8500_reg_init[id].bank,
			ab8500_reg_init[id].addr,
			ab8500_reg_init[id].mask,
			value);
	}

	/* register all regulators */
	for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
Loading