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

Commit 24ee65e4 authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branches 'regulator/topic/s5m8767',...

Merge remote-tracking branches 'regulator/topic/s5m8767', 'regulator/topic/st-pwm', 'regulator/topic/ti-abb', 'regulator/topic/tps51632', 'regulator/topic/tps62360', 'regulator/topic/tps6507x', 'regulator/topic/tps65090' and 'regulator/topic/tps65217' into regulator-next
Loading
+12 −1
Original line number Original line Diff line number Diff line
@@ -69,13 +69,16 @@ sub-node should be of the format as listed below.
		};
		};
	};
	};
The above regulator entries are defined in regulator bindings documentation
The above regulator entries are defined in regulator bindings documentation
except op_mode description.
except these properties:
	- op_mode: describes the different operating modes of the LDO's with
	- op_mode: describes the different operating modes of the LDO's with
		power mode change in SOC. The different possible values are,
		power mode change in SOC. The different possible values are,
		0 - always off mode
		0 - always off mode
		1 - on in normal mode
		1 - on in normal mode
		2 - low power mode
		2 - low power mode
		3 - suspend mode
		3 - suspend mode
	- s5m8767,pmic-ext-control-gpios: (optional) GPIO specifier for one
		GPIO controlling this regulator (enable/disable); This is
		valid only for buck9.


The following are the names of the regulators that the s5m8767 pmic block
The following are the names of the regulators that the s5m8767 pmic block
supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number
supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number
@@ -148,5 +151,13 @@ Example:
				regulator-always-on;
				regulator-always-on;
				regulator-boot-on;
				regulator-boot-on;
			};
			};

			vemmc_reg: BUCK9 {
				regulator-name = "VMEM_VDD_2.8V";
				regulator-min-microvolt = <2800000>;
				regulator-max-microvolt = <2800000>;
				op_mode = <3>; /* Standby Mode */
				s5m8767,pmic-ext-control-gpios = <&gpk0 2 0>;
			};
		};
		};
	};
	};
+5 −1
Original line number Original line Diff line number Diff line
@@ -4,10 +4,14 @@ Required Properties:
- compatible: Should be one of:
- compatible: Should be one of:
  - "ti,abb-v1" for older SoCs like OMAP3
  - "ti,abb-v1" for older SoCs like OMAP3
  - "ti,abb-v2" for newer SoCs like OMAP4, OMAP5
  - "ti,abb-v2" for newer SoCs like OMAP4, OMAP5
  - "ti,abb-v3" for a generic definition where setup and control registers are
     provided (example: DRA7)
- reg: Address and length of the register set for the device. It contains
- reg: Address and length of the register set for the device. It contains
  the information of registers in the same order as described by reg-names
  the information of registers in the same order as described by reg-names
- reg-names: Should contain the reg names
- reg-names: Should contain the reg names
  - "base-address"	- contains base address of ABB module
  - "base-address"	- contains base address of ABB module (ti,abb-v1,ti,abb-v2)
  - "control-address"	- contains control register address of ABB module (ti,abb-v3)
  - "setup-address"	- contains setup register address of ABB module (ti,abb-v3)
  - "int-address"	- contains address of interrupt register for ABB module
  - "int-address"	- contains address of interrupt register for ABB module
  (also see Optional properties)
  (also see Optional properties)
- #address-cell: should be 0
- #address-cell: should be 0
+6 −0
Original line number Original line Diff line number Diff line
@@ -448,6 +448,12 @@ config REGULATOR_S5M8767
	 via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and
	 via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and
	 supports DVS mode with 8bits of output voltage control.
	 supports DVS mode with 8bits of output voltage control.


config REGULATOR_ST_PWM
	tristate "STMicroelectronics PWM voltage regulator"
	depends on ARCH_STI
	help
	 This driver supports ST's PWM controlled voltage regulators.

config REGULATOR_TI_ABB
config REGULATOR_TI_ABB
	tristate "TI Adaptive Body Bias on-chip LDO"
	tristate "TI Adaptive Body Bias on-chip LDO"
	depends on ARCH_OMAP
	depends on ARCH_OMAP
+1 −0
Original line number Original line Diff line number Diff line
@@ -61,6 +61,7 @@ obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
obj-$(CONFIG_REGULATOR_ST_PWM) += st-pwm.o
obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
+103 −68
Original line number Original line Diff line number Diff line
@@ -11,11 +11,8 @@
 *
 *
 */
 */


#include <linux/bug.h>
#include <linux/err.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/of_gpio.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/driver.h>
@@ -170,12 +167,11 @@ static unsigned int s5m8767_opmode_reg[][4] = {
	{0x0, 0x3, 0x1, 0x1}, /* BUCK9 */
	{0x0, 0x3, 0x1, 0x1}, /* BUCK9 */
};
};


static int s5m8767_get_register(struct regulator_dev *rdev, int *reg,
static int s5m8767_get_register(struct s5m8767_info *s5m8767, int reg_id,
				int *enable_ctrl)
				int *reg, int *enable_ctrl)
{
{
	int i, reg_id = rdev_get_id(rdev);
	int i;
	unsigned int mode;
	unsigned int mode;
	struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);


	switch (reg_id) {
	switch (reg_id) {
	case S5M8767_LDO1 ... S5M8767_LDO2:
	case S5M8767_LDO1 ... S5M8767_LDO2:
@@ -214,53 +210,6 @@ static int s5m8767_get_register(struct regulator_dev *rdev, int *reg,
	return 0;
	return 0;
}
}


static int s5m8767_reg_is_enabled(struct regulator_dev *rdev)
{
	struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
	int ret, reg;
	int enable_ctrl;
	unsigned int val;

	ret = s5m8767_get_register(rdev, &reg, &enable_ctrl);
	if (ret == -EINVAL)
		return 1;
	else if (ret)
		return ret;

	ret = regmap_read(s5m8767->iodev->regmap_pmic, reg, &val);
	if (ret)
		return ret;

	return (val & S5M8767_ENCTRL_MASK) == enable_ctrl;
}

static int s5m8767_reg_enable(struct regulator_dev *rdev)
{
	struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
	int ret, reg;
	int enable_ctrl;

	ret = s5m8767_get_register(rdev, &reg, &enable_ctrl);
	if (ret)
		return ret;

	return regmap_update_bits(s5m8767->iodev->regmap_pmic, reg,
			S5M8767_ENCTRL_MASK, enable_ctrl);
}

static int s5m8767_reg_disable(struct regulator_dev *rdev)
{
	struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
	int ret, reg, enable_ctrl;

	ret = s5m8767_get_register(rdev, &reg, &enable_ctrl);
	if (ret)
		return ret;

	return regmap_update_bits(s5m8767->iodev->regmap_pmic, reg,
			S5M8767_ENCTRL_MASK, ~S5M8767_ENCTRL_MASK);
}

static int s5m8767_get_vsel_reg(int reg_id, struct s5m8767_info *s5m8767)
static int s5m8767_get_vsel_reg(int reg_id, struct s5m8767_info *s5m8767)
{
{
	int reg;
	int reg;
@@ -410,9 +359,9 @@ static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev,


static struct regulator_ops s5m8767_ops = {
static struct regulator_ops s5m8767_ops = {
	.list_voltage		= regulator_list_voltage_linear,
	.list_voltage		= regulator_list_voltage_linear,
	.is_enabled		= s5m8767_reg_is_enabled,
	.is_enabled		= regulator_is_enabled_regmap,
	.enable			= s5m8767_reg_enable,
	.enable			= regulator_enable_regmap,
	.disable		= s5m8767_reg_disable,
	.disable		= regulator_disable_regmap,
	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
	.set_voltage_sel	= s5m8767_set_voltage_sel,
	.set_voltage_sel	= s5m8767_set_voltage_sel,
	.set_voltage_time_sel	= s5m8767_set_voltage_time_sel,
	.set_voltage_time_sel	= s5m8767_set_voltage_time_sel,
@@ -420,9 +369,9 @@ static struct regulator_ops s5m8767_ops = {


static struct regulator_ops s5m8767_buck78_ops = {
static struct regulator_ops s5m8767_buck78_ops = {
	.list_voltage		= regulator_list_voltage_linear,
	.list_voltage		= regulator_list_voltage_linear,
	.is_enabled		= s5m8767_reg_is_enabled,
	.is_enabled		= regulator_is_enabled_regmap,
	.enable			= s5m8767_reg_enable,
	.enable			= regulator_enable_regmap,
	.disable		= s5m8767_reg_disable,
	.disable		= regulator_disable_regmap,
	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
};
};
@@ -483,6 +432,66 @@ static struct regulator_desc regulators[] = {
	s5m8767_regulator_desc(BUCK9),
	s5m8767_regulator_desc(BUCK9),
};
};


/*
 * Enable GPIO control over BUCK9 in regulator_config for that regulator.
 */
static void s5m8767_regulator_config_ext_control(struct s5m8767_info *s5m8767,
		struct sec_regulator_data *rdata,
		struct regulator_config *config)
{
	int i, mode = 0;

	if (rdata->id != S5M8767_BUCK9)
		return;

	/* Check if opmode for regulator matches S5M8767_ENCTRL_USE_GPIO */
	for (i = 0; i < s5m8767->num_regulators; i++) {
		const struct sec_opmode_data *opmode = &s5m8767->opmode[i];
		if (opmode->id == rdata->id) {
			mode = s5m8767_opmode_reg[rdata->id][opmode->mode];
			break;
		}
	}
	if (mode != S5M8767_ENCTRL_USE_GPIO) {
		dev_warn(s5m8767->dev,
				"ext-control for %s: mismatched op_mode (%x), ignoring\n",
				rdata->reg_node->name, mode);
		return;
	}

	if (!gpio_is_valid(rdata->ext_control_gpio)) {
		dev_warn(s5m8767->dev,
				"ext-control for %s: GPIO not valid, ignoring\n",
				rdata->reg_node->name);
		return;
	}

	config->ena_gpio = rdata->ext_control_gpio;
	config->ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
}

/*
 * Turn on GPIO control over BUCK9.
 */
static int s5m8767_enable_ext_control(struct s5m8767_info *s5m8767,
		struct regulator_dev *rdev)
{
	int id = rdev_get_id(rdev);
	int ret, reg, enable_ctrl;

	if (id != S5M8767_BUCK9)
		return -EINVAL;

	ret = s5m8767_get_register(s5m8767, id, &reg, &enable_ctrl);
	if (ret)
		return ret;

	return regmap_update_bits(s5m8767->iodev->regmap_pmic,
			reg, S5M8767_ENCTRL_MASK,
			S5M8767_ENCTRL_USE_GPIO << S5M8767_ENCTRL_SHIFT);
}


#ifdef CONFIG_OF
#ifdef CONFIG_OF
static int s5m8767_pmic_dt_parse_dvs_gpio(struct sec_pmic_dev *iodev,
static int s5m8767_pmic_dt_parse_dvs_gpio(struct sec_pmic_dev *iodev,
			struct sec_platform_data *pdata,
			struct sec_platform_data *pdata,
@@ -520,6 +529,16 @@ static int s5m8767_pmic_dt_parse_ds_gpio(struct sec_pmic_dev *iodev,
	return 0;
	return 0;
}
}


static void s5m8767_pmic_dt_parse_ext_control_gpio(struct sec_pmic_dev *iodev,
		struct sec_regulator_data *rdata,
		struct device_node *reg_np)
{
	rdata->ext_control_gpio = of_get_named_gpio(reg_np,
			"s5m8767,pmic-ext-control-gpios", 0);
	if (!gpio_is_valid(rdata->ext_control_gpio))
		rdata->ext_control_gpio = 0;
}

static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
					struct sec_platform_data *pdata)
					struct sec_platform_data *pdata)
{
{
@@ -546,19 +565,13 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,


	rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
	rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
				pdata->num_regulators, GFP_KERNEL);
				pdata->num_regulators, GFP_KERNEL);
	if (!rdata) {
	if (!rdata)
		dev_err(iodev->dev,
			"could not allocate memory for regulator data\n");
		return -ENOMEM;
		return -ENOMEM;
	}


	rmode = devm_kzalloc(&pdev->dev, sizeof(*rmode) *
	rmode = devm_kzalloc(&pdev->dev, sizeof(*rmode) *
				pdata->num_regulators, GFP_KERNEL);
				pdata->num_regulators, GFP_KERNEL);
	if (!rmode) {
	if (!rmode)
		dev_err(iodev->dev,
			"could not allocate memory for regulator mode\n");
		return -ENOMEM;
		return -ENOMEM;
	}


	pdata->regulators = rdata;
	pdata->regulators = rdata;
	pdata->opmode = rmode;
	pdata->opmode = rmode;
@@ -574,6 +587,8 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
			continue;
			continue;
		}
		}


		s5m8767_pmic_dt_parse_ext_control_gpio(iodev, rdata, reg_np);

		rdata->id = i;
		rdata->id = i;
		rdata->initdata = of_get_regulator_init_data(
		rdata->initdata = of_get_regulator_init_data(
						&pdev->dev, reg_np);
						&pdev->dev, reg_np);
@@ -922,6 +937,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
	for (i = 0; i < pdata->num_regulators; i++) {
	for (i = 0; i < pdata->num_regulators; i++) {
		const struct sec_voltage_desc *desc;
		const struct sec_voltage_desc *desc;
		int id = pdata->regulators[i].id;
		int id = pdata->regulators[i].id;
		int enable_reg, enable_val;


		desc = reg_voltage_map[id];
		desc = reg_voltage_map[id];
		if (desc) {
		if (desc) {
@@ -935,6 +951,12 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
				regulators[id].vsel_mask = 0x3f;
				regulators[id].vsel_mask = 0x3f;
			else
			else
				regulators[id].vsel_mask = 0xff;
				regulators[id].vsel_mask = 0xff;

			s5m8767_get_register(s5m8767, id, &enable_reg,
					     &enable_val);
			regulators[id].enable_reg = enable_reg;
			regulators[id].enable_mask = S5M8767_ENCTRL_MASK;
			regulators[id].enable_val = enable_val;
		}
		}


		config.dev = s5m8767->dev;
		config.dev = s5m8767->dev;
@@ -942,6 +964,9 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
		config.driver_data = s5m8767;
		config.driver_data = s5m8767;
		config.regmap = iodev->regmap_pmic;
		config.regmap = iodev->regmap_pmic;
		config.of_node = pdata->regulators[i].reg_node;
		config.of_node = pdata->regulators[i].reg_node;
		if (pdata->regulators[i].ext_control_gpio)
			s5m8767_regulator_config_ext_control(s5m8767,
					&pdata->regulators[i], &config);


		rdev[i] = devm_regulator_register(&pdev->dev, &regulators[id],
		rdev[i] = devm_regulator_register(&pdev->dev, &regulators[id],
						  &config);
						  &config);
@@ -951,6 +976,16 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
					id);
					id);
			return ret;
			return ret;
		}
		}

		if (pdata->regulators[i].ext_control_gpio) {
			ret = s5m8767_enable_ext_control(s5m8767, rdev[i]);
			if (ret < 0) {
				dev_err(s5m8767->dev,
						"failed to enable gpio control over %s: %d\n",
						rdev[i]->desc->name, ret);
				return ret;
			}
		}
	}
	}


	return 0;
	return 0;
Loading