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

Commit 11f24823 authored by Mark Brown's avatar Mark Brown
Browse files

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

Merge remote-tracking branches 'regulator/topic/da9210', 'regulator/topic/da9211', 'regulator/topic/fan53555', 'regulator/topic/isl9305' and 'regulator/topic/list' into regulator-next
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -5,6 +5,10 @@ Required properties:
- compatible:	must be "dlg,da9210"
- compatible:	must be "dlg,da9210"
- reg:		the i2c slave address of the regulator. It should be 0x68.
- reg:		the i2c slave address of the regulator. It should be 0x68.


Optional properties:

- interrupts:	a reference to the DA9210 interrupt, if available.

Any standard regulator properties can be used to configure the single da9210
Any standard regulator properties can be used to configure the single da9210
DCDC.
DCDC.


+30 −2
Original line number Original line Diff line number Diff line
* Dialog Semiconductor DA9211/DA9213 Voltage Regulator
* Dialog Semiconductor DA9211/DA9213/DA9215 Voltage Regulator


Required properties:
Required properties:
- compatible: "dlg,da9211" or "dlg,da9213".
- compatible: "dlg,da9211" or "dlg,da9213" or "dlg,da9215"
- reg: I2C slave address, usually 0x68.
- reg: I2C slave address, usually 0x68.
- interrupts: the interrupt outputs of the controller
- interrupts: the interrupt outputs of the controller
- regulators: A node that houses a sub-node for each regulator within the
- regulators: A node that houses a sub-node for each regulator within the
@@ -66,3 +66,31 @@ Example 2) DA9213
			};
			};
		};
		};
	};
	};


Example 3) DA9215
	pmic: da9215@68 {
		compatible = "dlg,da9215";
		reg = <0x68>;
		interrupts = <3 27>;

		regulators {
			BUCKA {
				regulator-name = "VBUCKA";
				regulator-min-microvolt = < 300000>;
				regulator-max-microvolt = <1570000>;
				regulator-min-microamp 	= <4000000>;
				regulator-max-microamp 	= <7000000>;
				enable-gpios = <&gpio 27 0>;
			};
			BUCKB {
				regulator-name = "VBUCKB";
				regulator-min-microvolt = < 300000>;
				regulator-max-microvolt = <1570000>;
				regulator-min-microamp 	= <4000000>;
				regulator-max-microamp 	= <7000000>;
				enable-gpios = <&gpio 17 0>;
			};
		};
	};
+3 −3
Original line number Original line Diff line number Diff line
@@ -209,13 +209,13 @@ config REGULATOR_DA9210
	  interface.
	  interface.


config REGULATOR_DA9211
config REGULATOR_DA9211
	tristate "Dialog Semiconductor DA9211/DA9212/DA9213/DA9214 regulator"
	tristate "Dialog Semiconductor DA9211/DA9212/DA9213/DA9214/DA9215 regulator"
	depends on I2C
	depends on I2C
	select REGMAP_I2C
	select REGMAP_I2C
	help
	help
	  Say y here to support for the Dialog Semiconductor DA9211/DA9212
	  Say y here to support for the Dialog Semiconductor DA9211/DA9212
	  /DA9213/DA9214.
	  /DA9213/DA9214/DA9215.
	  The DA9211/DA9212/DA9213/DA9214 is a multi-phase synchronous
	  The DA9211/DA9212/DA9213/DA9214/DA9215 is a multi-phase synchronous
	  step down converter 12A or 16A DC-DC Buck controlled through an I2C
	  step down converter 12A or 16A DC-DC Buck controlled through an I2C
	  interface.
	  interface.


+61 −55
Original line number Original line Diff line number Diff line
@@ -111,6 +111,11 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
					  const char *supply_name);
					  const char *supply_name);
static void _regulator_put(struct regulator *regulator);
static void _regulator_put(struct regulator *regulator);


static struct regulator_dev *dev_to_rdev(struct device *dev)
{
	return container_of(dev, struct regulator_dev, dev);
}

static const char *rdev_get_name(struct regulator_dev *rdev)
static const char *rdev_get_name(struct regulator_dev *rdev)
{
{
	if (rdev->constraints && rdev->constraints->name)
	if (rdev->constraints && rdev->constraints->name)
@@ -1612,14 +1617,15 @@ static void _regulator_put(struct regulator *regulator)
	if (regulator->dev)
	if (regulator->dev)
		sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
		sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
	mutex_lock(&rdev->mutex);
	mutex_lock(&rdev->mutex);
	kfree(regulator->supply_name);
	list_del(&regulator->list);
	list_del(&regulator->list);
	kfree(regulator);


	rdev->open_count--;
	rdev->open_count--;
	rdev->exclusive = 0;
	rdev->exclusive = 0;
	mutex_unlock(&rdev->mutex);
	mutex_unlock(&rdev->mutex);


	kfree(regulator->supply_name);
	kfree(regulator);

	module_put(rdev->owner);
	module_put(rdev->owner);
}
}


@@ -3608,6 +3614,9 @@ static const struct attribute_group *regulator_dev_groups[] = {
static void regulator_dev_release(struct device *dev)
static void regulator_dev_release(struct device *dev)
{
{
	struct regulator_dev *rdev = dev_get_drvdata(dev);
	struct regulator_dev *rdev = dev_get_drvdata(dev);

	kfree(rdev->constraints);
	of_node_put(rdev->dev.of_node);
	kfree(rdev);
	kfree(rdev);
}
}


@@ -3839,9 +3848,7 @@ void regulator_unregister(struct regulator_dev *rdev)
	unset_regulator_supplies(rdev);
	unset_regulator_supplies(rdev);
	list_del(&rdev->list);
	list_del(&rdev->list);
	mutex_unlock(&regulator_list_mutex);
	mutex_unlock(&regulator_list_mutex);
	kfree(rdev->constraints);
	regulator_ena_gpio_free(rdev);
	regulator_ena_gpio_free(rdev);
	of_node_put(rdev->dev.of_node);
	device_unregister(&rdev->dev);
	device_unregister(&rdev->dev);
}
}
EXPORT_SYMBOL_GPL(regulator_unregister);
EXPORT_SYMBOL_GPL(regulator_unregister);
@@ -4161,38 +4168,18 @@ static int __init regulator_init(void)
/* init early to allow our consumers to complete system booting */
/* init early to allow our consumers to complete system booting */
core_initcall(regulator_init);
core_initcall(regulator_init);


static int __init regulator_init_complete(void)
static int __init regulator_late_cleanup(struct device *dev, void *data)
{
{
	struct regulator_dev *rdev;
	struct regulator_dev *rdev = dev_to_rdev(dev);
	const struct regulator_ops *ops;
	const struct regulator_ops *ops = rdev->desc->ops;
	struct regulation_constraints *c;
	struct regulation_constraints *c = rdev->constraints;
	int enabled, ret;
	int enabled, ret;


	/*
	 * Since DT doesn't provide an idiomatic mechanism for
	 * enabling full constraints and since it's much more natural
	 * with DT to provide them just assume that a DT enabled
	 * system has full constraints.
	 */
	if (of_have_populated_dt())
		has_full_constraints = true;

	mutex_lock(&regulator_list_mutex);

	/* If we have a full configuration then disable any regulators
	 * we have permission to change the status for and which are
	 * not in use or always_on.  This is effectively the default
	 * for DT and ACPI as they have full constraints.
	 */
	list_for_each_entry(rdev, &regulator_list, list) {
		ops = rdev->desc->ops;
		c = rdev->constraints;

	if (c && c->always_on)
	if (c && c->always_on)
			continue;
		return 0;


	if (c && !(c->valid_ops_mask & REGULATOR_CHANGE_STATUS))
	if (c && !(c->valid_ops_mask & REGULATOR_CHANGE_STATUS))
			continue;
		return 0;


	mutex_lock(&rdev->mutex);
	mutex_lock(&rdev->mutex);


@@ -4209,8 +4196,8 @@ static int __init regulator_init_complete(void)
		goto unlock;
		goto unlock;


	if (have_full_constraints()) {
	if (have_full_constraints()) {
			/* We log since this may kill the system if it
		/* We log since this may kill the system if it goes
			 * goes wrong. */
		 * wrong. */
		rdev_info(rdev, "disabling\n");
		rdev_info(rdev, "disabling\n");
		ret = _regulator_do_disable(rdev);
		ret = _regulator_do_disable(rdev);
		if (ret != 0)
		if (ret != 0)
@@ -4226,9 +4213,28 @@ static int __init regulator_init_complete(void)


unlock:
unlock:
	mutex_unlock(&rdev->mutex);
	mutex_unlock(&rdev->mutex);

	return 0;
}
}


	mutex_unlock(&regulator_list_mutex);
static int __init regulator_init_complete(void)
{
	/*
	 * Since DT doesn't provide an idiomatic mechanism for
	 * enabling full constraints and since it's much more natural
	 * with DT to provide them just assume that a DT enabled
	 * system has full constraints.
	 */
	if (of_have_populated_dt())
		has_full_constraints = true;

	/* If we have a full configuration then disable any regulators
	 * we have permission to change the status for and which are
	 * not in use or always_on.  This is effectively the default
	 * for DT and ACPI as they have full constraints.
	 */
	class_for_each_device(&regulator_class, NULL, NULL,
			      regulator_late_cleanup);


	return 0;
	return 0;
}
}
+75 −0
Original line number Original line Diff line number Diff line
@@ -22,6 +22,8 @@
#include <linux/i2c.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/machine.h>
@@ -120,6 +122,55 @@ static int da9210_get_current_limit(struct regulator_dev *rdev)
	return da9210_buck_limits[sel];
	return da9210_buck_limits[sel];
}
}


static irqreturn_t da9210_irq_handler(int irq, void *data)
{
	struct da9210 *chip = data;
	unsigned int val, handled = 0;
	int error, ret = IRQ_NONE;

	error = regmap_read(chip->regmap, DA9210_REG_EVENT_B, &val);
	if (error < 0)
		goto error_i2c;

	if (val & DA9210_E_OVCURR) {
		regulator_notifier_call_chain(chip->rdev,
					      REGULATOR_EVENT_OVER_CURRENT,
					      NULL);
		handled |= DA9210_E_OVCURR;
	}
	if (val & DA9210_E_NPWRGOOD) {
		regulator_notifier_call_chain(chip->rdev,
					      REGULATOR_EVENT_UNDER_VOLTAGE,
					      NULL);
		handled |= DA9210_E_NPWRGOOD;
	}
	if (val & (DA9210_E_TEMP_WARN | DA9210_E_TEMP_CRIT)) {
		regulator_notifier_call_chain(chip->rdev,
					      REGULATOR_EVENT_OVER_TEMP, NULL);
		handled |= val & (DA9210_E_TEMP_WARN | DA9210_E_TEMP_CRIT);
	}
	if (val & DA9210_E_VMAX) {
		regulator_notifier_call_chain(chip->rdev,
					      REGULATOR_EVENT_REGULATION_OUT,
					      NULL);
		handled |= DA9210_E_VMAX;
	}
	if (handled) {
		/* Clear handled events */
		error = regmap_write(chip->regmap, DA9210_REG_EVENT_B, handled);
		if (error < 0)
			goto error_i2c;

		ret = IRQ_HANDLED;
	}

	return ret;

error_i2c:
	dev_err(regmap_get_device(chip->regmap), "I2C error : %d\n", error);
	return ret;
}

/*
/*
 * I2C driver interface functions
 * I2C driver interface functions
 */
 */
@@ -168,6 +219,30 @@ static int da9210_i2c_probe(struct i2c_client *i2c,
	}
	}


	chip->rdev = rdev;
	chip->rdev = rdev;
	if (i2c->irq) {
		error = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
						  da9210_irq_handler,
						  IRQF_TRIGGER_LOW |
						  IRQF_ONESHOT | IRQF_SHARED,
						  "da9210", chip);
		if (error) {
			dev_err(&i2c->dev, "Failed to request IRQ%u: %d\n",
				i2c->irq, error);
			return error;
		}

		error = regmap_update_bits(chip->regmap, DA9210_REG_MASK_B,
					 DA9210_M_OVCURR | DA9210_M_NPWRGOOD |
					 DA9210_M_TEMP_WARN |
					 DA9210_M_TEMP_CRIT | DA9210_M_VMAX, 0);
		if (error < 0) {
			dev_err(&i2c->dev, "Failed to update mask reg: %d\n",
				error);
			return error;
		}
	} else {
		dev_warn(&i2c->dev, "No IRQ configured\n");
	}


	i2c_set_clientdata(i2c, chip);
	i2c_set_clientdata(i2c, chip);


Loading