Commit 9e63d230 authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branch 'regulator/topic/ab3100' into v3.9-rc8

parents 78da0218 018fd856
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -753,6 +753,7 @@ static struct mfd_cell ab3100_devs[] = {
	},
	{
		.name = "ab3100-regulators",
		.of_compatible = "stericsson,ab3100-regulators",
		.id = -1,
	},
	{
+186 −50
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
#include <linux/regulator/driver.h>
#include <linux/mfd/ab3100.h>
#include <linux/mfd/abx500.h>
#include <linux/of.h>
#include <linux/regulator/of_regulator.h>

/* LDO registers and some handy masking definitions for AB3100 */
#define AB3100_LDO_A		0x40
@@ -345,7 +347,11 @@ static int ab3100_get_voltage_regulator_external(struct regulator_dev *reg)
{
	struct ab3100_regulator *abreg = rdev_get_drvdata(reg);

	if (abreg->plfdata)
		return abreg->plfdata->external_voltage;
	else
		/* TODO: encode external voltage into device tree */
		return 0;
}

static struct regulator_ops regulator_ops_fixed = {
@@ -488,16 +494,174 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
	},
};

static int ab3100_regulator_register(struct platform_device *pdev,
				     struct ab3100_platform_data *plfdata,
				     struct regulator_init_data *init_data,
				     struct device_node *np,
				     int id)
{
	struct regulator_desc *desc;
	struct ab3100_regulator *reg;
	struct regulator_dev *rdev;
	struct regulator_config config = { };
	int err, i;

	for (i = 0; i < AB3100_NUM_REGULATORS; i++) {
		desc = &ab3100_regulator_desc[i];
		if (desc->id == id)
			break;
	}
	if (desc->id != id)
		return -ENODEV;

	/* Same index used for this array */
	reg = &ab3100_regulators[i];

	/*
 * NOTE: the following functions are regulators pluralis - it is the
 * binding to the AB3100 core driver and the parent platform device
 * for all the different regulators.
	 * Initialize per-regulator struct.
	 * Inherit platform data, this comes down from the
	 * i2c boarddata, from the machine. So if you want to
	 * see what it looks like for a certain machine, go
	 * into the machine I2C setup.
	 */
	reg->dev = &pdev->dev;
	if (plfdata) {
		reg->plfdata = plfdata;
		config.init_data = &plfdata->reg_constraints[i];
	} else if (np) {
		config.of_node = np;
		config.init_data = init_data;
	}
	config.dev = &pdev->dev;
	config.driver_data = reg;

	rdev = regulator_register(desc, &config);
	if (IS_ERR(rdev)) {
		err = PTR_ERR(rdev);
		dev_err(&pdev->dev,
			"%s: failed to register regulator %s err %d\n",
			__func__, desc->name,
			err);
		return err;
	}

	/* Then set a pointer back to the registered regulator */
	reg->rdev = rdev;
	return 0;
}

static struct of_regulator_match ab3100_regulator_matches[] = {
	{ .name = "ab3100_ldo_a", .driver_data = (void *) AB3100_LDO_A, },
	{ .name = "ab3100_ldo_c", .driver_data = (void *) AB3100_LDO_C, },
	{ .name = "ab3100_ldo_d", .driver_data = (void *) AB3100_LDO_D, },
	{ .name = "ab3100_ldo_e", .driver_data = (void *) AB3100_LDO_E, },
	{ .name = "ab3100_ldo_f", .driver_data = (void *) AB3100_LDO_F },
	{ .name = "ab3100_ldo_g", .driver_data = (void *) AB3100_LDO_G },
	{ .name = "ab3100_ldo_h", .driver_data = (void *) AB3100_LDO_H },
	{ .name = "ab3100_ldo_k", .driver_data = (void *) AB3100_LDO_K },
	{ .name = "ab3100_ext", .driver_data = (void *) AB3100_LDO_EXT },
	{ .name = "ab3100_buck", .driver_data = (void *) AB3100_BUCK },
};

/*
 * Initial settings of ab3100 registers.
 * Common for below LDO regulator settings are that
 * bit 7-5 controls voltage. Bit 4 turns regulator ON(1) or OFF(0).
 * Bit 3-2 controls sleep enable and bit 1-0 controls sleep mode.
 */
/* LDO_A 0x16: 2.75V, ON, SLEEP_A, SLEEP OFF GND */
#define LDO_A_SETTING		0x16
/* LDO_C 0x10: 2.65V, ON, SLEEP_A or B, SLEEP full power */
#define LDO_C_SETTING		0x10
/* LDO_D 0x10: 2.65V, ON, sleep mode not used */
#define LDO_D_SETTING		0x10
/* LDO_E 0x10: 1.8V, ON, SLEEP_A or B, SLEEP full power */
#define LDO_E_SETTING		0x10
/* LDO_E SLEEP 0x00: 1.8V, not used, SLEEP_A or B, not used */
#define LDO_E_SLEEP_SETTING	0x00
/* LDO_F 0xD0: 2.5V, ON, SLEEP_A or B, SLEEP full power */
#define LDO_F_SETTING		0xD0
/* LDO_G 0x00: 2.85V, OFF, SLEEP_A or B, SLEEP full power */
#define LDO_G_SETTING		0x00
/* LDO_H 0x18: 2.75V, ON, SLEEP_B, SLEEP full power */
#define LDO_H_SETTING		0x18
/* LDO_K 0x00: 2.75V, OFF, SLEEP_A or B, SLEEP full power */
#define LDO_K_SETTING		0x00
/* LDO_EXT 0x00: Voltage not set, OFF, not used, not used */
#define LDO_EXT_SETTING		0x00
/* BUCK 0x7D: 1.2V, ON, SLEEP_A and B, SLEEP low power */
#define BUCK_SETTING	0x7D
/* BUCK SLEEP 0xAC: 1.05V, Not used, SLEEP_A and B, Not used */
#define BUCK_SLEEP_SETTING	0xAC

static const u8 ab3100_reg_initvals[] = {
	LDO_A_SETTING,
	LDO_C_SETTING,
	LDO_E_SETTING,
	LDO_E_SLEEP_SETTING,
	LDO_F_SETTING,
	LDO_G_SETTING,
	LDO_H_SETTING,
	LDO_K_SETTING,
	LDO_EXT_SETTING,
	BUCK_SETTING,
	BUCK_SLEEP_SETTING,
	LDO_D_SETTING,
};

static int ab3100_regulators_remove(struct platform_device *pdev)
{
	int i;

	for (i = 0; i < AB3100_NUM_REGULATORS; i++) {
		struct ab3100_regulator *reg = &ab3100_regulators[i];

		regulator_unregister(reg->rdev);
		reg->rdev = NULL;
	}
	return 0;
}

static int
ab3100_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
{
	int err, i;

	/*
	 * Set up the regulator registers, as was previously done with
	 * platform data.
	 */
	/* Set up regulators */
	for (i = 0; i < ARRAY_SIZE(ab3100_reg_init_order); i++) {
		err = abx500_set_register_interruptible(&pdev->dev, 0,
					ab3100_reg_init_order[i],
					ab3100_reg_initvals[i]);
		if (err) {
			dev_err(&pdev->dev, "regulator initialization failed with error %d\n",
				err);
			return err;
		}
	}

	for (i = 0; i < ARRAY_SIZE(ab3100_regulator_matches); i++) {
		err = ab3100_regulator_register(
			pdev, NULL, ab3100_regulator_matches[i].init_data,
			ab3100_regulator_matches[i].of_node,
			(int) ab3100_regulator_matches[i].driver_data);
		if (err) {
			ab3100_regulators_remove(pdev);
			return err;
		}
	}

	return 0;
}


static int ab3100_regulators_probe(struct platform_device *pdev)
{
	struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
	struct regulator_config config = { };
	struct device_node *np = pdev->dev.of_node;
	int err = 0;
	u8 data;
	int i;
@@ -516,6 +680,18 @@ static int ab3100_regulators_probe(struct platform_device *pdev)
		dev_notice(&pdev->dev,
			   "chip is in inactive mode (Cold start)\n");

	if (np) {
		err = of_regulator_match(&pdev->dev, np,
					 ab3100_regulator_matches,
					 ARRAY_SIZE(ab3100_regulator_matches));
		if (err < 0) {
			dev_err(&pdev->dev,
				"Error parsing regulator init data: %d\n", err);
			return err;
		}
		return ab3100_regulator_of_probe(pdev, np);
	}

	/* Set up regulators */
	for (i = 0; i < ARRAY_SIZE(ab3100_reg_init_order); i++) {
		err = abx500_set_register_interruptible(&pdev->dev, 0,
@@ -530,56 +706,16 @@ static int ab3100_regulators_probe(struct platform_device *pdev)

	/* Register the regulators */
	for (i = 0; i < AB3100_NUM_REGULATORS; i++) {
		struct ab3100_regulator *reg = &ab3100_regulators[i];
		struct regulator_dev *rdev;

		/*
		 * Initialize per-regulator struct.
		 * Inherit platform data, this comes down from the
		 * i2c boarddata, from the machine. So if you want to
		 * see what it looks like for a certain machine, go
		 * into the machine I2C setup.
		 */
		reg->dev = &pdev->dev;
		reg->plfdata = plfdata;

		config.dev = &pdev->dev;
		config.driver_data = reg;
		config.init_data = &plfdata->reg_constraints[i];
		struct regulator_desc *desc = &ab3100_regulator_desc[i];

		/*
		 * Register the regulator, pass around
		 * the ab3100_regulator struct
		 */
		rdev = regulator_register(&ab3100_regulator_desc[i], &config);
		if (IS_ERR(rdev)) {
			err = PTR_ERR(rdev);
			dev_err(&pdev->dev,
				"%s: failed to register regulator %s err %d\n",
				__func__, ab3100_regulator_desc[i].name,
				err);
			/* remove the already registered regulators */
			while (--i >= 0)
				regulator_unregister(ab3100_regulators[i].rdev);
		err = ab3100_regulator_register(pdev, plfdata, NULL, NULL,
						desc->id);
		if (err) {
			ab3100_regulators_remove(pdev);
			return err;
		}

		/* Then set a pointer back to the registered regulator */
		reg->rdev = rdev;
	}

	return 0;
	}

static int ab3100_regulators_remove(struct platform_device *pdev)
{
	int i;

	for (i = 0; i < AB3100_NUM_REGULATORS; i++) {
		struct ab3100_regulator *reg = &ab3100_regulators[i];

		regulator_unregister(reg->rdev);
	}
	return 0;
}