All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 1/4] regulator: axp20x: move device independant parts to new files
@ 2016-09-22 17:06   ` Jean-Francois Moine
  0 siblings, 0 replies; 27+ messages in thread
From: Jean-Francois Moine @ 2016-09-22 17:06 UTC (permalink / raw)
  To: Chen-Yu Tsai, Mark Rutland, Rob Herring
  Cc: devicetree, linux-arm-kernel, linux-kernel, linux-sunxi

The axp20x driver contains device specific and device independant parts.
This patch moves the independant parts to new .c/.h files.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
 drivers/regulator/Makefile           |   2 +-
 drivers/regulator/axp-regulator.c    | 308 ++++++++++++++++++++++++++
 drivers/regulator/axp-regulator.h    | 127 +++++++++++
 drivers/regulator/axp20x-regulator.c | 415 +++--------------------------------
 4 files changed, 464 insertions(+), 388 deletions(-)
 create mode 100644 drivers/regulator/axp-regulator.c
 create mode 100644 drivers/regulator/axp-regulator.h

diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 2142a5d..225a026 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -21,7 +21,7 @@ obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
 obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
 obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
 obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
-obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o
+obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o axp-regulator.o
 obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o
 obj-$(CONFIG_REGULATOR_DA903X)	+= da903x.o
 obj-$(CONFIG_REGULATOR_DA9052)	+= da9052-regulator.o
diff --git a/drivers/regulator/axp-regulator.c b/drivers/regulator/axp-regulator.c
new file mode 100644
index 0000000..0d7adb6
--- /dev/null
+++ b/drivers/regulator/axp-regulator.c
@@ -0,0 +1,308 @@
+/*
+ * AXP regulators driver
+ *
+ * Copyright (C) 2016 Jean-Francois Moine <moinejf@free.fr>
+ * Copyright (C) 2013 Carlo Caione <carlo@caione.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/mfd/axp20x.h>
+#include <linux/sunxi-rsb.h>
+
+#include "axp-regulator.h"
+
+#define AXP20X_WORKMODE_DCDC2_MASK	BIT(2)
+#define AXP20X_WORKMODE_DCDC3_MASK	BIT(1)
+#define AXP22X_WORKMODE_DCDCX_MASK(x)	BIT(x)
+
+#define AXP20X_FREQ_DCDC_MASK	0x0f
+
+#define AXP22X_MISC_N_VBUSEN_FUNC	BIT(4)
+
+const struct regulator_ops axp_ops_fixed = {
+	.list_voltage		= regulator_list_voltage_linear,
+};
+EXPORT_SYMBOL_GPL(axp_ops_fixed);
+
+const struct regulator_ops axp_ops_range = {
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.list_voltage		= regulator_list_voltage_linear_range,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.is_enabled		= regulator_is_enabled_regmap,
+};
+EXPORT_SYMBOL_GPL(axp_ops_range);
+
+const struct regulator_ops axp_ops = {
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.list_voltage		= regulator_list_voltage_linear,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.is_enabled		= regulator_is_enabled_regmap,
+};
+EXPORT_SYMBOL_GPL(axp_ops);
+
+const struct regulator_ops axp_ops_sw = {
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.is_enabled		= regulator_is_enabled_regmap,
+};
+EXPORT_SYMBOL_GPL(axp_ops_sw);
+
+static const struct regulator_desc axp22x_drivevbus_regulator = {
+	.name		= "drivevbus",
+	.supply_name	= "drivevbus",
+	.of_match	= of_match_ptr("drivevbus"),
+	.regulators_node = of_match_ptr("regulators"),
+	.type		= REGULATOR_VOLTAGE,
+	.owner		= THIS_MODULE,
+	.enable_reg	= AXP20X_VBUS_IPSOUT_MGMT,
+	.enable_mask	= BIT(2),
+	.ops		= &axp_ops_sw,
+};
+
+static int axp_set_dcdc_freq(struct device *dev,
+					u32 dcdcfreq)
+{
+	struct axp20x_dev *axp20x = dev_get_drvdata(dev);
+	unsigned int reg = AXP20X_DCDC_FREQ;
+	u32 min, max, def, step;
+
+	switch (axp20x->variant) {
+	case AXP202_ID:
+	case AXP209_ID:
+		min = 750;
+		max = 1875;
+		def = 1500;
+		step = 75;
+		break;
+	case AXP806_ID:
+		/*
+		 * AXP806 DCDC work frequency setting has the same range and
+		 * step as AXP22X, but at a different register.
+		 * Fall through to the check below.
+		 * (See include/linux/mfd/axp20x.h)
+		 */
+		reg = AXP806_DCDC_FREQ_CTRL;
+	case AXP221_ID:
+	case AXP223_ID:
+	case AXP809_ID:
+		min = 1800;
+		max = 4050;
+		def = 3000;
+		step = 150;
+		break;
+	default:
+		dev_err(dev,
+			"Setting DCDC frequency for unsupported AXP variant\n");
+		return -EINVAL;
+	}
+
+	if (dcdcfreq == 0)
+		dcdcfreq = def;
+
+	if (dcdcfreq < min) {
+		dcdcfreq = min;
+		dev_warn(dev, "DCDC frequency too low. Set to %ukHz\n",
+			 min);
+	}
+
+	if (dcdcfreq > max) {
+		dcdcfreq = max;
+		dev_warn(dev, "DCDC frequency too high. Set to %ukHz\n",
+			 max);
+	}
+
+	dcdcfreq = (dcdcfreq - min) / step;
+
+	return regmap_update_bits(axp20x->regmap, reg,
+				  AXP20X_FREQ_DCDC_MASK, dcdcfreq);
+}
+
+static int axp_regulator_parse_dt(struct device *dev)
+{
+	struct device_node *np, *regulators;
+	int ret;
+	u32 dcdcfreq = 0;
+
+	np = of_node_get(dev->of_node);
+	if (!np)
+		return 0;
+
+	regulators = of_get_child_by_name(np, "regulators");
+	if (!regulators) {
+		dev_warn(dev, "regulators node not found\n");
+	} else {
+		of_property_read_u32(regulators, "x-powers,dcdc-freq", &dcdcfreq);
+		ret = axp_set_dcdc_freq(dev, dcdcfreq);
+		if (ret < 0) {
+			dev_err(dev, "Error setting dcdc frequency: %d\n", ret);
+			return ret;
+		}
+
+		of_node_put(regulators);
+	}
+
+	return 0;
+}
+
+static int axp_set_dcdc_workmode(struct regulator_dev *rdev,
+				int id, u32 workmode)
+{
+	struct axp20x_dev *axp20x = rdev_get_drvdata(rdev);
+	unsigned int reg = AXP20X_DCDC_MODE;
+	unsigned int mask;
+
+	switch (axp20x->variant) {
+	case AXP202_ID:
+	case AXP209_ID:
+		if ((id != AXP20X_DCDC2) && (id != AXP20X_DCDC3))
+			return -EINVAL;
+
+		mask = AXP20X_WORKMODE_DCDC2_MASK;
+		if (id == AXP20X_DCDC3)
+			mask = AXP20X_WORKMODE_DCDC3_MASK;
+
+		workmode <<= ffs(mask) - 1;
+		break;
+
+	case AXP806_ID:
+		reg = AXP806_DCDC_MODE_CTRL2;
+		/*
+		 * AXP806 DCDC regulator IDs have the same range as AXP22X.
+		 * Fall through to the check below.
+		 * (See include/linux/mfd/axp20x.h)
+		 */
+	case AXP221_ID:
+	case AXP223_ID:
+	case AXP809_ID:
+		if (id < AXP22X_DCDC1 || id > AXP22X_DCDC5)
+			return -EINVAL;
+
+		mask = AXP22X_WORKMODE_DCDCX_MASK(id - AXP22X_DCDC1);
+		workmode <<= id - AXP22X_DCDC1;
+		break;
+
+	default:
+		/* should not happen */
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	return regmap_update_bits(rdev->regmap, reg, mask, workmode);
+}
+
+/* create the regulators */
+int axp_regulator_create(struct device *dev,
+			 const struct axp_cfg *axp_cfg)
+{
+	struct regulator_dev *rdev;
+	struct axp20x_dev *axp20x = dev_get_drvdata(dev);
+	struct regulator_config config = {
+		.dev = dev,
+		.regmap = axp20x->regmap,
+		.driver_data = axp20x,
+	};
+	int ret, i;
+	u32 workmode;
+	const char *dcdc1_name = NULL;
+	const char *dcdc5_name = NULL;
+
+	/* This only sets the dcdc freq. Ignore any errors */
+	axp_regulator_parse_dt(dev);
+
+	for (i = 0; i < axp_cfg->nregulators; i++) {
+		const struct regulator_desc *desc = &axp_cfg->regulators[i];
+		struct regulator_desc *new_desc;
+
+		if (axp_cfg->skip_bitmap & (1 << i))
+			continue;
+
+		/*
+		 * Regulators DC1SW and DC5LDO are connected internally,
+		 * so we have to handle their supply names separately.
+		 *
+		 * We always register the regulators in proper sequence,
+		 * so the supply names are correctly read. See the last
+		 * part of this loop to see where we save the DT defined
+		 * name.
+		 */
+		if (i == axp_cfg->dc1sw_ix && dcdc1_name) {
+			new_desc = devm_kzalloc(dev, sizeof(*desc),
+						GFP_KERNEL);
+			*new_desc = *desc;
+			new_desc->supply_name = dcdc1_name;
+			desc = new_desc;
+		}
+
+		if (i == axp_cfg->dc5ldo_ix && dcdc5_name) {
+			new_desc = devm_kzalloc(dev, sizeof(*desc),
+						GFP_KERNEL);
+			*new_desc = *desc;
+			new_desc->supply_name = dcdc5_name;
+			desc = new_desc;
+		}
+
+		rdev = devm_regulator_register(dev, desc, &config);
+		if (IS_ERR(rdev)) {
+			dev_err(dev, "Failed to register %s\n",
+				axp_cfg->regulators[i].name);
+
+			return PTR_ERR(rdev);
+		}
+
+		ret = of_property_read_u32(rdev->dev.of_node,
+					   "x-powers,dcdc-workmode",
+					   &workmode);
+		if (!ret) {
+			if (axp_set_dcdc_workmode(rdev, i, workmode))
+				dev_err(dev, "Failed to set workmode on %s\n",
+					rdev->desc->name);
+		}
+
+		/*
+		 * Save AXP22X DCDC1 / DCDC5 regulator names for later.
+		 */
+		if (i == axp_cfg->dcdc1_ix)
+			of_property_read_string(rdev->dev.of_node,
+						"regulator-name",
+						&dcdc1_name);
+		if (i == axp_cfg->dcdc5_ix)
+			of_property_read_string(rdev->dev.of_node,
+						"regulator-name",
+						&dcdc5_name);
+	}
+
+	if (axp_cfg->drivevbus) {
+		/* Change N_VBUSEN sense pin to DRIVEVBUS output pin */
+		regmap_update_bits(axp20x->regmap, AXP20X_OVER_TMP,
+				   AXP22X_MISC_N_VBUSEN_FUNC, 0);
+		rdev = devm_regulator_register(dev,
+					       &axp22x_drivevbus_regulator,
+					       &config);
+		if (IS_ERR(rdev)) {
+			dev_err(dev, "Failed to register drivevbus\n");
+			return PTR_ERR(rdev);
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(axp_regulator_create);
+
+MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
+MODULE_DESCRIPTION("Regulator Module for AXP PMIC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/axp-regulator.h b/drivers/regulator/axp-regulator.h
new file mode 100644
index 0000000..0adf1b0
--- /dev/null
+++ b/drivers/regulator/axp-regulator.h
@@ -0,0 +1,127 @@
+#ifndef __AXP_REGULATOR_H__
+#define __AXP_REGULATOR_H__
+/*
+ * Copyright (C) 2016 Jean-Francois Moine <moinejf@free.fr>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#define AXP20X_IO_ENABLED		0x03
+#define AXP20X_IO_DISABLED		0x07
+
+#define AXP22X_IO_ENABLED		0x03
+#define AXP22X_IO_DISABLED		0x04
+
+#define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg,	\
+		    _vmask, _ereg, _emask, _enable_val, _disable_val)		\
+	[_family##_##_id] = {							\
+		.name		= (_match),					\
+		.supply_name	= (_supply),					\
+		.of_match	= of_match_ptr(_match),				\
+		.regulators_node = of_match_ptr("regulators"),			\
+		.type		= REGULATOR_VOLTAGE,				\
+		.id		= _family##_##_id,				\
+		.n_voltages	= (((_max) - (_min)) / (_step) + 1),		\
+		.owner		= THIS_MODULE,					\
+		.min_uV		= (_min) * 1000,				\
+		.uV_step	= (_step) * 1000,				\
+		.vsel_reg	= (_vreg),					\
+		.vsel_mask	= (_vmask),					\
+		.enable_reg	= (_ereg),					\
+		.enable_mask	= (_emask),					\
+		.enable_val	= (_enable_val),				\
+		.disable_val	= (_disable_val),				\
+		.ops		= &axp_ops,					\
+	}
+
+#define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg,	\
+		 _vmask, _ereg, _emask) 					\
+	[_family##_##_id] = {							\
+		.name		= (_match),					\
+		.supply_name	= (_supply),					\
+		.of_match	= of_match_ptr(_match),				\
+		.regulators_node = of_match_ptr("regulators"),			\
+		.type		= REGULATOR_VOLTAGE,				\
+		.id		= _family##_##_id,				\
+		.n_voltages	= (((_max) - (_min)) / (_step) + 1),		\
+		.owner		= THIS_MODULE,					\
+		.min_uV		= (_min) * 1000,				\
+		.uV_step	= (_step) * 1000,				\
+		.vsel_reg	= (_vreg),					\
+		.vsel_mask	= (_vmask),					\
+		.enable_reg	= (_ereg),					\
+		.enable_mask	= (_emask),					\
+		.ops		= &axp_ops,					\
+	}
+
+#define AXP_DESC_SW(_family, _id, _match, _supply, _ereg, _emask)		\
+	[_family##_##_id] = {							\
+		.name		= (_match),					\
+		.supply_name	= (_supply),					\
+		.of_match	= of_match_ptr(_match),				\
+		.regulators_node = of_match_ptr("regulators"),			\
+		.type		= REGULATOR_VOLTAGE,				\
+		.id		= _family##_##_id,				\
+		.owner		= THIS_MODULE,					\
+		.enable_reg	= (_ereg),					\
+		.enable_mask	= (_emask),					\
+		.ops		= &axp_ops_sw,					\
+	}
+
+#define AXP_DESC_FIXED(_family, _id, _match, _supply, _volt)			\
+	[_family##_##_id] = {							\
+		.name		= (_match),					\
+		.supply_name	= (_supply),					\
+		.of_match	= of_match_ptr(_match),				\
+		.regulators_node = of_match_ptr("regulators"),			\
+		.type		= REGULATOR_VOLTAGE,				\
+		.id		= _family##_##_id,				\
+		.n_voltages	= 1,						\
+		.owner		= THIS_MODULE,					\
+		.min_uV		= (_volt) * 1000,				\
+		.ops		= &axp_ops_fixed				\
+	}
+
+#define AXP_DESC_RANGES(_family, _id, _match, _supply, _ranges, _n_voltages,	\
+			_vreg, _vmask, _ereg, _emask)				\
+	[_family##_##_id] = {							\
+		.name		= (_match),					\
+		.supply_name	= (_supply),					\
+		.of_match	= of_match_ptr(_match),				\
+		.regulators_node = of_match_ptr("regulators"),			\
+		.type		= REGULATOR_VOLTAGE,				\
+		.id		= _family##_##_id,				\
+		.n_voltages	= (_n_voltages),				\
+		.owner		= THIS_MODULE,					\
+		.vsel_reg	= (_vreg),					\
+		.vsel_mask	= (_vmask),					\
+		.enable_reg	= (_ereg),					\
+		.enable_mask	= (_emask),					\
+		.linear_ranges	= (_ranges),					\
+		.n_linear_ranges = ARRAY_SIZE(_ranges),				\
+		.ops		= &axp_ops_range,				\
+	}
+
+extern const struct regulator_ops axp_ops;
+extern const struct regulator_ops axp_ops_fixed;
+extern const struct regulator_ops axp_ops_range;
+extern const struct regulator_ops axp_ops_sw;
+
+struct axp_cfg {
+	const struct regulator_desc *regulators;
+	u8 nregulators;
+	s8 dcdc1_ix;
+	s8 dcdc5_ix;
+	s8 dc1sw_ix;
+	s8 dc5ldo_ix;
+	u32 skip_bitmap;
+	bool drivevbus;
+};
+
+int axp_regulator_create(struct device *dev,
+			 const struct axp_cfg *axp_cfg);
+
+#endif /* __AXP_REGULATOR_H__ */
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index 244ddc3..9dd9ca3 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -24,137 +24,7 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/of_regulator.h>
 
-#define AXP20X_IO_ENABLED		0x03
-#define AXP20X_IO_DISABLED		0x07
-
-#define AXP22X_IO_ENABLED		0x03
-#define AXP22X_IO_DISABLED		0x04
-
-#define AXP20X_WORKMODE_DCDC2_MASK	BIT(2)
-#define AXP20X_WORKMODE_DCDC3_MASK	BIT(1)
-#define AXP22X_WORKMODE_DCDCX_MASK(x)	BIT(x)
-
-#define AXP20X_FREQ_DCDC_MASK		0x0f
-
-#define AXP22X_MISC_N_VBUSEN_FUNC	BIT(4)
-
-#define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg,	\
-		    _vmask, _ereg, _emask, _enable_val, _disable_val)		\
-	[_family##_##_id] = {							\
-		.name		= (_match),					\
-		.supply_name	= (_supply),					\
-		.of_match	= of_match_ptr(_match),				\
-		.regulators_node = of_match_ptr("regulators"),			\
-		.type		= REGULATOR_VOLTAGE,				\
-		.id		= _family##_##_id,				\
-		.n_voltages	= (((_max) - (_min)) / (_step) + 1),		\
-		.owner		= THIS_MODULE,					\
-		.min_uV		= (_min) * 1000,				\
-		.uV_step	= (_step) * 1000,				\
-		.vsel_reg	= (_vreg),					\
-		.vsel_mask	= (_vmask),					\
-		.enable_reg	= (_ereg),					\
-		.enable_mask	= (_emask),					\
-		.enable_val	= (_enable_val),				\
-		.disable_val	= (_disable_val),				\
-		.ops		= &axp20x_ops,					\
-	}
-
-#define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg,	\
-		 _vmask, _ereg, _emask) 					\
-	[_family##_##_id] = {							\
-		.name		= (_match),					\
-		.supply_name	= (_supply),					\
-		.of_match	= of_match_ptr(_match),				\
-		.regulators_node = of_match_ptr("regulators"),			\
-		.type		= REGULATOR_VOLTAGE,				\
-		.id		= _family##_##_id,				\
-		.n_voltages	= (((_max) - (_min)) / (_step) + 1),		\
-		.owner		= THIS_MODULE,					\
-		.min_uV		= (_min) * 1000,				\
-		.uV_step	= (_step) * 1000,				\
-		.vsel_reg	= (_vreg),					\
-		.vsel_mask	= (_vmask),					\
-		.enable_reg	= (_ereg),					\
-		.enable_mask	= (_emask),					\
-		.ops		= &axp20x_ops,					\
-	}
-
-#define AXP_DESC_SW(_family, _id, _match, _supply, _ereg, _emask)		\
-	[_family##_##_id] = {							\
-		.name		= (_match),					\
-		.supply_name	= (_supply),					\
-		.of_match	= of_match_ptr(_match),				\
-		.regulators_node = of_match_ptr("regulators"),			\
-		.type		= REGULATOR_VOLTAGE,				\
-		.id		= _family##_##_id,				\
-		.owner		= THIS_MODULE,					\
-		.enable_reg	= (_ereg),					\
-		.enable_mask	= (_emask),					\
-		.ops		= &axp20x_ops_sw,				\
-	}
-
-#define AXP_DESC_FIXED(_family, _id, _match, _supply, _volt)			\
-	[_family##_##_id] = {							\
-		.name		= (_match),					\
-		.supply_name	= (_supply),					\
-		.of_match	= of_match_ptr(_match),				\
-		.regulators_node = of_match_ptr("regulators"),			\
-		.type		= REGULATOR_VOLTAGE,				\
-		.id		= _family##_##_id,				\
-		.n_voltages	= 1,						\
-		.owner		= THIS_MODULE,					\
-		.min_uV		= (_volt) * 1000,				\
-		.ops		= &axp20x_ops_fixed				\
-	}
-
-#define AXP_DESC_RANGES(_family, _id, _match, _supply, _ranges, _n_voltages,	\
-			_vreg, _vmask, _ereg, _emask)				\
-	[_family##_##_id] = {							\
-		.name		= (_match),					\
-		.supply_name	= (_supply),					\
-		.of_match	= of_match_ptr(_match),				\
-		.regulators_node = of_match_ptr("regulators"),			\
-		.type		= REGULATOR_VOLTAGE,				\
-		.id		= _family##_##_id,				\
-		.n_voltages	= (_n_voltages),				\
-		.owner		= THIS_MODULE,					\
-		.vsel_reg	= (_vreg),					\
-		.vsel_mask	= (_vmask),					\
-		.enable_reg	= (_ereg),					\
-		.enable_mask	= (_emask),					\
-		.linear_ranges	= (_ranges),					\
-		.n_linear_ranges = ARRAY_SIZE(_ranges),				\
-		.ops		= &axp20x_ops_range,				\
-	}
-
-static struct regulator_ops axp20x_ops_fixed = {
-	.list_voltage		= regulator_list_voltage_linear,
-};
-
-static struct regulator_ops axp20x_ops_range = {
-	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
-	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
-	.list_voltage		= regulator_list_voltage_linear_range,
-	.enable			= regulator_enable_regmap,
-	.disable		= regulator_disable_regmap,
-	.is_enabled		= regulator_is_enabled_regmap,
-};
-
-static struct regulator_ops axp20x_ops = {
-	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
-	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
-	.list_voltage		= regulator_list_voltage_linear,
-	.enable			= regulator_enable_regmap,
-	.disable		= regulator_disable_regmap,
-	.is_enabled		= regulator_is_enabled_regmap,
-};
-
-static struct regulator_ops axp20x_ops_sw = {
-	.enable			= regulator_enable_regmap,
-	.disable		= regulator_disable_regmap,
-	.is_enabled		= regulator_is_enabled_regmap,
-};
+#include "axp-regulator.h"
 
 static const struct regulator_linear_range axp20x_ldo4_ranges[] = {
 	REGULATOR_LINEAR_RANGE(1250000, 0x0, 0x0, 0),
@@ -232,18 +102,6 @@ static const struct regulator_desc axp22x_regulators[] = {
 	AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtc_ldo", "ips", 3000),
 };
 
-static const struct regulator_desc axp22x_drivevbus_regulator = {
-	.name		= "drivevbus",
-	.supply_name	= "drivevbus",
-	.of_match	= of_match_ptr("drivevbus"),
-	.regulators_node = of_match_ptr("regulators"),
-	.type		= REGULATOR_VOLTAGE,
-	.owner		= THIS_MODULE,
-	.enable_reg	= AXP20X_VBUS_IPSOUT_MGMT,
-	.enable_mask	= BIT(2),
-	.ops		= &axp20x_ops_sw,
-};
-
 static const struct regulator_linear_range axp806_dcdca_ranges[] = {
 	REGULATOR_LINEAR_RANGE(600000, 0x0, 0x32, 10000),
 	REGULATOR_LINEAR_RANGE(1120000, 0x33, 0x47, 20000),
@@ -347,135 +205,6 @@ static const struct regulator_desc axp809_regulators[] = {
 	AXP_DESC_SW(AXP809, SW, "sw", "swin", AXP22X_PWR_OUT_CTRL2, BIT(6)),
 };
 
-static int axp20x_set_dcdc_freq(struct device *dev, u32 dcdcfreq)
-{
-	struct axp20x_dev *axp20x = dev_get_drvdata(dev);
-	unsigned int reg = AXP20X_DCDC_FREQ;
-	u32 min, max, def, step;
-
-	switch (axp20x->variant) {
-	case AXP202_ID:
-	case AXP209_ID:
-		min = 750;
-		max = 1875;
-		def = 1500;
-		step = 75;
-		break;
-	case AXP806_ID:
-		/*
-		 * AXP806 DCDC work frequency setting has the same range and
-		 * step as AXP22X, but at a different register.
-		 * Fall through to the check below.
-		 * (See include/linux/mfd/axp20x.h)
-		 */
-		reg = AXP806_DCDC_FREQ_CTRL;
-	case AXP221_ID:
-	case AXP223_ID:
-	case AXP809_ID:
-		min = 1800;
-		max = 4050;
-		def = 3000;
-		step = 150;
-		break;
-	default:
-		dev_err(dev,
-			"Setting DCDC frequency for unsupported AXP variant\n");
-		return -EINVAL;
-	}
-
-	if (dcdcfreq == 0)
-		dcdcfreq = def;
-
-	if (dcdcfreq < min) {
-		dcdcfreq = min;
-		dev_warn(dev, "DCDC frequency too low. Set to %ukHz\n",
-			 min);
-	}
-
-	if (dcdcfreq > max) {
-		dcdcfreq = max;
-		dev_warn(dev, "DCDC frequency too high. Set to %ukHz\n",
-			 max);
-	}
-
-	dcdcfreq = (dcdcfreq - min) / step;
-
-	return regmap_update_bits(axp20x->regmap, reg,
-				  AXP20X_FREQ_DCDC_MASK, dcdcfreq);
-}
-
-static int axp20x_regulator_parse_dt(struct device *dev)
-{
-	struct device_node *np, *regulators;
-	int ret;
-	u32 dcdcfreq = 0;
-
-	np = of_node_get(dev->of_node);
-	if (!np)
-		return 0;
-
-	regulators = of_get_child_by_name(np, "regulators");
-	if (!regulators) {
-		dev_warn(dev, "regulators node not found\n");
-	} else {
-		of_property_read_u32(regulators, "x-powers,dcdc-freq", &dcdcfreq);
-		ret = axp20x_set_dcdc_freq(dev, dcdcfreq);
-		if (ret < 0) {
-			dev_err(dev, "Error setting dcdc frequency: %d\n", ret);
-			return ret;
-		}
-
-		of_node_put(regulators);
-	}
-
-	return 0;
-}
-
-static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 workmode)
-{
-	struct axp20x_dev *axp20x = rdev_get_drvdata(rdev);
-	unsigned int reg = AXP20X_DCDC_MODE;
-	unsigned int mask;
-
-	switch (axp20x->variant) {
-	case AXP202_ID:
-	case AXP209_ID:
-		if ((id != AXP20X_DCDC2) && (id != AXP20X_DCDC3))
-			return -EINVAL;
-
-		mask = AXP20X_WORKMODE_DCDC2_MASK;
-		if (id == AXP20X_DCDC3)
-			mask = AXP20X_WORKMODE_DCDC3_MASK;
-
-		workmode <<= ffs(mask) - 1;
-		break;
-
-	case AXP806_ID:
-		reg = AXP806_DCDC_MODE_CTRL2;
-		/*
-		 * AXP806 DCDC regulator IDs have the same range as AXP22X.
-		 * Fall through to the check below.
-		 * (See include/linux/mfd/axp20x.h)
-		 */
-	case AXP221_ID:
-	case AXP223_ID:
-	case AXP809_ID:
-		if (id < AXP22X_DCDC1 || id > AXP22X_DCDC5)
-			return -EINVAL;
-
-		mask = AXP22X_WORKMODE_DCDCX_MASK(id - AXP22X_DCDC1);
-		workmode <<= id - AXP22X_DCDC1;
-		break;
-
-	default:
-		/* should not happen */
-		WARN_ON(1);
-		return -EINVAL;
-	}
-
-	return regmap_update_bits(rdev->regmap, reg, mask, workmode);
-}
-
 /*
  * This function checks which regulators are part of poly-phase
  * output setups based on the registers settings.
@@ -500,60 +229,51 @@ static u32 axp20x_polyphase_slave(struct axp20x_dev *axp20x)
 static int axp20x_regulator_probe(struct platform_device *pdev)
 {
 	struct device *dev = pdev->dev.parent;
-	struct regulator_dev *rdev;
 	struct axp20x_dev *axp20x = dev_get_drvdata(dev);
-	const struct regulator_desc *regulators;
-	struct regulator_config config = {
-		.dev = dev,
-		.regmap = axp20x->regmap,
-		.driver_data = axp20x,
-	};
-	int ret, i, nregulators;
-	u32 workmode;
-	const char *dcdc1_name = axp22x_regulators[AXP22X_DCDC1].name;
-	const char *dcdc5_name = axp22x_regulators[AXP22X_DCDC5].name;
-	s8 dcdc1_ix = -1;
-	s8 dcdc5_ix = -1;
-	s8 dc1sw_ix = -1;
-	s8 dc5ldo_ix = -1;
-	bool drivevbus = false;
-	u32 skip_bitmap = 0;
+	struct axp_cfg axp_cfg;
+
+	axp_cfg.dcdc1_ix = -1;
+	axp_cfg.dcdc5_ix = -1;
+	axp_cfg.dc1sw_ix = -1;
+	axp_cfg.dc5ldo_ix = -1;
+	axp_cfg.drivevbus = false;
+	axp_cfg.skip_bitmap = 0;
 
 	switch (axp20x->variant) {
 	case AXP202_ID:
 	case AXP209_ID:
-		regulators = axp20x_regulators;
-		nregulators = AXP20X_REG_ID_MAX;
+		axp_cfg.regulators = axp20x_regulators;
+		axp_cfg.nregulators = AXP20X_REG_ID_MAX;
 		break;
 	case AXP221_ID:
 	case AXP223_ID:
-		regulators = axp22x_regulators;
-		nregulators = AXP22X_REG_ID_MAX;
-		dcdc1_ix = AXP22X_DCDC1;
-		dcdc5_ix = AXP22X_DCDC5;
-		dc1sw_ix = AXP22X_DC1SW;
-		dc5ldo_ix = AXP22X_DC5LDO;
-		drivevbus = of_property_read_bool(dev->of_node,
+		axp_cfg.regulators = axp22x_regulators;
+		axp_cfg.nregulators = AXP22X_REG_ID_MAX;
+		axp_cfg.dcdc1_ix = AXP22X_DCDC1;
+		axp_cfg.dcdc5_ix = AXP22X_DCDC5;
+		axp_cfg.dc1sw_ix = AXP22X_DC1SW;
+		axp_cfg.dc5ldo_ix = AXP22X_DC5LDO;
+		axp_cfg.drivevbus = of_property_read_bool(dev->of_node,
 						  "x-powers,drive-vbus-en");
 		break;
 	case AXP806_ID:
-		regulators = axp806_regulators;
-		nregulators = AXP806_REG_ID_MAX;
+		axp_cfg.regulators = axp806_regulators;
+		axp_cfg.nregulators = AXP806_REG_ID_MAX;
 
 		/*
 		 * The regulators which are slave in a poly-phase setup
 		 * are skipped, as their controls are bound to the master
 		 * regulator and won't work.
 		 */
-		skip_bitmap |= axp20x_polyphase_slave(axp20x);
+		axp_cfg.skip_bitmap |= axp20x_polyphase_slave(axp20x);
 		break;
 	case AXP809_ID:
-		regulators = axp809_regulators;
-		nregulators = AXP809_REG_ID_MAX;
-		dcdc1_ix = AXP809_DCDC1;
-		dcdc5_ix = AXP809_DCDC5;
-		dc1sw_ix = AXP809_DC1SW;
-		dc5ldo_ix = AXP809_DC5LDO;
+		axp_cfg.regulators = axp809_regulators;
+		axp_cfg.nregulators = AXP809_REG_ID_MAX;
+		axp_cfg.dcdc1_ix = AXP809_DCDC1;
+		axp_cfg.dcdc5_ix = AXP809_DCDC5;
+		axp_cfg.dc1sw_ix = AXP809_DC1SW;
+		axp_cfg.dc5ldo_ix = AXP809_DC5LDO;
 		break;
 	default:
 		dev_err(dev, "Unsupported AXP variant: %ld\n",
@@ -561,86 +281,7 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	/* This only sets the dcdc freq. Ignore any errors */
-	axp20x_regulator_parse_dt(dev);
-
-	for (i = 0; i < nregulators; i++) {
-		const struct regulator_desc *desc = &regulators[i];
-		struct regulator_desc *new_desc;
-
-		if (skip_bitmap & (1 << i))
-			continue;
-
-		/*
-		 * Regulators DC1SW and DC5LDO are connected internally,
-		 * so we have to handle their supply names separately.
-		 *
-		 * We always register the regulators in proper sequence,
-		 * so the supply names are correctly read. See the last
-		 * part of this loop to see where we save the DT defined
-		 * name.
-		 */
-		if (i == dc1sw_ix && dcdc1_name) {
-			new_desc = devm_kzalloc(dev, sizeof(*desc),
-						GFP_KERNEL);
-			*new_desc = regulators[i];
-			new_desc->supply_name = dcdc1_name;
-			desc = new_desc;
-		}
-
-		if (i == dc5ldo_ix && dcdc5_name) {
-			new_desc = devm_kzalloc(dev, sizeof(*desc),
-						GFP_KERNEL);
-			*new_desc = regulators[i];
-			new_desc->supply_name = dcdc5_name;
-			desc = new_desc;
-		}
-
-		rdev = devm_regulator_register(dev, desc, &config);
-		if (IS_ERR(rdev)) {
-			dev_err(dev, "Failed to register %s\n",
-				regulators[i].name);
-
-			return PTR_ERR(rdev);
-		}
-
-		ret = of_property_read_u32(rdev->dev.of_node,
-					   "x-powers,dcdc-workmode",
-					   &workmode);
-		if (!ret) {
-			if (axp20x_set_dcdc_workmode(rdev, i, workmode))
-				dev_err(dev, "Failed to set workmode on %s\n",
-					rdev->desc->name);
-		}
-
-		/*
-		 * Save AXP22X DCDC1 / DCDC5 regulator names for later.
-		 */
-		if (i == dcdc1_ix)
-			of_property_read_string(rdev->dev.of_node,
-						"regulator-name",
-						&dcdc1_name);
-
-		if (i == dcdc5_ix)
-			of_property_read_string(rdev->dev.of_node,
-						"regulator-name",
-						&dcdc5_name);
-	}
-
-	if (drivevbus) {
-		/* Change N_VBUSEN sense pin to DRIVEVBUS output pin */
-		regmap_update_bits(axp20x->regmap, AXP20X_OVER_TMP,
-				   AXP22X_MISC_N_VBUSEN_FUNC, 0);
-		rdev = devm_regulator_register(dev,
-					       &axp22x_drivevbus_regulator,
-					       &config);
-		if (IS_ERR(rdev)) {
-			dev_err(dev, "Failed to register drivevbus\n");
-			return PTR_ERR(rdev);
-		}
-	}
-
-	return 0;
+	return axp_regulator_create(dev, &axp_cfg);
 }
 
 static struct platform_driver axp20x_regulator_driver = {
-- 
2.10.0

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 1/4] regulator: axp20x: move device independant parts to new files
@ 2016-09-22 17:06   ` Jean-Francois Moine
  0 siblings, 0 replies; 27+ messages in thread
From: Jean-Francois Moine @ 2016-09-22 17:06 UTC (permalink / raw)
  To: Chen-Yu Tsai, Mark Rutland, Rob Herring
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw

The axp20x driver contains device specific and device independant parts.
This patch moves the independant parts to new .c/.h files.

Signed-off-by: Jean-Francois Moine <moinejf-GANU6spQydw@public.gmane.org>
---
 drivers/regulator/Makefile           |   2 +-
 drivers/regulator/axp-regulator.c    | 308 ++++++++++++++++++++++++++
 drivers/regulator/axp-regulator.h    | 127 +++++++++++
 drivers/regulator/axp20x-regulator.c | 415 +++--------------------------------
 4 files changed, 464 insertions(+), 388 deletions(-)
 create mode 100644 drivers/regulator/axp-regulator.c
 create mode 100644 drivers/regulator/axp-regulator.h

diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 2142a5d..225a026 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -21,7 +21,7 @@ obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
 obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
 obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
 obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
-obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o
+obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o axp-regulator.o
 obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o
 obj-$(CONFIG_REGULATOR_DA903X)	+= da903x.o
 obj-$(CONFIG_REGULATOR_DA9052)	+= da9052-regulator.o
diff --git a/drivers/regulator/axp-regulator.c b/drivers/regulator/axp-regulator.c
new file mode 100644
index 0000000..0d7adb6
--- /dev/null
+++ b/drivers/regulator/axp-regulator.c
@@ -0,0 +1,308 @@
+/*
+ * AXP regulators driver
+ *
+ * Copyright (C) 2016 Jean-Francois Moine <moinejf-GANU6spQydw@public.gmane.org>
+ * Copyright (C) 2013 Carlo Caione <carlo-KA+7E9HrN00dnm+yROfE0A@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/mfd/axp20x.h>
+#include <linux/sunxi-rsb.h>
+
+#include "axp-regulator.h"
+
+#define AXP20X_WORKMODE_DCDC2_MASK	BIT(2)
+#define AXP20X_WORKMODE_DCDC3_MASK	BIT(1)
+#define AXP22X_WORKMODE_DCDCX_MASK(x)	BIT(x)
+
+#define AXP20X_FREQ_DCDC_MASK	0x0f
+
+#define AXP22X_MISC_N_VBUSEN_FUNC	BIT(4)
+
+const struct regulator_ops axp_ops_fixed = {
+	.list_voltage		= regulator_list_voltage_linear,
+};
+EXPORT_SYMBOL_GPL(axp_ops_fixed);
+
+const struct regulator_ops axp_ops_range = {
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.list_voltage		= regulator_list_voltage_linear_range,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.is_enabled		= regulator_is_enabled_regmap,
+};
+EXPORT_SYMBOL_GPL(axp_ops_range);
+
+const struct regulator_ops axp_ops = {
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.list_voltage		= regulator_list_voltage_linear,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.is_enabled		= regulator_is_enabled_regmap,
+};
+EXPORT_SYMBOL_GPL(axp_ops);
+
+const struct regulator_ops axp_ops_sw = {
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.is_enabled		= regulator_is_enabled_regmap,
+};
+EXPORT_SYMBOL_GPL(axp_ops_sw);
+
+static const struct regulator_desc axp22x_drivevbus_regulator = {
+	.name		= "drivevbus",
+	.supply_name	= "drivevbus",
+	.of_match	= of_match_ptr("drivevbus"),
+	.regulators_node = of_match_ptr("regulators"),
+	.type		= REGULATOR_VOLTAGE,
+	.owner		= THIS_MODULE,
+	.enable_reg	= AXP20X_VBUS_IPSOUT_MGMT,
+	.enable_mask	= BIT(2),
+	.ops		= &axp_ops_sw,
+};
+
+static int axp_set_dcdc_freq(struct device *dev,
+					u32 dcdcfreq)
+{
+	struct axp20x_dev *axp20x = dev_get_drvdata(dev);
+	unsigned int reg = AXP20X_DCDC_FREQ;
+	u32 min, max, def, step;
+
+	switch (axp20x->variant) {
+	case AXP202_ID:
+	case AXP209_ID:
+		min = 750;
+		max = 1875;
+		def = 1500;
+		step = 75;
+		break;
+	case AXP806_ID:
+		/*
+		 * AXP806 DCDC work frequency setting has the same range and
+		 * step as AXP22X, but at a different register.
+		 * Fall through to the check below.
+		 * (See include/linux/mfd/axp20x.h)
+		 */
+		reg = AXP806_DCDC_FREQ_CTRL;
+	case AXP221_ID:
+	case AXP223_ID:
+	case AXP809_ID:
+		min = 1800;
+		max = 4050;
+		def = 3000;
+		step = 150;
+		break;
+	default:
+		dev_err(dev,
+			"Setting DCDC frequency for unsupported AXP variant\n");
+		return -EINVAL;
+	}
+
+	if (dcdcfreq == 0)
+		dcdcfreq = def;
+
+	if (dcdcfreq < min) {
+		dcdcfreq = min;
+		dev_warn(dev, "DCDC frequency too low. Set to %ukHz\n",
+			 min);
+	}
+
+	if (dcdcfreq > max) {
+		dcdcfreq = max;
+		dev_warn(dev, "DCDC frequency too high. Set to %ukHz\n",
+			 max);
+	}
+
+	dcdcfreq = (dcdcfreq - min) / step;
+
+	return regmap_update_bits(axp20x->regmap, reg,
+				  AXP20X_FREQ_DCDC_MASK, dcdcfreq);
+}
+
+static int axp_regulator_parse_dt(struct device *dev)
+{
+	struct device_node *np, *regulators;
+	int ret;
+	u32 dcdcfreq = 0;
+
+	np = of_node_get(dev->of_node);
+	if (!np)
+		return 0;
+
+	regulators = of_get_child_by_name(np, "regulators");
+	if (!regulators) {
+		dev_warn(dev, "regulators node not found\n");
+	} else {
+		of_property_read_u32(regulators, "x-powers,dcdc-freq", &dcdcfreq);
+		ret = axp_set_dcdc_freq(dev, dcdcfreq);
+		if (ret < 0) {
+			dev_err(dev, "Error setting dcdc frequency: %d\n", ret);
+			return ret;
+		}
+
+		of_node_put(regulators);
+	}
+
+	return 0;
+}
+
+static int axp_set_dcdc_workmode(struct regulator_dev *rdev,
+				int id, u32 workmode)
+{
+	struct axp20x_dev *axp20x = rdev_get_drvdata(rdev);
+	unsigned int reg = AXP20X_DCDC_MODE;
+	unsigned int mask;
+
+	switch (axp20x->variant) {
+	case AXP202_ID:
+	case AXP209_ID:
+		if ((id != AXP20X_DCDC2) && (id != AXP20X_DCDC3))
+			return -EINVAL;
+
+		mask = AXP20X_WORKMODE_DCDC2_MASK;
+		if (id == AXP20X_DCDC3)
+			mask = AXP20X_WORKMODE_DCDC3_MASK;
+
+		workmode <<= ffs(mask) - 1;
+		break;
+
+	case AXP806_ID:
+		reg = AXP806_DCDC_MODE_CTRL2;
+		/*
+		 * AXP806 DCDC regulator IDs have the same range as AXP22X.
+		 * Fall through to the check below.
+		 * (See include/linux/mfd/axp20x.h)
+		 */
+	case AXP221_ID:
+	case AXP223_ID:
+	case AXP809_ID:
+		if (id < AXP22X_DCDC1 || id > AXP22X_DCDC5)
+			return -EINVAL;
+
+		mask = AXP22X_WORKMODE_DCDCX_MASK(id - AXP22X_DCDC1);
+		workmode <<= id - AXP22X_DCDC1;
+		break;
+
+	default:
+		/* should not happen */
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	return regmap_update_bits(rdev->regmap, reg, mask, workmode);
+}
+
+/* create the regulators */
+int axp_regulator_create(struct device *dev,
+			 const struct axp_cfg *axp_cfg)
+{
+	struct regulator_dev *rdev;
+	struct axp20x_dev *axp20x = dev_get_drvdata(dev);
+	struct regulator_config config = {
+		.dev = dev,
+		.regmap = axp20x->regmap,
+		.driver_data = axp20x,
+	};
+	int ret, i;
+	u32 workmode;
+	const char *dcdc1_name = NULL;
+	const char *dcdc5_name = NULL;
+
+	/* This only sets the dcdc freq. Ignore any errors */
+	axp_regulator_parse_dt(dev);
+
+	for (i = 0; i < axp_cfg->nregulators; i++) {
+		const struct regulator_desc *desc = &axp_cfg->regulators[i];
+		struct regulator_desc *new_desc;
+
+		if (axp_cfg->skip_bitmap & (1 << i))
+			continue;
+
+		/*
+		 * Regulators DC1SW and DC5LDO are connected internally,
+		 * so we have to handle their supply names separately.
+		 *
+		 * We always register the regulators in proper sequence,
+		 * so the supply names are correctly read. See the last
+		 * part of this loop to see where we save the DT defined
+		 * name.
+		 */
+		if (i == axp_cfg->dc1sw_ix && dcdc1_name) {
+			new_desc = devm_kzalloc(dev, sizeof(*desc),
+						GFP_KERNEL);
+			*new_desc = *desc;
+			new_desc->supply_name = dcdc1_name;
+			desc = new_desc;
+		}
+
+		if (i == axp_cfg->dc5ldo_ix && dcdc5_name) {
+			new_desc = devm_kzalloc(dev, sizeof(*desc),
+						GFP_KERNEL);
+			*new_desc = *desc;
+			new_desc->supply_name = dcdc5_name;
+			desc = new_desc;
+		}
+
+		rdev = devm_regulator_register(dev, desc, &config);
+		if (IS_ERR(rdev)) {
+			dev_err(dev, "Failed to register %s\n",
+				axp_cfg->regulators[i].name);
+
+			return PTR_ERR(rdev);
+		}
+
+		ret = of_property_read_u32(rdev->dev.of_node,
+					   "x-powers,dcdc-workmode",
+					   &workmode);
+		if (!ret) {
+			if (axp_set_dcdc_workmode(rdev, i, workmode))
+				dev_err(dev, "Failed to set workmode on %s\n",
+					rdev->desc->name);
+		}
+
+		/*
+		 * Save AXP22X DCDC1 / DCDC5 regulator names for later.
+		 */
+		if (i == axp_cfg->dcdc1_ix)
+			of_property_read_string(rdev->dev.of_node,
+						"regulator-name",
+						&dcdc1_name);
+		if (i == axp_cfg->dcdc5_ix)
+			of_property_read_string(rdev->dev.of_node,
+						"regulator-name",
+						&dcdc5_name);
+	}
+
+	if (axp_cfg->drivevbus) {
+		/* Change N_VBUSEN sense pin to DRIVEVBUS output pin */
+		regmap_update_bits(axp20x->regmap, AXP20X_OVER_TMP,
+				   AXP22X_MISC_N_VBUSEN_FUNC, 0);
+		rdev = devm_regulator_register(dev,
+					       &axp22x_drivevbus_regulator,
+					       &config);
+		if (IS_ERR(rdev)) {
+			dev_err(dev, "Failed to register drivevbus\n");
+			return PTR_ERR(rdev);
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(axp_regulator_create);
+
+MODULE_AUTHOR("Carlo Caione <carlo-KA+7E9HrN00dnm+yROfE0A@public.gmane.org>");
+MODULE_DESCRIPTION("Regulator Module for AXP PMIC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/axp-regulator.h b/drivers/regulator/axp-regulator.h
new file mode 100644
index 0000000..0adf1b0
--- /dev/null
+++ b/drivers/regulator/axp-regulator.h
@@ -0,0 +1,127 @@
+#ifndef __AXP_REGULATOR_H__
+#define __AXP_REGULATOR_H__
+/*
+ * Copyright (C) 2016 Jean-Francois Moine <moinejf-GANU6spQydw@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#define AXP20X_IO_ENABLED		0x03
+#define AXP20X_IO_DISABLED		0x07
+
+#define AXP22X_IO_ENABLED		0x03
+#define AXP22X_IO_DISABLED		0x04
+
+#define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg,	\
+		    _vmask, _ereg, _emask, _enable_val, _disable_val)		\
+	[_family##_##_id] = {							\
+		.name		= (_match),					\
+		.supply_name	= (_supply),					\
+		.of_match	= of_match_ptr(_match),				\
+		.regulators_node = of_match_ptr("regulators"),			\
+		.type		= REGULATOR_VOLTAGE,				\
+		.id		= _family##_##_id,				\
+		.n_voltages	= (((_max) - (_min)) / (_step) + 1),		\
+		.owner		= THIS_MODULE,					\
+		.min_uV		= (_min) * 1000,				\
+		.uV_step	= (_step) * 1000,				\
+		.vsel_reg	= (_vreg),					\
+		.vsel_mask	= (_vmask),					\
+		.enable_reg	= (_ereg),					\
+		.enable_mask	= (_emask),					\
+		.enable_val	= (_enable_val),				\
+		.disable_val	= (_disable_val),				\
+		.ops		= &axp_ops,					\
+	}
+
+#define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg,	\
+		 _vmask, _ereg, _emask) 					\
+	[_family##_##_id] = {							\
+		.name		= (_match),					\
+		.supply_name	= (_supply),					\
+		.of_match	= of_match_ptr(_match),				\
+		.regulators_node = of_match_ptr("regulators"),			\
+		.type		= REGULATOR_VOLTAGE,				\
+		.id		= _family##_##_id,				\
+		.n_voltages	= (((_max) - (_min)) / (_step) + 1),		\
+		.owner		= THIS_MODULE,					\
+		.min_uV		= (_min) * 1000,				\
+		.uV_step	= (_step) * 1000,				\
+		.vsel_reg	= (_vreg),					\
+		.vsel_mask	= (_vmask),					\
+		.enable_reg	= (_ereg),					\
+		.enable_mask	= (_emask),					\
+		.ops		= &axp_ops,					\
+	}
+
+#define AXP_DESC_SW(_family, _id, _match, _supply, _ereg, _emask)		\
+	[_family##_##_id] = {							\
+		.name		= (_match),					\
+		.supply_name	= (_supply),					\
+		.of_match	= of_match_ptr(_match),				\
+		.regulators_node = of_match_ptr("regulators"),			\
+		.type		= REGULATOR_VOLTAGE,				\
+		.id		= _family##_##_id,				\
+		.owner		= THIS_MODULE,					\
+		.enable_reg	= (_ereg),					\
+		.enable_mask	= (_emask),					\
+		.ops		= &axp_ops_sw,					\
+	}
+
+#define AXP_DESC_FIXED(_family, _id, _match, _supply, _volt)			\
+	[_family##_##_id] = {							\
+		.name		= (_match),					\
+		.supply_name	= (_supply),					\
+		.of_match	= of_match_ptr(_match),				\
+		.regulators_node = of_match_ptr("regulators"),			\
+		.type		= REGULATOR_VOLTAGE,				\
+		.id		= _family##_##_id,				\
+		.n_voltages	= 1,						\
+		.owner		= THIS_MODULE,					\
+		.min_uV		= (_volt) * 1000,				\
+		.ops		= &axp_ops_fixed				\
+	}
+
+#define AXP_DESC_RANGES(_family, _id, _match, _supply, _ranges, _n_voltages,	\
+			_vreg, _vmask, _ereg, _emask)				\
+	[_family##_##_id] = {							\
+		.name		= (_match),					\
+		.supply_name	= (_supply),					\
+		.of_match	= of_match_ptr(_match),				\
+		.regulators_node = of_match_ptr("regulators"),			\
+		.type		= REGULATOR_VOLTAGE,				\
+		.id		= _family##_##_id,				\
+		.n_voltages	= (_n_voltages),				\
+		.owner		= THIS_MODULE,					\
+		.vsel_reg	= (_vreg),					\
+		.vsel_mask	= (_vmask),					\
+		.enable_reg	= (_ereg),					\
+		.enable_mask	= (_emask),					\
+		.linear_ranges	= (_ranges),					\
+		.n_linear_ranges = ARRAY_SIZE(_ranges),				\
+		.ops		= &axp_ops_range,				\
+	}
+
+extern const struct regulator_ops axp_ops;
+extern const struct regulator_ops axp_ops_fixed;
+extern const struct regulator_ops axp_ops_range;
+extern const struct regulator_ops axp_ops_sw;
+
+struct axp_cfg {
+	const struct regulator_desc *regulators;
+	u8 nregulators;
+	s8 dcdc1_ix;
+	s8 dcdc5_ix;
+	s8 dc1sw_ix;
+	s8 dc5ldo_ix;
+	u32 skip_bitmap;
+	bool drivevbus;
+};
+
+int axp_regulator_create(struct device *dev,
+			 const struct axp_cfg *axp_cfg);
+
+#endif /* __AXP_REGULATOR_H__ */
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index 244ddc3..9dd9ca3 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -24,137 +24,7 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/of_regulator.h>
 
-#define AXP20X_IO_ENABLED		0x03
-#define AXP20X_IO_DISABLED		0x07
-
-#define AXP22X_IO_ENABLED		0x03
-#define AXP22X_IO_DISABLED		0x04
-
-#define AXP20X_WORKMODE_DCDC2_MASK	BIT(2)
-#define AXP20X_WORKMODE_DCDC3_MASK	BIT(1)
-#define AXP22X_WORKMODE_DCDCX_MASK(x)	BIT(x)
-
-#define AXP20X_FREQ_DCDC_MASK		0x0f
-
-#define AXP22X_MISC_N_VBUSEN_FUNC	BIT(4)
-
-#define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg,	\
-		    _vmask, _ereg, _emask, _enable_val, _disable_val)		\
-	[_family##_##_id] = {							\
-		.name		= (_match),					\
-		.supply_name	= (_supply),					\
-		.of_match	= of_match_ptr(_match),				\
-		.regulators_node = of_match_ptr("regulators"),			\
-		.type		= REGULATOR_VOLTAGE,				\
-		.id		= _family##_##_id,				\
-		.n_voltages	= (((_max) - (_min)) / (_step) + 1),		\
-		.owner		= THIS_MODULE,					\
-		.min_uV		= (_min) * 1000,				\
-		.uV_step	= (_step) * 1000,				\
-		.vsel_reg	= (_vreg),					\
-		.vsel_mask	= (_vmask),					\
-		.enable_reg	= (_ereg),					\
-		.enable_mask	= (_emask),					\
-		.enable_val	= (_enable_val),				\
-		.disable_val	= (_disable_val),				\
-		.ops		= &axp20x_ops,					\
-	}
-
-#define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg,	\
-		 _vmask, _ereg, _emask) 					\
-	[_family##_##_id] = {							\
-		.name		= (_match),					\
-		.supply_name	= (_supply),					\
-		.of_match	= of_match_ptr(_match),				\
-		.regulators_node = of_match_ptr("regulators"),			\
-		.type		= REGULATOR_VOLTAGE,				\
-		.id		= _family##_##_id,				\
-		.n_voltages	= (((_max) - (_min)) / (_step) + 1),		\
-		.owner		= THIS_MODULE,					\
-		.min_uV		= (_min) * 1000,				\
-		.uV_step	= (_step) * 1000,				\
-		.vsel_reg	= (_vreg),					\
-		.vsel_mask	= (_vmask),					\
-		.enable_reg	= (_ereg),					\
-		.enable_mask	= (_emask),					\
-		.ops		= &axp20x_ops,					\
-	}
-
-#define AXP_DESC_SW(_family, _id, _match, _supply, _ereg, _emask)		\
-	[_family##_##_id] = {							\
-		.name		= (_match),					\
-		.supply_name	= (_supply),					\
-		.of_match	= of_match_ptr(_match),				\
-		.regulators_node = of_match_ptr("regulators"),			\
-		.type		= REGULATOR_VOLTAGE,				\
-		.id		= _family##_##_id,				\
-		.owner		= THIS_MODULE,					\
-		.enable_reg	= (_ereg),					\
-		.enable_mask	= (_emask),					\
-		.ops		= &axp20x_ops_sw,				\
-	}
-
-#define AXP_DESC_FIXED(_family, _id, _match, _supply, _volt)			\
-	[_family##_##_id] = {							\
-		.name		= (_match),					\
-		.supply_name	= (_supply),					\
-		.of_match	= of_match_ptr(_match),				\
-		.regulators_node = of_match_ptr("regulators"),			\
-		.type		= REGULATOR_VOLTAGE,				\
-		.id		= _family##_##_id,				\
-		.n_voltages	= 1,						\
-		.owner		= THIS_MODULE,					\
-		.min_uV		= (_volt) * 1000,				\
-		.ops		= &axp20x_ops_fixed				\
-	}
-
-#define AXP_DESC_RANGES(_family, _id, _match, _supply, _ranges, _n_voltages,	\
-			_vreg, _vmask, _ereg, _emask)				\
-	[_family##_##_id] = {							\
-		.name		= (_match),					\
-		.supply_name	= (_supply),					\
-		.of_match	= of_match_ptr(_match),				\
-		.regulators_node = of_match_ptr("regulators"),			\
-		.type		= REGULATOR_VOLTAGE,				\
-		.id		= _family##_##_id,				\
-		.n_voltages	= (_n_voltages),				\
-		.owner		= THIS_MODULE,					\
-		.vsel_reg	= (_vreg),					\
-		.vsel_mask	= (_vmask),					\
-		.enable_reg	= (_ereg),					\
-		.enable_mask	= (_emask),					\
-		.linear_ranges	= (_ranges),					\
-		.n_linear_ranges = ARRAY_SIZE(_ranges),				\
-		.ops		= &axp20x_ops_range,				\
-	}
-
-static struct regulator_ops axp20x_ops_fixed = {
-	.list_voltage		= regulator_list_voltage_linear,
-};
-
-static struct regulator_ops axp20x_ops_range = {
-	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
-	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
-	.list_voltage		= regulator_list_voltage_linear_range,
-	.enable			= regulator_enable_regmap,
-	.disable		= regulator_disable_regmap,
-	.is_enabled		= regulator_is_enabled_regmap,
-};
-
-static struct regulator_ops axp20x_ops = {
-	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
-	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
-	.list_voltage		= regulator_list_voltage_linear,
-	.enable			= regulator_enable_regmap,
-	.disable		= regulator_disable_regmap,
-	.is_enabled		= regulator_is_enabled_regmap,
-};
-
-static struct regulator_ops axp20x_ops_sw = {
-	.enable			= regulator_enable_regmap,
-	.disable		= regulator_disable_regmap,
-	.is_enabled		= regulator_is_enabled_regmap,
-};
+#include "axp-regulator.h"
 
 static const struct regulator_linear_range axp20x_ldo4_ranges[] = {
 	REGULATOR_LINEAR_RANGE(1250000, 0x0, 0x0, 0),
@@ -232,18 +102,6 @@ static const struct regulator_desc axp22x_regulators[] = {
 	AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtc_ldo", "ips", 3000),
 };
 
-static const struct regulator_desc axp22x_drivevbus_regulator = {
-	.name		= "drivevbus",
-	.supply_name	= "drivevbus",
-	.of_match	= of_match_ptr("drivevbus"),
-	.regulators_node = of_match_ptr("regulators"),
-	.type		= REGULATOR_VOLTAGE,
-	.owner		= THIS_MODULE,
-	.enable_reg	= AXP20X_VBUS_IPSOUT_MGMT,
-	.enable_mask	= BIT(2),
-	.ops		= &axp20x_ops_sw,
-};
-
 static const struct regulator_linear_range axp806_dcdca_ranges[] = {
 	REGULATOR_LINEAR_RANGE(600000, 0x0, 0x32, 10000),
 	REGULATOR_LINEAR_RANGE(1120000, 0x33, 0x47, 20000),
@@ -347,135 +205,6 @@ static const struct regulator_desc axp809_regulators[] = {
 	AXP_DESC_SW(AXP809, SW, "sw", "swin", AXP22X_PWR_OUT_CTRL2, BIT(6)),
 };
 
-static int axp20x_set_dcdc_freq(struct device *dev, u32 dcdcfreq)
-{
-	struct axp20x_dev *axp20x = dev_get_drvdata(dev);
-	unsigned int reg = AXP20X_DCDC_FREQ;
-	u32 min, max, def, step;
-
-	switch (axp20x->variant) {
-	case AXP202_ID:
-	case AXP209_ID:
-		min = 750;
-		max = 1875;
-		def = 1500;
-		step = 75;
-		break;
-	case AXP806_ID:
-		/*
-		 * AXP806 DCDC work frequency setting has the same range and
-		 * step as AXP22X, but at a different register.
-		 * Fall through to the check below.
-		 * (See include/linux/mfd/axp20x.h)
-		 */
-		reg = AXP806_DCDC_FREQ_CTRL;
-	case AXP221_ID:
-	case AXP223_ID:
-	case AXP809_ID:
-		min = 1800;
-		max = 4050;
-		def = 3000;
-		step = 150;
-		break;
-	default:
-		dev_err(dev,
-			"Setting DCDC frequency for unsupported AXP variant\n");
-		return -EINVAL;
-	}
-
-	if (dcdcfreq == 0)
-		dcdcfreq = def;
-
-	if (dcdcfreq < min) {
-		dcdcfreq = min;
-		dev_warn(dev, "DCDC frequency too low. Set to %ukHz\n",
-			 min);
-	}
-
-	if (dcdcfreq > max) {
-		dcdcfreq = max;
-		dev_warn(dev, "DCDC frequency too high. Set to %ukHz\n",
-			 max);
-	}
-
-	dcdcfreq = (dcdcfreq - min) / step;
-
-	return regmap_update_bits(axp20x->regmap, reg,
-				  AXP20X_FREQ_DCDC_MASK, dcdcfreq);
-}
-
-static int axp20x_regulator_parse_dt(struct device *dev)
-{
-	struct device_node *np, *regulators;
-	int ret;
-	u32 dcdcfreq = 0;
-
-	np = of_node_get(dev->of_node);
-	if (!np)
-		return 0;
-
-	regulators = of_get_child_by_name(np, "regulators");
-	if (!regulators) {
-		dev_warn(dev, "regulators node not found\n");
-	} else {
-		of_property_read_u32(regulators, "x-powers,dcdc-freq", &dcdcfreq);
-		ret = axp20x_set_dcdc_freq(dev, dcdcfreq);
-		if (ret < 0) {
-			dev_err(dev, "Error setting dcdc frequency: %d\n", ret);
-			return ret;
-		}
-
-		of_node_put(regulators);
-	}
-
-	return 0;
-}
-
-static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 workmode)
-{
-	struct axp20x_dev *axp20x = rdev_get_drvdata(rdev);
-	unsigned int reg = AXP20X_DCDC_MODE;
-	unsigned int mask;
-
-	switch (axp20x->variant) {
-	case AXP202_ID:
-	case AXP209_ID:
-		if ((id != AXP20X_DCDC2) && (id != AXP20X_DCDC3))
-			return -EINVAL;
-
-		mask = AXP20X_WORKMODE_DCDC2_MASK;
-		if (id == AXP20X_DCDC3)
-			mask = AXP20X_WORKMODE_DCDC3_MASK;
-
-		workmode <<= ffs(mask) - 1;
-		break;
-
-	case AXP806_ID:
-		reg = AXP806_DCDC_MODE_CTRL2;
-		/*
-		 * AXP806 DCDC regulator IDs have the same range as AXP22X.
-		 * Fall through to the check below.
-		 * (See include/linux/mfd/axp20x.h)
-		 */
-	case AXP221_ID:
-	case AXP223_ID:
-	case AXP809_ID:
-		if (id < AXP22X_DCDC1 || id > AXP22X_DCDC5)
-			return -EINVAL;
-
-		mask = AXP22X_WORKMODE_DCDCX_MASK(id - AXP22X_DCDC1);
-		workmode <<= id - AXP22X_DCDC1;
-		break;
-
-	default:
-		/* should not happen */
-		WARN_ON(1);
-		return -EINVAL;
-	}
-
-	return regmap_update_bits(rdev->regmap, reg, mask, workmode);
-}
-
 /*
  * This function checks which regulators are part of poly-phase
  * output setups based on the registers settings.
@@ -500,60 +229,51 @@ static u32 axp20x_polyphase_slave(struct axp20x_dev *axp20x)
 static int axp20x_regulator_probe(struct platform_device *pdev)
 {
 	struct device *dev = pdev->dev.parent;
-	struct regulator_dev *rdev;
 	struct axp20x_dev *axp20x = dev_get_drvdata(dev);
-	const struct regulator_desc *regulators;
-	struct regulator_config config = {
-		.dev = dev,
-		.regmap = axp20x->regmap,
-		.driver_data = axp20x,
-	};
-	int ret, i, nregulators;
-	u32 workmode;
-	const char *dcdc1_name = axp22x_regulators[AXP22X_DCDC1].name;
-	const char *dcdc5_name = axp22x_regulators[AXP22X_DCDC5].name;
-	s8 dcdc1_ix = -1;
-	s8 dcdc5_ix = -1;
-	s8 dc1sw_ix = -1;
-	s8 dc5ldo_ix = -1;
-	bool drivevbus = false;
-	u32 skip_bitmap = 0;
+	struct axp_cfg axp_cfg;
+
+	axp_cfg.dcdc1_ix = -1;
+	axp_cfg.dcdc5_ix = -1;
+	axp_cfg.dc1sw_ix = -1;
+	axp_cfg.dc5ldo_ix = -1;
+	axp_cfg.drivevbus = false;
+	axp_cfg.skip_bitmap = 0;
 
 	switch (axp20x->variant) {
 	case AXP202_ID:
 	case AXP209_ID:
-		regulators = axp20x_regulators;
-		nregulators = AXP20X_REG_ID_MAX;
+		axp_cfg.regulators = axp20x_regulators;
+		axp_cfg.nregulators = AXP20X_REG_ID_MAX;
 		break;
 	case AXP221_ID:
 	case AXP223_ID:
-		regulators = axp22x_regulators;
-		nregulators = AXP22X_REG_ID_MAX;
-		dcdc1_ix = AXP22X_DCDC1;
-		dcdc5_ix = AXP22X_DCDC5;
-		dc1sw_ix = AXP22X_DC1SW;
-		dc5ldo_ix = AXP22X_DC5LDO;
-		drivevbus = of_property_read_bool(dev->of_node,
+		axp_cfg.regulators = axp22x_regulators;
+		axp_cfg.nregulators = AXP22X_REG_ID_MAX;
+		axp_cfg.dcdc1_ix = AXP22X_DCDC1;
+		axp_cfg.dcdc5_ix = AXP22X_DCDC5;
+		axp_cfg.dc1sw_ix = AXP22X_DC1SW;
+		axp_cfg.dc5ldo_ix = AXP22X_DC5LDO;
+		axp_cfg.drivevbus = of_property_read_bool(dev->of_node,
 						  "x-powers,drive-vbus-en");
 		break;
 	case AXP806_ID:
-		regulators = axp806_regulators;
-		nregulators = AXP806_REG_ID_MAX;
+		axp_cfg.regulators = axp806_regulators;
+		axp_cfg.nregulators = AXP806_REG_ID_MAX;
 
 		/*
 		 * The regulators which are slave in a poly-phase setup
 		 * are skipped, as their controls are bound to the master
 		 * regulator and won't work.
 		 */
-		skip_bitmap |= axp20x_polyphase_slave(axp20x);
+		axp_cfg.skip_bitmap |= axp20x_polyphase_slave(axp20x);
 		break;
 	case AXP809_ID:
-		regulators = axp809_regulators;
-		nregulators = AXP809_REG_ID_MAX;
-		dcdc1_ix = AXP809_DCDC1;
-		dcdc5_ix = AXP809_DCDC5;
-		dc1sw_ix = AXP809_DC1SW;
-		dc5ldo_ix = AXP809_DC5LDO;
+		axp_cfg.regulators = axp809_regulators;
+		axp_cfg.nregulators = AXP809_REG_ID_MAX;
+		axp_cfg.dcdc1_ix = AXP809_DCDC1;
+		axp_cfg.dcdc5_ix = AXP809_DCDC5;
+		axp_cfg.dc1sw_ix = AXP809_DC1SW;
+		axp_cfg.dc5ldo_ix = AXP809_DC5LDO;
 		break;
 	default:
 		dev_err(dev, "Unsupported AXP variant: %ld\n",
@@ -561,86 +281,7 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	/* This only sets the dcdc freq. Ignore any errors */
-	axp20x_regulator_parse_dt(dev);
-
-	for (i = 0; i < nregulators; i++) {
-		const struct regulator_desc *desc = &regulators[i];
-		struct regulator_desc *new_desc;
-
-		if (skip_bitmap & (1 << i))
-			continue;
-
-		/*
-		 * Regulators DC1SW and DC5LDO are connected internally,
-		 * so we have to handle their supply names separately.
-		 *
-		 * We always register the regulators in proper sequence,
-		 * so the supply names are correctly read. See the last
-		 * part of this loop to see where we save the DT defined
-		 * name.
-		 */
-		if (i == dc1sw_ix && dcdc1_name) {
-			new_desc = devm_kzalloc(dev, sizeof(*desc),
-						GFP_KERNEL);
-			*new_desc = regulators[i];
-			new_desc->supply_name = dcdc1_name;
-			desc = new_desc;
-		}
-
-		if (i == dc5ldo_ix && dcdc5_name) {
-			new_desc = devm_kzalloc(dev, sizeof(*desc),
-						GFP_KERNEL);
-			*new_desc = regulators[i];
-			new_desc->supply_name = dcdc5_name;
-			desc = new_desc;
-		}
-
-		rdev = devm_regulator_register(dev, desc, &config);
-		if (IS_ERR(rdev)) {
-			dev_err(dev, "Failed to register %s\n",
-				regulators[i].name);
-
-			return PTR_ERR(rdev);
-		}
-
-		ret = of_property_read_u32(rdev->dev.of_node,
-					   "x-powers,dcdc-workmode",
-					   &workmode);
-		if (!ret) {
-			if (axp20x_set_dcdc_workmode(rdev, i, workmode))
-				dev_err(dev, "Failed to set workmode on %s\n",
-					rdev->desc->name);
-		}
-
-		/*
-		 * Save AXP22X DCDC1 / DCDC5 regulator names for later.
-		 */
-		if (i == dcdc1_ix)
-			of_property_read_string(rdev->dev.of_node,
-						"regulator-name",
-						&dcdc1_name);
-
-		if (i == dcdc5_ix)
-			of_property_read_string(rdev->dev.of_node,
-						"regulator-name",
-						&dcdc5_name);
-	}
-
-	if (drivevbus) {
-		/* Change N_VBUSEN sense pin to DRIVEVBUS output pin */
-		regmap_update_bits(axp20x->regmap, AXP20X_OVER_TMP,
-				   AXP22X_MISC_N_VBUSEN_FUNC, 0);
-		rdev = devm_regulator_register(dev,
-					       &axp22x_drivevbus_regulator,
-					       &config);
-		if (IS_ERR(rdev)) {
-			dev_err(dev, "Failed to register drivevbus\n");
-			return PTR_ERR(rdev);
-		}
-	}
-
-	return 0;
+	return axp_regulator_create(dev, &axp_cfg);
 }
 
 static struct platform_driver axp20x_regulator_driver = {
-- 
2.10.0

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 1/4] regulator: axp20x: move device independant parts to new files
@ 2016-09-22 17:06   ` Jean-Francois Moine
  0 siblings, 0 replies; 27+ messages in thread
From: Jean-Francois Moine @ 2016-09-22 17:06 UTC (permalink / raw)
  To: linux-arm-kernel

The axp20x driver contains device specific and device independant parts.
This patch moves the independant parts to new .c/.h files.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
 drivers/regulator/Makefile           |   2 +-
 drivers/regulator/axp-regulator.c    | 308 ++++++++++++++++++++++++++
 drivers/regulator/axp-regulator.h    | 127 +++++++++++
 drivers/regulator/axp20x-regulator.c | 415 +++--------------------------------
 4 files changed, 464 insertions(+), 388 deletions(-)
 create mode 100644 drivers/regulator/axp-regulator.c
 create mode 100644 drivers/regulator/axp-regulator.h

diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 2142a5d..225a026 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -21,7 +21,7 @@ obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
 obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
 obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
 obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
-obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o
+obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o axp-regulator.o
 obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o
 obj-$(CONFIG_REGULATOR_DA903X)	+= da903x.o
 obj-$(CONFIG_REGULATOR_DA9052)	+= da9052-regulator.o
diff --git a/drivers/regulator/axp-regulator.c b/drivers/regulator/axp-regulator.c
new file mode 100644
index 0000000..0d7adb6
--- /dev/null
+++ b/drivers/regulator/axp-regulator.c
@@ -0,0 +1,308 @@
+/*
+ * AXP regulators driver
+ *
+ * Copyright (C) 2016 Jean-Francois Moine <moinejf@free.fr>
+ * Copyright (C) 2013 Carlo Caione <carlo@caione.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/mfd/axp20x.h>
+#include <linux/sunxi-rsb.h>
+
+#include "axp-regulator.h"
+
+#define AXP20X_WORKMODE_DCDC2_MASK	BIT(2)
+#define AXP20X_WORKMODE_DCDC3_MASK	BIT(1)
+#define AXP22X_WORKMODE_DCDCX_MASK(x)	BIT(x)
+
+#define AXP20X_FREQ_DCDC_MASK	0x0f
+
+#define AXP22X_MISC_N_VBUSEN_FUNC	BIT(4)
+
+const struct regulator_ops axp_ops_fixed = {
+	.list_voltage		= regulator_list_voltage_linear,
+};
+EXPORT_SYMBOL_GPL(axp_ops_fixed);
+
+const struct regulator_ops axp_ops_range = {
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.list_voltage		= regulator_list_voltage_linear_range,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.is_enabled		= regulator_is_enabled_regmap,
+};
+EXPORT_SYMBOL_GPL(axp_ops_range);
+
+const struct regulator_ops axp_ops = {
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.list_voltage		= regulator_list_voltage_linear,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.is_enabled		= regulator_is_enabled_regmap,
+};
+EXPORT_SYMBOL_GPL(axp_ops);
+
+const struct regulator_ops axp_ops_sw = {
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.is_enabled		= regulator_is_enabled_regmap,
+};
+EXPORT_SYMBOL_GPL(axp_ops_sw);
+
+static const struct regulator_desc axp22x_drivevbus_regulator = {
+	.name		= "drivevbus",
+	.supply_name	= "drivevbus",
+	.of_match	= of_match_ptr("drivevbus"),
+	.regulators_node = of_match_ptr("regulators"),
+	.type		= REGULATOR_VOLTAGE,
+	.owner		= THIS_MODULE,
+	.enable_reg	= AXP20X_VBUS_IPSOUT_MGMT,
+	.enable_mask	= BIT(2),
+	.ops		= &axp_ops_sw,
+};
+
+static int axp_set_dcdc_freq(struct device *dev,
+					u32 dcdcfreq)
+{
+	struct axp20x_dev *axp20x = dev_get_drvdata(dev);
+	unsigned int reg = AXP20X_DCDC_FREQ;
+	u32 min, max, def, step;
+
+	switch (axp20x->variant) {
+	case AXP202_ID:
+	case AXP209_ID:
+		min = 750;
+		max = 1875;
+		def = 1500;
+		step = 75;
+		break;
+	case AXP806_ID:
+		/*
+		 * AXP806 DCDC work frequency setting has the same range and
+		 * step as AXP22X, but at a different register.
+		 * Fall through to the check below.
+		 * (See include/linux/mfd/axp20x.h)
+		 */
+		reg = AXP806_DCDC_FREQ_CTRL;
+	case AXP221_ID:
+	case AXP223_ID:
+	case AXP809_ID:
+		min = 1800;
+		max = 4050;
+		def = 3000;
+		step = 150;
+		break;
+	default:
+		dev_err(dev,
+			"Setting DCDC frequency for unsupported AXP variant\n");
+		return -EINVAL;
+	}
+
+	if (dcdcfreq == 0)
+		dcdcfreq = def;
+
+	if (dcdcfreq < min) {
+		dcdcfreq = min;
+		dev_warn(dev, "DCDC frequency too low. Set to %ukHz\n",
+			 min);
+	}
+
+	if (dcdcfreq > max) {
+		dcdcfreq = max;
+		dev_warn(dev, "DCDC frequency too high. Set to %ukHz\n",
+			 max);
+	}
+
+	dcdcfreq = (dcdcfreq - min) / step;
+
+	return regmap_update_bits(axp20x->regmap, reg,
+				  AXP20X_FREQ_DCDC_MASK, dcdcfreq);
+}
+
+static int axp_regulator_parse_dt(struct device *dev)
+{
+	struct device_node *np, *regulators;
+	int ret;
+	u32 dcdcfreq = 0;
+
+	np = of_node_get(dev->of_node);
+	if (!np)
+		return 0;
+
+	regulators = of_get_child_by_name(np, "regulators");
+	if (!regulators) {
+		dev_warn(dev, "regulators node not found\n");
+	} else {
+		of_property_read_u32(regulators, "x-powers,dcdc-freq", &dcdcfreq);
+		ret = axp_set_dcdc_freq(dev, dcdcfreq);
+		if (ret < 0) {
+			dev_err(dev, "Error setting dcdc frequency: %d\n", ret);
+			return ret;
+		}
+
+		of_node_put(regulators);
+	}
+
+	return 0;
+}
+
+static int axp_set_dcdc_workmode(struct regulator_dev *rdev,
+				int id, u32 workmode)
+{
+	struct axp20x_dev *axp20x = rdev_get_drvdata(rdev);
+	unsigned int reg = AXP20X_DCDC_MODE;
+	unsigned int mask;
+
+	switch (axp20x->variant) {
+	case AXP202_ID:
+	case AXP209_ID:
+		if ((id != AXP20X_DCDC2) && (id != AXP20X_DCDC3))
+			return -EINVAL;
+
+		mask = AXP20X_WORKMODE_DCDC2_MASK;
+		if (id == AXP20X_DCDC3)
+			mask = AXP20X_WORKMODE_DCDC3_MASK;
+
+		workmode <<= ffs(mask) - 1;
+		break;
+
+	case AXP806_ID:
+		reg = AXP806_DCDC_MODE_CTRL2;
+		/*
+		 * AXP806 DCDC regulator IDs have the same range as AXP22X.
+		 * Fall through to the check below.
+		 * (See include/linux/mfd/axp20x.h)
+		 */
+	case AXP221_ID:
+	case AXP223_ID:
+	case AXP809_ID:
+		if (id < AXP22X_DCDC1 || id > AXP22X_DCDC5)
+			return -EINVAL;
+
+		mask = AXP22X_WORKMODE_DCDCX_MASK(id - AXP22X_DCDC1);
+		workmode <<= id - AXP22X_DCDC1;
+		break;
+
+	default:
+		/* should not happen */
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	return regmap_update_bits(rdev->regmap, reg, mask, workmode);
+}
+
+/* create the regulators */
+int axp_regulator_create(struct device *dev,
+			 const struct axp_cfg *axp_cfg)
+{
+	struct regulator_dev *rdev;
+	struct axp20x_dev *axp20x = dev_get_drvdata(dev);
+	struct regulator_config config = {
+		.dev = dev,
+		.regmap = axp20x->regmap,
+		.driver_data = axp20x,
+	};
+	int ret, i;
+	u32 workmode;
+	const char *dcdc1_name = NULL;
+	const char *dcdc5_name = NULL;
+
+	/* This only sets the dcdc freq. Ignore any errors */
+	axp_regulator_parse_dt(dev);
+
+	for (i = 0; i < axp_cfg->nregulators; i++) {
+		const struct regulator_desc *desc = &axp_cfg->regulators[i];
+		struct regulator_desc *new_desc;
+
+		if (axp_cfg->skip_bitmap & (1 << i))
+			continue;
+
+		/*
+		 * Regulators DC1SW and DC5LDO are connected internally,
+		 * so we have to handle their supply names separately.
+		 *
+		 * We always register the regulators in proper sequence,
+		 * so the supply names are correctly read. See the last
+		 * part of this loop to see where we save the DT defined
+		 * name.
+		 */
+		if (i == axp_cfg->dc1sw_ix && dcdc1_name) {
+			new_desc = devm_kzalloc(dev, sizeof(*desc),
+						GFP_KERNEL);
+			*new_desc = *desc;
+			new_desc->supply_name = dcdc1_name;
+			desc = new_desc;
+		}
+
+		if (i == axp_cfg->dc5ldo_ix && dcdc5_name) {
+			new_desc = devm_kzalloc(dev, sizeof(*desc),
+						GFP_KERNEL);
+			*new_desc = *desc;
+			new_desc->supply_name = dcdc5_name;
+			desc = new_desc;
+		}
+
+		rdev = devm_regulator_register(dev, desc, &config);
+		if (IS_ERR(rdev)) {
+			dev_err(dev, "Failed to register %s\n",
+				axp_cfg->regulators[i].name);
+
+			return PTR_ERR(rdev);
+		}
+
+		ret = of_property_read_u32(rdev->dev.of_node,
+					   "x-powers,dcdc-workmode",
+					   &workmode);
+		if (!ret) {
+			if (axp_set_dcdc_workmode(rdev, i, workmode))
+				dev_err(dev, "Failed to set workmode on %s\n",
+					rdev->desc->name);
+		}
+
+		/*
+		 * Save AXP22X DCDC1 / DCDC5 regulator names for later.
+		 */
+		if (i == axp_cfg->dcdc1_ix)
+			of_property_read_string(rdev->dev.of_node,
+						"regulator-name",
+						&dcdc1_name);
+		if (i == axp_cfg->dcdc5_ix)
+			of_property_read_string(rdev->dev.of_node,
+						"regulator-name",
+						&dcdc5_name);
+	}
+
+	if (axp_cfg->drivevbus) {
+		/* Change N_VBUSEN sense pin to DRIVEVBUS output pin */
+		regmap_update_bits(axp20x->regmap, AXP20X_OVER_TMP,
+				   AXP22X_MISC_N_VBUSEN_FUNC, 0);
+		rdev = devm_regulator_register(dev,
+					       &axp22x_drivevbus_regulator,
+					       &config);
+		if (IS_ERR(rdev)) {
+			dev_err(dev, "Failed to register drivevbus\n");
+			return PTR_ERR(rdev);
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(axp_regulator_create);
+
+MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
+MODULE_DESCRIPTION("Regulator Module for AXP PMIC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/axp-regulator.h b/drivers/regulator/axp-regulator.h
new file mode 100644
index 0000000..0adf1b0
--- /dev/null
+++ b/drivers/regulator/axp-regulator.h
@@ -0,0 +1,127 @@
+#ifndef __AXP_REGULATOR_H__
+#define __AXP_REGULATOR_H__
+/*
+ * Copyright (C) 2016 Jean-Francois Moine <moinejf@free.fr>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#define AXP20X_IO_ENABLED		0x03
+#define AXP20X_IO_DISABLED		0x07
+
+#define AXP22X_IO_ENABLED		0x03
+#define AXP22X_IO_DISABLED		0x04
+
+#define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg,	\
+		    _vmask, _ereg, _emask, _enable_val, _disable_val)		\
+	[_family##_##_id] = {							\
+		.name		= (_match),					\
+		.supply_name	= (_supply),					\
+		.of_match	= of_match_ptr(_match),				\
+		.regulators_node = of_match_ptr("regulators"),			\
+		.type		= REGULATOR_VOLTAGE,				\
+		.id		= _family##_##_id,				\
+		.n_voltages	= (((_max) - (_min)) / (_step) + 1),		\
+		.owner		= THIS_MODULE,					\
+		.min_uV		= (_min) * 1000,				\
+		.uV_step	= (_step) * 1000,				\
+		.vsel_reg	= (_vreg),					\
+		.vsel_mask	= (_vmask),					\
+		.enable_reg	= (_ereg),					\
+		.enable_mask	= (_emask),					\
+		.enable_val	= (_enable_val),				\
+		.disable_val	= (_disable_val),				\
+		.ops		= &axp_ops,					\
+	}
+
+#define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg,	\
+		 _vmask, _ereg, _emask) 					\
+	[_family##_##_id] = {							\
+		.name		= (_match),					\
+		.supply_name	= (_supply),					\
+		.of_match	= of_match_ptr(_match),				\
+		.regulators_node = of_match_ptr("regulators"),			\
+		.type		= REGULATOR_VOLTAGE,				\
+		.id		= _family##_##_id,				\
+		.n_voltages	= (((_max) - (_min)) / (_step) + 1),		\
+		.owner		= THIS_MODULE,					\
+		.min_uV		= (_min) * 1000,				\
+		.uV_step	= (_step) * 1000,				\
+		.vsel_reg	= (_vreg),					\
+		.vsel_mask	= (_vmask),					\
+		.enable_reg	= (_ereg),					\
+		.enable_mask	= (_emask),					\
+		.ops		= &axp_ops,					\
+	}
+
+#define AXP_DESC_SW(_family, _id, _match, _supply, _ereg, _emask)		\
+	[_family##_##_id] = {							\
+		.name		= (_match),					\
+		.supply_name	= (_supply),					\
+		.of_match	= of_match_ptr(_match),				\
+		.regulators_node = of_match_ptr("regulators"),			\
+		.type		= REGULATOR_VOLTAGE,				\
+		.id		= _family##_##_id,				\
+		.owner		= THIS_MODULE,					\
+		.enable_reg	= (_ereg),					\
+		.enable_mask	= (_emask),					\
+		.ops		= &axp_ops_sw,					\
+	}
+
+#define AXP_DESC_FIXED(_family, _id, _match, _supply, _volt)			\
+	[_family##_##_id] = {							\
+		.name		= (_match),					\
+		.supply_name	= (_supply),					\
+		.of_match	= of_match_ptr(_match),				\
+		.regulators_node = of_match_ptr("regulators"),			\
+		.type		= REGULATOR_VOLTAGE,				\
+		.id		= _family##_##_id,				\
+		.n_voltages	= 1,						\
+		.owner		= THIS_MODULE,					\
+		.min_uV		= (_volt) * 1000,				\
+		.ops		= &axp_ops_fixed				\
+	}
+
+#define AXP_DESC_RANGES(_family, _id, _match, _supply, _ranges, _n_voltages,	\
+			_vreg, _vmask, _ereg, _emask)				\
+	[_family##_##_id] = {							\
+		.name		= (_match),					\
+		.supply_name	= (_supply),					\
+		.of_match	= of_match_ptr(_match),				\
+		.regulators_node = of_match_ptr("regulators"),			\
+		.type		= REGULATOR_VOLTAGE,				\
+		.id		= _family##_##_id,				\
+		.n_voltages	= (_n_voltages),				\
+		.owner		= THIS_MODULE,					\
+		.vsel_reg	= (_vreg),					\
+		.vsel_mask	= (_vmask),					\
+		.enable_reg	= (_ereg),					\
+		.enable_mask	= (_emask),					\
+		.linear_ranges	= (_ranges),					\
+		.n_linear_ranges = ARRAY_SIZE(_ranges),				\
+		.ops		= &axp_ops_range,				\
+	}
+
+extern const struct regulator_ops axp_ops;
+extern const struct regulator_ops axp_ops_fixed;
+extern const struct regulator_ops axp_ops_range;
+extern const struct regulator_ops axp_ops_sw;
+
+struct axp_cfg {
+	const struct regulator_desc *regulators;
+	u8 nregulators;
+	s8 dcdc1_ix;
+	s8 dcdc5_ix;
+	s8 dc1sw_ix;
+	s8 dc5ldo_ix;
+	u32 skip_bitmap;
+	bool drivevbus;
+};
+
+int axp_regulator_create(struct device *dev,
+			 const struct axp_cfg *axp_cfg);
+
+#endif /* __AXP_REGULATOR_H__ */
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index 244ddc3..9dd9ca3 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -24,137 +24,7 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/of_regulator.h>
 
-#define AXP20X_IO_ENABLED		0x03
-#define AXP20X_IO_DISABLED		0x07
-
-#define AXP22X_IO_ENABLED		0x03
-#define AXP22X_IO_DISABLED		0x04
-
-#define AXP20X_WORKMODE_DCDC2_MASK	BIT(2)
-#define AXP20X_WORKMODE_DCDC3_MASK	BIT(1)
-#define AXP22X_WORKMODE_DCDCX_MASK(x)	BIT(x)
-
-#define AXP20X_FREQ_DCDC_MASK		0x0f
-
-#define AXP22X_MISC_N_VBUSEN_FUNC	BIT(4)
-
-#define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg,	\
-		    _vmask, _ereg, _emask, _enable_val, _disable_val)		\
-	[_family##_##_id] = {							\
-		.name		= (_match),					\
-		.supply_name	= (_supply),					\
-		.of_match	= of_match_ptr(_match),				\
-		.regulators_node = of_match_ptr("regulators"),			\
-		.type		= REGULATOR_VOLTAGE,				\
-		.id		= _family##_##_id,				\
-		.n_voltages	= (((_max) - (_min)) / (_step) + 1),		\
-		.owner		= THIS_MODULE,					\
-		.min_uV		= (_min) * 1000,				\
-		.uV_step	= (_step) * 1000,				\
-		.vsel_reg	= (_vreg),					\
-		.vsel_mask	= (_vmask),					\
-		.enable_reg	= (_ereg),					\
-		.enable_mask	= (_emask),					\
-		.enable_val	= (_enable_val),				\
-		.disable_val	= (_disable_val),				\
-		.ops		= &axp20x_ops,					\
-	}
-
-#define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg,	\
-		 _vmask, _ereg, _emask) 					\
-	[_family##_##_id] = {							\
-		.name		= (_match),					\
-		.supply_name	= (_supply),					\
-		.of_match	= of_match_ptr(_match),				\
-		.regulators_node = of_match_ptr("regulators"),			\
-		.type		= REGULATOR_VOLTAGE,				\
-		.id		= _family##_##_id,				\
-		.n_voltages	= (((_max) - (_min)) / (_step) + 1),		\
-		.owner		= THIS_MODULE,					\
-		.min_uV		= (_min) * 1000,				\
-		.uV_step	= (_step) * 1000,				\
-		.vsel_reg	= (_vreg),					\
-		.vsel_mask	= (_vmask),					\
-		.enable_reg	= (_ereg),					\
-		.enable_mask	= (_emask),					\
-		.ops		= &axp20x_ops,					\
-	}
-
-#define AXP_DESC_SW(_family, _id, _match, _supply, _ereg, _emask)		\
-	[_family##_##_id] = {							\
-		.name		= (_match),					\
-		.supply_name	= (_supply),					\
-		.of_match	= of_match_ptr(_match),				\
-		.regulators_node = of_match_ptr("regulators"),			\
-		.type		= REGULATOR_VOLTAGE,				\
-		.id		= _family##_##_id,				\
-		.owner		= THIS_MODULE,					\
-		.enable_reg	= (_ereg),					\
-		.enable_mask	= (_emask),					\
-		.ops		= &axp20x_ops_sw,				\
-	}
-
-#define AXP_DESC_FIXED(_family, _id, _match, _supply, _volt)			\
-	[_family##_##_id] = {							\
-		.name		= (_match),					\
-		.supply_name	= (_supply),					\
-		.of_match	= of_match_ptr(_match),				\
-		.regulators_node = of_match_ptr("regulators"),			\
-		.type		= REGULATOR_VOLTAGE,				\
-		.id		= _family##_##_id,				\
-		.n_voltages	= 1,						\
-		.owner		= THIS_MODULE,					\
-		.min_uV		= (_volt) * 1000,				\
-		.ops		= &axp20x_ops_fixed				\
-	}
-
-#define AXP_DESC_RANGES(_family, _id, _match, _supply, _ranges, _n_voltages,	\
-			_vreg, _vmask, _ereg, _emask)				\
-	[_family##_##_id] = {							\
-		.name		= (_match),					\
-		.supply_name	= (_supply),					\
-		.of_match	= of_match_ptr(_match),				\
-		.regulators_node = of_match_ptr("regulators"),			\
-		.type		= REGULATOR_VOLTAGE,				\
-		.id		= _family##_##_id,				\
-		.n_voltages	= (_n_voltages),				\
-		.owner		= THIS_MODULE,					\
-		.vsel_reg	= (_vreg),					\
-		.vsel_mask	= (_vmask),					\
-		.enable_reg	= (_ereg),					\
-		.enable_mask	= (_emask),					\
-		.linear_ranges	= (_ranges),					\
-		.n_linear_ranges = ARRAY_SIZE(_ranges),				\
-		.ops		= &axp20x_ops_range,				\
-	}
-
-static struct regulator_ops axp20x_ops_fixed = {
-	.list_voltage		= regulator_list_voltage_linear,
-};
-
-static struct regulator_ops axp20x_ops_range = {
-	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
-	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
-	.list_voltage		= regulator_list_voltage_linear_range,
-	.enable			= regulator_enable_regmap,
-	.disable		= regulator_disable_regmap,
-	.is_enabled		= regulator_is_enabled_regmap,
-};
-
-static struct regulator_ops axp20x_ops = {
-	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
-	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
-	.list_voltage		= regulator_list_voltage_linear,
-	.enable			= regulator_enable_regmap,
-	.disable		= regulator_disable_regmap,
-	.is_enabled		= regulator_is_enabled_regmap,
-};
-
-static struct regulator_ops axp20x_ops_sw = {
-	.enable			= regulator_enable_regmap,
-	.disable		= regulator_disable_regmap,
-	.is_enabled		= regulator_is_enabled_regmap,
-};
+#include "axp-regulator.h"
 
 static const struct regulator_linear_range axp20x_ldo4_ranges[] = {
 	REGULATOR_LINEAR_RANGE(1250000, 0x0, 0x0, 0),
@@ -232,18 +102,6 @@ static const struct regulator_desc axp22x_regulators[] = {
 	AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtc_ldo", "ips", 3000),
 };
 
-static const struct regulator_desc axp22x_drivevbus_regulator = {
-	.name		= "drivevbus",
-	.supply_name	= "drivevbus",
-	.of_match	= of_match_ptr("drivevbus"),
-	.regulators_node = of_match_ptr("regulators"),
-	.type		= REGULATOR_VOLTAGE,
-	.owner		= THIS_MODULE,
-	.enable_reg	= AXP20X_VBUS_IPSOUT_MGMT,
-	.enable_mask	= BIT(2),
-	.ops		= &axp20x_ops_sw,
-};
-
 static const struct regulator_linear_range axp806_dcdca_ranges[] = {
 	REGULATOR_LINEAR_RANGE(600000, 0x0, 0x32, 10000),
 	REGULATOR_LINEAR_RANGE(1120000, 0x33, 0x47, 20000),
@@ -347,135 +205,6 @@ static const struct regulator_desc axp809_regulators[] = {
 	AXP_DESC_SW(AXP809, SW, "sw", "swin", AXP22X_PWR_OUT_CTRL2, BIT(6)),
 };
 
-static int axp20x_set_dcdc_freq(struct device *dev, u32 dcdcfreq)
-{
-	struct axp20x_dev *axp20x = dev_get_drvdata(dev);
-	unsigned int reg = AXP20X_DCDC_FREQ;
-	u32 min, max, def, step;
-
-	switch (axp20x->variant) {
-	case AXP202_ID:
-	case AXP209_ID:
-		min = 750;
-		max = 1875;
-		def = 1500;
-		step = 75;
-		break;
-	case AXP806_ID:
-		/*
-		 * AXP806 DCDC work frequency setting has the same range and
-		 * step as AXP22X, but at a different register.
-		 * Fall through to the check below.
-		 * (See include/linux/mfd/axp20x.h)
-		 */
-		reg = AXP806_DCDC_FREQ_CTRL;
-	case AXP221_ID:
-	case AXP223_ID:
-	case AXP809_ID:
-		min = 1800;
-		max = 4050;
-		def = 3000;
-		step = 150;
-		break;
-	default:
-		dev_err(dev,
-			"Setting DCDC frequency for unsupported AXP variant\n");
-		return -EINVAL;
-	}
-
-	if (dcdcfreq == 0)
-		dcdcfreq = def;
-
-	if (dcdcfreq < min) {
-		dcdcfreq = min;
-		dev_warn(dev, "DCDC frequency too low. Set to %ukHz\n",
-			 min);
-	}
-
-	if (dcdcfreq > max) {
-		dcdcfreq = max;
-		dev_warn(dev, "DCDC frequency too high. Set to %ukHz\n",
-			 max);
-	}
-
-	dcdcfreq = (dcdcfreq - min) / step;
-
-	return regmap_update_bits(axp20x->regmap, reg,
-				  AXP20X_FREQ_DCDC_MASK, dcdcfreq);
-}
-
-static int axp20x_regulator_parse_dt(struct device *dev)
-{
-	struct device_node *np, *regulators;
-	int ret;
-	u32 dcdcfreq = 0;
-
-	np = of_node_get(dev->of_node);
-	if (!np)
-		return 0;
-
-	regulators = of_get_child_by_name(np, "regulators");
-	if (!regulators) {
-		dev_warn(dev, "regulators node not found\n");
-	} else {
-		of_property_read_u32(regulators, "x-powers,dcdc-freq", &dcdcfreq);
-		ret = axp20x_set_dcdc_freq(dev, dcdcfreq);
-		if (ret < 0) {
-			dev_err(dev, "Error setting dcdc frequency: %d\n", ret);
-			return ret;
-		}
-
-		of_node_put(regulators);
-	}
-
-	return 0;
-}
-
-static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 workmode)
-{
-	struct axp20x_dev *axp20x = rdev_get_drvdata(rdev);
-	unsigned int reg = AXP20X_DCDC_MODE;
-	unsigned int mask;
-
-	switch (axp20x->variant) {
-	case AXP202_ID:
-	case AXP209_ID:
-		if ((id != AXP20X_DCDC2) && (id != AXP20X_DCDC3))
-			return -EINVAL;
-
-		mask = AXP20X_WORKMODE_DCDC2_MASK;
-		if (id == AXP20X_DCDC3)
-			mask = AXP20X_WORKMODE_DCDC3_MASK;
-
-		workmode <<= ffs(mask) - 1;
-		break;
-
-	case AXP806_ID:
-		reg = AXP806_DCDC_MODE_CTRL2;
-		/*
-		 * AXP806 DCDC regulator IDs have the same range as AXP22X.
-		 * Fall through to the check below.
-		 * (See include/linux/mfd/axp20x.h)
-		 */
-	case AXP221_ID:
-	case AXP223_ID:
-	case AXP809_ID:
-		if (id < AXP22X_DCDC1 || id > AXP22X_DCDC5)
-			return -EINVAL;
-
-		mask = AXP22X_WORKMODE_DCDCX_MASK(id - AXP22X_DCDC1);
-		workmode <<= id - AXP22X_DCDC1;
-		break;
-
-	default:
-		/* should not happen */
-		WARN_ON(1);
-		return -EINVAL;
-	}
-
-	return regmap_update_bits(rdev->regmap, reg, mask, workmode);
-}
-
 /*
  * This function checks which regulators are part of poly-phase
  * output setups based on the registers settings.
@@ -500,60 +229,51 @@ static u32 axp20x_polyphase_slave(struct axp20x_dev *axp20x)
 static int axp20x_regulator_probe(struct platform_device *pdev)
 {
 	struct device *dev = pdev->dev.parent;
-	struct regulator_dev *rdev;
 	struct axp20x_dev *axp20x = dev_get_drvdata(dev);
-	const struct regulator_desc *regulators;
-	struct regulator_config config = {
-		.dev = dev,
-		.regmap = axp20x->regmap,
-		.driver_data = axp20x,
-	};
-	int ret, i, nregulators;
-	u32 workmode;
-	const char *dcdc1_name = axp22x_regulators[AXP22X_DCDC1].name;
-	const char *dcdc5_name = axp22x_regulators[AXP22X_DCDC5].name;
-	s8 dcdc1_ix = -1;
-	s8 dcdc5_ix = -1;
-	s8 dc1sw_ix = -1;
-	s8 dc5ldo_ix = -1;
-	bool drivevbus = false;
-	u32 skip_bitmap = 0;
+	struct axp_cfg axp_cfg;
+
+	axp_cfg.dcdc1_ix = -1;
+	axp_cfg.dcdc5_ix = -1;
+	axp_cfg.dc1sw_ix = -1;
+	axp_cfg.dc5ldo_ix = -1;
+	axp_cfg.drivevbus = false;
+	axp_cfg.skip_bitmap = 0;
 
 	switch (axp20x->variant) {
 	case AXP202_ID:
 	case AXP209_ID:
-		regulators = axp20x_regulators;
-		nregulators = AXP20X_REG_ID_MAX;
+		axp_cfg.regulators = axp20x_regulators;
+		axp_cfg.nregulators = AXP20X_REG_ID_MAX;
 		break;
 	case AXP221_ID:
 	case AXP223_ID:
-		regulators = axp22x_regulators;
-		nregulators = AXP22X_REG_ID_MAX;
-		dcdc1_ix = AXP22X_DCDC1;
-		dcdc5_ix = AXP22X_DCDC5;
-		dc1sw_ix = AXP22X_DC1SW;
-		dc5ldo_ix = AXP22X_DC5LDO;
-		drivevbus = of_property_read_bool(dev->of_node,
+		axp_cfg.regulators = axp22x_regulators;
+		axp_cfg.nregulators = AXP22X_REG_ID_MAX;
+		axp_cfg.dcdc1_ix = AXP22X_DCDC1;
+		axp_cfg.dcdc5_ix = AXP22X_DCDC5;
+		axp_cfg.dc1sw_ix = AXP22X_DC1SW;
+		axp_cfg.dc5ldo_ix = AXP22X_DC5LDO;
+		axp_cfg.drivevbus = of_property_read_bool(dev->of_node,
 						  "x-powers,drive-vbus-en");
 		break;
 	case AXP806_ID:
-		regulators = axp806_regulators;
-		nregulators = AXP806_REG_ID_MAX;
+		axp_cfg.regulators = axp806_regulators;
+		axp_cfg.nregulators = AXP806_REG_ID_MAX;
 
 		/*
 		 * The regulators which are slave in a poly-phase setup
 		 * are skipped, as their controls are bound to the master
 		 * regulator and won't work.
 		 */
-		skip_bitmap |= axp20x_polyphase_slave(axp20x);
+		axp_cfg.skip_bitmap |= axp20x_polyphase_slave(axp20x);
 		break;
 	case AXP809_ID:
-		regulators = axp809_regulators;
-		nregulators = AXP809_REG_ID_MAX;
-		dcdc1_ix = AXP809_DCDC1;
-		dcdc5_ix = AXP809_DCDC5;
-		dc1sw_ix = AXP809_DC1SW;
-		dc5ldo_ix = AXP809_DC5LDO;
+		axp_cfg.regulators = axp809_regulators;
+		axp_cfg.nregulators = AXP809_REG_ID_MAX;
+		axp_cfg.dcdc1_ix = AXP809_DCDC1;
+		axp_cfg.dcdc5_ix = AXP809_DCDC5;
+		axp_cfg.dc1sw_ix = AXP809_DC1SW;
+		axp_cfg.dc5ldo_ix = AXP809_DC5LDO;
 		break;
 	default:
 		dev_err(dev, "Unsupported AXP variant: %ld\n",
@@ -561,86 +281,7 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	/* This only sets the dcdc freq. Ignore any errors */
-	axp20x_regulator_parse_dt(dev);
-
-	for (i = 0; i < nregulators; i++) {
-		const struct regulator_desc *desc = &regulators[i];
-		struct regulator_desc *new_desc;
-
-		if (skip_bitmap & (1 << i))
-			continue;
-
-		/*
-		 * Regulators DC1SW and DC5LDO are connected internally,
-		 * so we have to handle their supply names separately.
-		 *
-		 * We always register the regulators in proper sequence,
-		 * so the supply names are correctly read. See the last
-		 * part of this loop to see where we save the DT defined
-		 * name.
-		 */
-		if (i == dc1sw_ix && dcdc1_name) {
-			new_desc = devm_kzalloc(dev, sizeof(*desc),
-						GFP_KERNEL);
-			*new_desc = regulators[i];
-			new_desc->supply_name = dcdc1_name;
-			desc = new_desc;
-		}
-
-		if (i == dc5ldo_ix && dcdc5_name) {
-			new_desc = devm_kzalloc(dev, sizeof(*desc),
-						GFP_KERNEL);
-			*new_desc = regulators[i];
-			new_desc->supply_name = dcdc5_name;
-			desc = new_desc;
-		}
-
-		rdev = devm_regulator_register(dev, desc, &config);
-		if (IS_ERR(rdev)) {
-			dev_err(dev, "Failed to register %s\n",
-				regulators[i].name);
-
-			return PTR_ERR(rdev);
-		}
-
-		ret = of_property_read_u32(rdev->dev.of_node,
-					   "x-powers,dcdc-workmode",
-					   &workmode);
-		if (!ret) {
-			if (axp20x_set_dcdc_workmode(rdev, i, workmode))
-				dev_err(dev, "Failed to set workmode on %s\n",
-					rdev->desc->name);
-		}
-
-		/*
-		 * Save AXP22X DCDC1 / DCDC5 regulator names for later.
-		 */
-		if (i == dcdc1_ix)
-			of_property_read_string(rdev->dev.of_node,
-						"regulator-name",
-						&dcdc1_name);
-
-		if (i == dcdc5_ix)
-			of_property_read_string(rdev->dev.of_node,
-						"regulator-name",
-						&dcdc5_name);
-	}
-
-	if (drivevbus) {
-		/* Change N_VBUSEN sense pin to DRIVEVBUS output pin */
-		regmap_update_bits(axp20x->regmap, AXP20X_OVER_TMP,
-				   AXP22X_MISC_N_VBUSEN_FUNC, 0);
-		rdev = devm_regulator_register(dev,
-					       &axp22x_drivevbus_regulator,
-					       &config);
-		if (IS_ERR(rdev)) {
-			dev_err(dev, "Failed to register drivevbus\n");
-			return PTR_ERR(rdev);
-		}
-	}
-
-	return 0;
+	return axp_regulator_create(dev, &axp_cfg);
 }
 
 static struct platform_driver axp20x_regulator_driver = {
-- 
2.10.0

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 2/4] regulator: axp20x: duplicate the MFD axp20x-rsb code
@ 2016-09-22 17:25   ` Jean-Francois Moine
  0 siblings, 0 replies; 27+ messages in thread
From: Jean-Francois Moine @ 2016-09-22 17:25 UTC (permalink / raw)
  To: Chen-Yu Tsai, Mark Rutland, Rob Herring
  Cc: devicetree, linux-arm-kernel, linux-kernel, linux-sunxi

The axp20x rsb driver handles many different devices.
Duplicating its code in a generic regulator driver permits
to probe/remove individual devices.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
 drivers/regulator/axp-regulator.c | 39 +++++++++++++++++++++++++++++++++++++++
 drivers/regulator/axp-regulator.h |  6 ++++++
 2 files changed, 45 insertions(+)

diff --git a/drivers/regulator/axp-regulator.c b/drivers/regulator/axp-regulator.c
index 0d7adb6..17943fb 100644
--- a/drivers/regulator/axp-regulator.c
+++ b/drivers/regulator/axp-regulator.c
@@ -303,6 +303,45 @@ int axp_regulator_create(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(axp_regulator_create);
 
+/* probe/remove RSB devices */
+int axp_rsb_probe(struct sunxi_rsb_device *rdev,
+		  struct axp20x_dev *axp20x,
+		  const struct axp_cfg *axp_cfg)
+{
+	int ret;
+
+	axp20x->dev = &rdev->dev;
+	axp20x->irq = rdev->irq;
+	dev_set_drvdata(&rdev->dev, axp20x);
+
+	ret = axp20x_match_device(axp20x);
+	if (ret)
+		return ret;
+
+	axp20x->regmap = devm_regmap_init_sunxi_rsb(rdev,
+						    axp20x->regmap_cfg);
+	if (IS_ERR(axp20x->regmap)) {
+		ret = PTR_ERR(axp20x->regmap);
+		dev_err(&rdev->dev, "regmap init failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = axp20x_device_probe(axp20x);
+	if (ret < 0)
+		return ret;
+
+	return axp_regulator_create(&rdev->dev, axp_cfg);
+}
+EXPORT_SYMBOL_GPL(axp_rsb_probe);
+
+int axp_rsb_remove(struct sunxi_rsb_device *rdev)
+{
+	struct axp20x_dev *axp20x = sunxi_rsb_device_get_drvdata(rdev);
+
+	return axp20x_device_remove(axp20x);
+}
+EXPORT_SYMBOL_GPL(axp_rsb_remove);
+
 MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
 MODULE_DESCRIPTION("Regulator Module for AXP PMIC");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/axp-regulator.h b/drivers/regulator/axp-regulator.h
index 0adf1b0..085eaa0 100644
--- a/drivers/regulator/axp-regulator.h
+++ b/drivers/regulator/axp-regulator.h
@@ -124,4 +124,10 @@ struct axp_cfg {
 int axp_regulator_create(struct device *dev,
 			 const struct axp_cfg *axp_cfg);
 
+struct sunxi_rsb_device;
+int axp_rsb_probe(struct sunxi_rsb_device *rdev,
+		  struct axp20x_dev *axp20x,
+		  const struct axp_cfg *axp_cfg);
+int axp_rsb_remove(struct sunxi_rsb_device *rdev);
+
 #endif /* __AXP_REGULATOR_H__ */
-- 
2.10.0

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 2/4] regulator: axp20x: duplicate the MFD axp20x-rsb code
@ 2016-09-22 17:25   ` Jean-Francois Moine
  0 siblings, 0 replies; 27+ messages in thread
From: Jean-Francois Moine @ 2016-09-22 17:25 UTC (permalink / raw)
  To: Chen-Yu Tsai, Mark Rutland, Rob Herring
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw

The axp20x rsb driver handles many different devices.
Duplicating its code in a generic regulator driver permits
to probe/remove individual devices.

Signed-off-by: Jean-Francois Moine <moinejf-GANU6spQydw@public.gmane.org>
---
 drivers/regulator/axp-regulator.c | 39 +++++++++++++++++++++++++++++++++++++++
 drivers/regulator/axp-regulator.h |  6 ++++++
 2 files changed, 45 insertions(+)

diff --git a/drivers/regulator/axp-regulator.c b/drivers/regulator/axp-regulator.c
index 0d7adb6..17943fb 100644
--- a/drivers/regulator/axp-regulator.c
+++ b/drivers/regulator/axp-regulator.c
@@ -303,6 +303,45 @@ int axp_regulator_create(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(axp_regulator_create);
 
+/* probe/remove RSB devices */
+int axp_rsb_probe(struct sunxi_rsb_device *rdev,
+		  struct axp20x_dev *axp20x,
+		  const struct axp_cfg *axp_cfg)
+{
+	int ret;
+
+	axp20x->dev = &rdev->dev;
+	axp20x->irq = rdev->irq;
+	dev_set_drvdata(&rdev->dev, axp20x);
+
+	ret = axp20x_match_device(axp20x);
+	if (ret)
+		return ret;
+
+	axp20x->regmap = devm_regmap_init_sunxi_rsb(rdev,
+						    axp20x->regmap_cfg);
+	if (IS_ERR(axp20x->regmap)) {
+		ret = PTR_ERR(axp20x->regmap);
+		dev_err(&rdev->dev, "regmap init failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = axp20x_device_probe(axp20x);
+	if (ret < 0)
+		return ret;
+
+	return axp_regulator_create(&rdev->dev, axp_cfg);
+}
+EXPORT_SYMBOL_GPL(axp_rsb_probe);
+
+int axp_rsb_remove(struct sunxi_rsb_device *rdev)
+{
+	struct axp20x_dev *axp20x = sunxi_rsb_device_get_drvdata(rdev);
+
+	return axp20x_device_remove(axp20x);
+}
+EXPORT_SYMBOL_GPL(axp_rsb_remove);
+
 MODULE_AUTHOR("Carlo Caione <carlo-KA+7E9HrN00dnm+yROfE0A@public.gmane.org>");
 MODULE_DESCRIPTION("Regulator Module for AXP PMIC");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/axp-regulator.h b/drivers/regulator/axp-regulator.h
index 0adf1b0..085eaa0 100644
--- a/drivers/regulator/axp-regulator.h
+++ b/drivers/regulator/axp-regulator.h
@@ -124,4 +124,10 @@ struct axp_cfg {
 int axp_regulator_create(struct device *dev,
 			 const struct axp_cfg *axp_cfg);
 
+struct sunxi_rsb_device;
+int axp_rsb_probe(struct sunxi_rsb_device *rdev,
+		  struct axp20x_dev *axp20x,
+		  const struct axp_cfg *axp_cfg);
+int axp_rsb_remove(struct sunxi_rsb_device *rdev);
+
 #endif /* __AXP_REGULATOR_H__ */
-- 
2.10.0

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 2/4] regulator: axp20x: duplicate the MFD axp20x-rsb code
@ 2016-09-22 17:25   ` Jean-Francois Moine
  0 siblings, 0 replies; 27+ messages in thread
From: Jean-Francois Moine @ 2016-09-22 17:25 UTC (permalink / raw)
  To: linux-arm-kernel

The axp20x rsb driver handles many different devices.
Duplicating its code in a generic regulator driver permits
to probe/remove individual devices.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
 drivers/regulator/axp-regulator.c | 39 +++++++++++++++++++++++++++++++++++++++
 drivers/regulator/axp-regulator.h |  6 ++++++
 2 files changed, 45 insertions(+)

diff --git a/drivers/regulator/axp-regulator.c b/drivers/regulator/axp-regulator.c
index 0d7adb6..17943fb 100644
--- a/drivers/regulator/axp-regulator.c
+++ b/drivers/regulator/axp-regulator.c
@@ -303,6 +303,45 @@ int axp_regulator_create(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(axp_regulator_create);
 
+/* probe/remove RSB devices */
+int axp_rsb_probe(struct sunxi_rsb_device *rdev,
+		  struct axp20x_dev *axp20x,
+		  const struct axp_cfg *axp_cfg)
+{
+	int ret;
+
+	axp20x->dev = &rdev->dev;
+	axp20x->irq = rdev->irq;
+	dev_set_drvdata(&rdev->dev, axp20x);
+
+	ret = axp20x_match_device(axp20x);
+	if (ret)
+		return ret;
+
+	axp20x->regmap = devm_regmap_init_sunxi_rsb(rdev,
+						    axp20x->regmap_cfg);
+	if (IS_ERR(axp20x->regmap)) {
+		ret = PTR_ERR(axp20x->regmap);
+		dev_err(&rdev->dev, "regmap init failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = axp20x_device_probe(axp20x);
+	if (ret < 0)
+		return ret;
+
+	return axp_regulator_create(&rdev->dev, axp_cfg);
+}
+EXPORT_SYMBOL_GPL(axp_rsb_probe);
+
+int axp_rsb_remove(struct sunxi_rsb_device *rdev)
+{
+	struct axp20x_dev *axp20x = sunxi_rsb_device_get_drvdata(rdev);
+
+	return axp20x_device_remove(axp20x);
+}
+EXPORT_SYMBOL_GPL(axp_rsb_remove);
+
 MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
 MODULE_DESCRIPTION("Regulator Module for AXP PMIC");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/axp-regulator.h b/drivers/regulator/axp-regulator.h
index 0adf1b0..085eaa0 100644
--- a/drivers/regulator/axp-regulator.h
+++ b/drivers/regulator/axp-regulator.h
@@ -124,4 +124,10 @@ struct axp_cfg {
 int axp_regulator_create(struct device *dev,
 			 const struct axp_cfg *axp_cfg);
 
+struct sunxi_rsb_device;
+int axp_rsb_probe(struct sunxi_rsb_device *rdev,
+		  struct axp20x_dev *axp20x,
+		  const struct axp_cfg *axp_cfg);
+int axp_rsb_remove(struct sunxi_rsb_device *rdev);
+
 #endif /* __AXP_REGULATOR_H__ */
-- 
2.10.0

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 3/4] regulator: axp20x: add the AXP803
@ 2016-09-23  7:00   ` Jean-Francois Moine
  0 siblings, 0 replies; 27+ messages in thread
From: Jean-Francois Moine @ 2016-09-23  7:00 UTC (permalink / raw)
  To: Chen-Yu Tsai, Mark Rutland, Rob Herring
  Cc: devicetree, linux-arm-kernel, linux-kernel, linux-sunxi

The X-Powers AXP803 PMIC is close to the AXP809 with more outputs.
It is used in some Allwinner boards as the Sinovoip BananaPi M64
and the Pine A64.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
not tested
---
 Documentation/devicetree/bindings/mfd/axp20x.txt |  32 +++-
 drivers/mfd/axp20x.c                             |  13 ++
 drivers/regulator/Makefile                       |   3 +-
 drivers/regulator/axp803.c                       | 225 +++++++++++++++++++++++
 include/linux/mfd/axp20x.h                       |   1 +
 5 files changed, 271 insertions(+), 3 deletions(-)
 create mode 100644 drivers/regulator/axp803.c

diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
index 8f3ad9a..3332d02 100644
--- a/Documentation/devicetree/bindings/mfd/axp20x.txt
+++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
@@ -6,12 +6,13 @@ axp202 (X-Powers)
 axp209 (X-Powers)
 axp221 (X-Powers)
 axp223 (X-Powers)
+axp803 (X-Powers)
 axp809 (X-Powers)
 
 Required properties:
 - compatible: "x-powers,axp152", "x-powers,axp202", "x-powers,axp209",
-	      "x-powers,axp221", "x-powers,axp223", "x-powers,axp806",
-	      "x-powers,axp809"
+	      "x-powers,axp221", "x-powers,axp223", "x-powers,axp803",
+	      "x-powers,axp806", "x-powers,axp809"
 - reg: The I2C slave address or RSB hardware address for the AXP chip
 - interrupt-parent: The parent interrupt controller
 - interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
@@ -86,6 +87,33 @@ LDO_IO1		: LDO		: ips-supply		: GPIO 1
 RTC_LDO		: LDO		: ips-supply		: always on
 DRIVEVBUS	: Enable output	: drivevbus-supply	: external regulator
 
+AXP803 regulators, type, and corresponding input supply names:
+
+Regulator	  Type		  Supply Name		  Notes
+---------	  ----		  -----------		  -----
+DCDC1		: DC-DC buck	: vin1-supply
+DCDC2		: DC-DC buck	: vin2-supply
+DCDC3		: DC-DC	buck	: vin3-supply
+DCDC4		: DC-DC	buck	: vin4-supply
+DCDC5		: DC-DC	buck	: vin5-supply
+DCDC6		: DC-DC	buck	: vin6-supply
+ALDO1		: LDO		: aldoin-supply	: shared supply
+ALDO2		: LDO		: aldoin-supply	: shared supply
+ALDO3		: LDO		: aldoin-supply	: shared supply
+DLDO1		: LDO		: dldoin-supply	: shared supply
+DLDO2		: LDO		: dldoin-supply	: shared supply
+DLDO3		: LDO		: dldoin-supply	: shared supply
+DLDO4		: LDO		: dldoin-supply	: shared supply
+ELDO1		: LDO		: eldoin-supply	: shared supply
+ELDO2		: LDO		: eldoin-supply	: shared supply
+ELDO3		: LDO		: eldoin-supply	: shared supply
+FLDO1		: LDO		: fldoin-supply	: shared supply
+FLDO2		: LDO		: fldoin-supply	: shared supply
+RTC_LDO		: LDO		: ips-supply	: always on
+LDO_IO0		: LDO		: ips-supply	: GPIO 0
+LDO_IO1		: LDO		: ips-supply	: GPIO 1
+DC1SW		: On/Off Switch	:		: DCDC1 secondary output
+
 AXP806 regulators, type, and corresponding input supply names:
 
 Regulator	  Type		  Supply Name		  Notes
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index ba130be..7c90b12 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -38,6 +38,7 @@ static const char * const axp20x_model_names[] = {
 	"AXP221",
 	"AXP223",
 	"AXP288",
+	"AXP803",
 	"AXP806",
 	"AXP809",
 };
@@ -739,6 +740,14 @@ static struct mfd_cell axp809_cells[] = {
 	},
 };
 
+static struct mfd_cell axp803_cells[] = {
+	{
+		.name			= "axp20x-pek",
+		.num_resources		= ARRAY_SIZE(axp809_pek_resources),
+		.resources		= axp809_pek_resources,
+	},
+};
+
 static struct axp20x_dev *axp20x_pm_power_off;
 static void axp20x_power_off(void)
 {
@@ -801,6 +810,10 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
 		axp20x->regmap_cfg = &axp288_regmap_config;
 		axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
 		break;
+	case AXP803_ID:
+		axp20x->cells = axp803_cells;
+		axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
+		break;
 	case AXP806_ID:
 		axp20x->nr_cells = ARRAY_SIZE(axp806_cells);
 		axp20x->cells = axp806_cells;
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 225a026..2cbb280 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -21,7 +21,8 @@ obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
 obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
 obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
 obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
-obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o axp-regulator.o
+obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o axp-regulator.o \
+				axp803.o
 obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o
 obj-$(CONFIG_REGULATOR_DA903X)	+= da903x.o
 obj-$(CONFIG_REGULATOR_DA9052)	+= da9052-regulator.o
diff --git a/drivers/regulator/axp803.c b/drivers/regulator/axp803.c
new file mode 100644
index 0000000..bae83dd
--- /dev/null
+++ b/drivers/regulator/axp803.c
@@ -0,0 +1,225 @@
+/*
+ * AXP803 regulator driver
+ *
+ * Copyright (C) 2016 Jean-Francois Moine <moinejf@free.fr>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/axp20x.h>
+#include <linux/regulator/driver.h>
+#include <linux/sunxi-rsb.h>
+
+#include "axp-regulator.h"
+
+enum {
+	AXP803_DLDO1 = 0,
+	AXP803_DLDO2,
+	AXP803_DLDO3,
+	AXP803_DLDO4,
+	AXP803_ELDO1,
+	AXP803_ELDO2,
+	AXP803_ELDO3,
+	AXP803_FLDO1,
+	AXP803_FLDO2,
+	AXP803_DCDC1,
+	AXP803_DCDC2,
+	AXP803_DCDC3,
+	AXP803_DCDC4,
+	AXP803_DCDC5,
+	AXP803_DCDC6,
+	AXP803_ALDO1,
+	AXP803_ALDO2,
+	AXP803_ALDO3,
+	AXP803_LDO_IO0,
+	AXP803_LDO_IO1,
+	AXP803_RTC_LDO,
+	AXP803_DC1SW,
+};
+
+/* AXP803 registers */
+#define AXP803_FLDO1_V_OUT		0x1c
+#define AXP803_FLDO2_V_OUT		0x1d
+#define AXP803_DCDC1_V_OUT		0x20
+#define AXP803_DCDC2_V_OUT		0x21
+#define AXP803_DCDC3_V_OUT		0x22
+#define AXP803_DCDC4_V_OUT		0x23
+#define AXP803_DCDC5_V_OUT		0x24
+#define AXP803_DCDC6_V_OUT		0x25
+
+static const struct regulator_linear_range axp803_dldo2_ranges[] = {
+	REGULATOR_LINEAR_RANGE(700000, 0, 26, 100000),
+	REGULATOR_LINEAR_RANGE(3400000, 27, 31, 200000),
+};
+
+static const struct regulator_linear_range axp803_dcdc2_4_ranges[] = {
+	REGULATOR_LINEAR_RANGE(500000, 0, 71, 10000),
+	REGULATOR_LINEAR_RANGE(1220000, 72, 76, 20000),
+};
+
+static const struct regulator_linear_range axp803_dcdc5_ranges[] = {
+	REGULATOR_LINEAR_RANGE(800000, 0, 33, 10000),
+	REGULATOR_LINEAR_RANGE(1140000, 34, 69, 20000),
+};
+
+static const struct regulator_linear_range axp803_dcdc6_ranges[] = {
+	REGULATOR_LINEAR_RANGE(600000, 0, 51, 10000),
+	REGULATOR_LINEAR_RANGE(1120000, 52, 72, 20000),
+};
+
+static const struct regulator_desc axp803_regulators[] = {
+	AXP_DESC(AXP803, DLDO1, "dldo1", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(3)),
+	AXP_DESC_RANGES(AXP803, DLDO2, "dldo2", "dldoin", axp803_dldo2_ranges,
+			31, AXP22X_DLDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
+			BIT(4)),
+	AXP_DESC(AXP803, DLDO3, "dldo3", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
+	AXP_DESC(AXP803, DLDO4, "dldo4", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO4_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(6)),
+	AXP_DESC(AXP803, ELDO1, "eldo1", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(0)),
+	AXP_DESC(AXP803, ELDO2, "eldo2", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
+	AXP_DESC(AXP803, ELDO3, "eldo3", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
+	AXP_DESC(AXP803, FLDO1, "fldo1", "fldoin", 700, 1450, 50,
+		 AXP803_FLDO1_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(2)),
+	AXP_DESC(AXP803, FLDO2, "fldo2", "fldoin", 700, 1450, 50,
+		 AXP803_FLDO2_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(3)),
+	AXP_DESC(AXP803, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
+		 AXP803_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(0)),
+	AXP_DESC_RANGES(AXP803, DCDC2, "dcdc2", "vin2", axp803_dcdc2_4_ranges,
+			76, AXP803_DCDC2_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(1)),
+	AXP_DESC_RANGES(AXP803, DCDC3, "dcdc3", "vin3", axp803_dcdc2_4_ranges,
+			76, AXP803_DCDC3_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(2)),
+	AXP_DESC_RANGES(AXP803, DCDC4, "dcdc4", "vin4", axp803_dcdc2_4_ranges,
+			76, AXP803_DCDC4_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(3)),
+	AXP_DESC_RANGES(AXP803, DCDC5, "dcdc5", "vin5", axp803_dcdc5_ranges,
+			69, AXP803_DCDC5_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(4)),
+	AXP_DESC_RANGES(AXP803, DCDC6, "dcdc6", "vin6", axp803_dcdc6_ranges,
+			72, AXP803_DCDC6_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(5)),
+	AXP_DESC(AXP803, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(5)),
+	AXP_DESC(AXP803, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(6)),
+	AXP_DESC(AXP803, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(7)),
+	AXP_DESC_IO(AXP803, LDO_IO0, "ldo_io0", "ips", 700, 3300, 100,
+		    AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
+		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
+	AXP_DESC_IO(AXP803, LDO_IO1, "ldo_io1", "ips", 700, 3300, 100,
+		    AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
+		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
+	AXP_DESC_FIXED(AXP803, RTC_LDO, "rtc_ldo", "ips", 1800),
+	/* secondary switchable output of DCDC1 */
+	AXP_DESC_SW(AXP803, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2,
+		    BIT(7)),
+};
+
+static const struct regmap_range axp803_writeable_ranges[] = {
+	regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
+	regmap_reg_range(AXP20X_DCDC_MODE, AXP22X_BATLOW_THRES1),
+};
+
+static const struct regmap_range axp803_volatile_ranges[] = {
+	regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_PWR_OP_MODE),
+	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
+	regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
+	regmap_reg_range(AXP20X_FG_RES, AXP20X_FG_RES),
+};
+
+static const struct regmap_access_table axp803_writeable_table = {
+	.yes_ranges	= axp803_writeable_ranges,
+	.n_yes_ranges	= ARRAY_SIZE(axp803_writeable_ranges),
+};
+
+static const struct regmap_access_table axp803_volatile_table = {
+	.yes_ranges	= axp803_volatile_ranges,
+	.n_yes_ranges	= ARRAY_SIZE(axp803_volatile_ranges),
+};
+
+static const struct regmap_config axp803_regmap_config = {
+	.reg_bits	= 8,
+	.val_bits	= 8,
+	.wr_table	= &axp803_writeable_table,
+	.volatile_table	= &axp803_volatile_table,
+	.max_register	= AXP22X_BATLOW_THRES1,
+	.cache_type	= REGCACHE_RBTREE,
+};
+
+#define INIT_REGMAP_IRQ(_irq, _off, _bit)			\
+	[AXP809_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_bit) }
+
+static const struct regmap_irq axp803_regmap_irqs[] = {
+	INIT_REGMAP_IRQ(PEK_RIS_EDGE,	        4, 6),
+	INIT_REGMAP_IRQ(PEK_FAL_EDGE,	        4, 5),
+	INIT_REGMAP_IRQ(PEK_SHORT,		4, 4),
+	INIT_REGMAP_IRQ(PEK_LONG,		4, 3),
+	INIT_REGMAP_IRQ(PEK_OVER_OFF,		4, 2),
+	INIT_REGMAP_IRQ(GPIO1_INPUT,		4, 1),
+	INIT_REGMAP_IRQ(GPIO0_INPUT,		4, 0),
+};
+
+static const struct regmap_irq_chip axp803_regmap_irq_chip = {
+	.name			= "axp803",
+	.status_base		= AXP20X_IRQ1_STATE,
+	.ack_base		= AXP20X_IRQ1_STATE,
+	.mask_base		= AXP20X_IRQ1_EN,
+	.mask_invert		= true,
+	.init_ack_masked	= true,
+	.irqs			= axp803_regmap_irqs,
+	.num_irqs		= ARRAY_SIZE(axp803_regmap_irqs),
+	.num_regs		= 6,
+};
+
+static const struct axp_cfg axp803_cfg = {
+	.regulators = axp803_regulators,
+	.nregulators= ARRAY_SIZE(axp803_regulators),
+	.dcdc1_ix = AXP803_DCDC1,
+	.dcdc5_ix = -1,
+	.dc1sw_ix = AXP803_DC1SW,
+	.dc5ldo_ix = -1,
+};
+
+static struct axp20x_dev axp803_dev = {
+	.regmap_cfg = &axp803_regmap_config,
+	.regmap_irq_chip = &axp803_regmap_irq_chip,
+};
+
+static int axp803_rsb_probe(struct sunxi_rsb_device *rdev)
+{
+	return axp_rsb_probe(rdev, &axp803_dev, &axp803_cfg);
+}
+
+static const struct of_device_id axp803_of_match[] = {
+	{ .compatible = "x-powers,axp803", .data = (void *) AXP803_ID },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, axp803_of_match);
+
+static struct sunxi_rsb_driver axp803_rsb_driver = {
+	.driver = {
+		.name	= "axp803-rsb",
+		.of_match_table	= of_match_ptr(axp803_of_match),
+	},
+	.probe	= axp803_rsb_probe,
+	.remove	= axp_rsb_remove,
+};
+module_sunxi_rsb_driver(axp803_rsb_driver);
+
+MODULE_DESCRIPTION("AXP803 RSB driver");
+MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
index fec597f..9c5fb00 100644
--- a/include/linux/mfd/axp20x.h
+++ b/include/linux/mfd/axp20x.h
@@ -20,6 +20,7 @@ enum {
 	AXP221_ID,
 	AXP223_ID,
 	AXP288_ID,
+	AXP803_ID,
 	AXP806_ID,
 	AXP809_ID,
 	NR_AXP20X_VARIANTS,
-- 
2.10.0

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 3/4] regulator: axp20x: add the AXP803
@ 2016-09-23  7:00   ` Jean-Francois Moine
  0 siblings, 0 replies; 27+ messages in thread
From: Jean-Francois Moine @ 2016-09-23  7:00 UTC (permalink / raw)
  To: Chen-Yu Tsai, Mark Rutland, Rob Herring
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw

The X-Powers AXP803 PMIC is close to the AXP809 with more outputs.
It is used in some Allwinner boards as the Sinovoip BananaPi M64
and the Pine A64.

Signed-off-by: Jean-Francois Moine <moinejf-GANU6spQydw@public.gmane.org>
---
not tested
---
 Documentation/devicetree/bindings/mfd/axp20x.txt |  32 +++-
 drivers/mfd/axp20x.c                             |  13 ++
 drivers/regulator/Makefile                       |   3 +-
 drivers/regulator/axp803.c                       | 225 +++++++++++++++++++++++
 include/linux/mfd/axp20x.h                       |   1 +
 5 files changed, 271 insertions(+), 3 deletions(-)
 create mode 100644 drivers/regulator/axp803.c

diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
index 8f3ad9a..3332d02 100644
--- a/Documentation/devicetree/bindings/mfd/axp20x.txt
+++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
@@ -6,12 +6,13 @@ axp202 (X-Powers)
 axp209 (X-Powers)
 axp221 (X-Powers)
 axp223 (X-Powers)
+axp803 (X-Powers)
 axp809 (X-Powers)
 
 Required properties:
 - compatible: "x-powers,axp152", "x-powers,axp202", "x-powers,axp209",
-	      "x-powers,axp221", "x-powers,axp223", "x-powers,axp806",
-	      "x-powers,axp809"
+	      "x-powers,axp221", "x-powers,axp223", "x-powers,axp803",
+	      "x-powers,axp806", "x-powers,axp809"
 - reg: The I2C slave address or RSB hardware address for the AXP chip
 - interrupt-parent: The parent interrupt controller
 - interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
@@ -86,6 +87,33 @@ LDO_IO1		: LDO		: ips-supply		: GPIO 1
 RTC_LDO		: LDO		: ips-supply		: always on
 DRIVEVBUS	: Enable output	: drivevbus-supply	: external regulator
 
+AXP803 regulators, type, and corresponding input supply names:
+
+Regulator	  Type		  Supply Name		  Notes
+---------	  ----		  -----------		  -----
+DCDC1		: DC-DC buck	: vin1-supply
+DCDC2		: DC-DC buck	: vin2-supply
+DCDC3		: DC-DC	buck	: vin3-supply
+DCDC4		: DC-DC	buck	: vin4-supply
+DCDC5		: DC-DC	buck	: vin5-supply
+DCDC6		: DC-DC	buck	: vin6-supply
+ALDO1		: LDO		: aldoin-supply	: shared supply
+ALDO2		: LDO		: aldoin-supply	: shared supply
+ALDO3		: LDO		: aldoin-supply	: shared supply
+DLDO1		: LDO		: dldoin-supply	: shared supply
+DLDO2		: LDO		: dldoin-supply	: shared supply
+DLDO3		: LDO		: dldoin-supply	: shared supply
+DLDO4		: LDO		: dldoin-supply	: shared supply
+ELDO1		: LDO		: eldoin-supply	: shared supply
+ELDO2		: LDO		: eldoin-supply	: shared supply
+ELDO3		: LDO		: eldoin-supply	: shared supply
+FLDO1		: LDO		: fldoin-supply	: shared supply
+FLDO2		: LDO		: fldoin-supply	: shared supply
+RTC_LDO		: LDO		: ips-supply	: always on
+LDO_IO0		: LDO		: ips-supply	: GPIO 0
+LDO_IO1		: LDO		: ips-supply	: GPIO 1
+DC1SW		: On/Off Switch	:		: DCDC1 secondary output
+
 AXP806 regulators, type, and corresponding input supply names:
 
 Regulator	  Type		  Supply Name		  Notes
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index ba130be..7c90b12 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -38,6 +38,7 @@ static const char * const axp20x_model_names[] = {
 	"AXP221",
 	"AXP223",
 	"AXP288",
+	"AXP803",
 	"AXP806",
 	"AXP809",
 };
@@ -739,6 +740,14 @@ static struct mfd_cell axp809_cells[] = {
 	},
 };
 
+static struct mfd_cell axp803_cells[] = {
+	{
+		.name			= "axp20x-pek",
+		.num_resources		= ARRAY_SIZE(axp809_pek_resources),
+		.resources		= axp809_pek_resources,
+	},
+};
+
 static struct axp20x_dev *axp20x_pm_power_off;
 static void axp20x_power_off(void)
 {
@@ -801,6 +810,10 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
 		axp20x->regmap_cfg = &axp288_regmap_config;
 		axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
 		break;
+	case AXP803_ID:
+		axp20x->cells = axp803_cells;
+		axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
+		break;
 	case AXP806_ID:
 		axp20x->nr_cells = ARRAY_SIZE(axp806_cells);
 		axp20x->cells = axp806_cells;
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 225a026..2cbb280 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -21,7 +21,8 @@ obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
 obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
 obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
 obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
-obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o axp-regulator.o
+obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o axp-regulator.o \
+				axp803.o
 obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o
 obj-$(CONFIG_REGULATOR_DA903X)	+= da903x.o
 obj-$(CONFIG_REGULATOR_DA9052)	+= da9052-regulator.o
diff --git a/drivers/regulator/axp803.c b/drivers/regulator/axp803.c
new file mode 100644
index 0000000..bae83dd
--- /dev/null
+++ b/drivers/regulator/axp803.c
@@ -0,0 +1,225 @@
+/*
+ * AXP803 regulator driver
+ *
+ * Copyright (C) 2016 Jean-Francois Moine <moinejf-GANU6spQydw@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/axp20x.h>
+#include <linux/regulator/driver.h>
+#include <linux/sunxi-rsb.h>
+
+#include "axp-regulator.h"
+
+enum {
+	AXP803_DLDO1 = 0,
+	AXP803_DLDO2,
+	AXP803_DLDO3,
+	AXP803_DLDO4,
+	AXP803_ELDO1,
+	AXP803_ELDO2,
+	AXP803_ELDO3,
+	AXP803_FLDO1,
+	AXP803_FLDO2,
+	AXP803_DCDC1,
+	AXP803_DCDC2,
+	AXP803_DCDC3,
+	AXP803_DCDC4,
+	AXP803_DCDC5,
+	AXP803_DCDC6,
+	AXP803_ALDO1,
+	AXP803_ALDO2,
+	AXP803_ALDO3,
+	AXP803_LDO_IO0,
+	AXP803_LDO_IO1,
+	AXP803_RTC_LDO,
+	AXP803_DC1SW,
+};
+
+/* AXP803 registers */
+#define AXP803_FLDO1_V_OUT		0x1c
+#define AXP803_FLDO2_V_OUT		0x1d
+#define AXP803_DCDC1_V_OUT		0x20
+#define AXP803_DCDC2_V_OUT		0x21
+#define AXP803_DCDC3_V_OUT		0x22
+#define AXP803_DCDC4_V_OUT		0x23
+#define AXP803_DCDC5_V_OUT		0x24
+#define AXP803_DCDC6_V_OUT		0x25
+
+static const struct regulator_linear_range axp803_dldo2_ranges[] = {
+	REGULATOR_LINEAR_RANGE(700000, 0, 26, 100000),
+	REGULATOR_LINEAR_RANGE(3400000, 27, 31, 200000),
+};
+
+static const struct regulator_linear_range axp803_dcdc2_4_ranges[] = {
+	REGULATOR_LINEAR_RANGE(500000, 0, 71, 10000),
+	REGULATOR_LINEAR_RANGE(1220000, 72, 76, 20000),
+};
+
+static const struct regulator_linear_range axp803_dcdc5_ranges[] = {
+	REGULATOR_LINEAR_RANGE(800000, 0, 33, 10000),
+	REGULATOR_LINEAR_RANGE(1140000, 34, 69, 20000),
+};
+
+static const struct regulator_linear_range axp803_dcdc6_ranges[] = {
+	REGULATOR_LINEAR_RANGE(600000, 0, 51, 10000),
+	REGULATOR_LINEAR_RANGE(1120000, 52, 72, 20000),
+};
+
+static const struct regulator_desc axp803_regulators[] = {
+	AXP_DESC(AXP803, DLDO1, "dldo1", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(3)),
+	AXP_DESC_RANGES(AXP803, DLDO2, "dldo2", "dldoin", axp803_dldo2_ranges,
+			31, AXP22X_DLDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
+			BIT(4)),
+	AXP_DESC(AXP803, DLDO3, "dldo3", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
+	AXP_DESC(AXP803, DLDO4, "dldo4", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO4_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(6)),
+	AXP_DESC(AXP803, ELDO1, "eldo1", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(0)),
+	AXP_DESC(AXP803, ELDO2, "eldo2", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
+	AXP_DESC(AXP803, ELDO3, "eldo3", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
+	AXP_DESC(AXP803, FLDO1, "fldo1", "fldoin", 700, 1450, 50,
+		 AXP803_FLDO1_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(2)),
+	AXP_DESC(AXP803, FLDO2, "fldo2", "fldoin", 700, 1450, 50,
+		 AXP803_FLDO2_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(3)),
+	AXP_DESC(AXP803, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
+		 AXP803_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(0)),
+	AXP_DESC_RANGES(AXP803, DCDC2, "dcdc2", "vin2", axp803_dcdc2_4_ranges,
+			76, AXP803_DCDC2_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(1)),
+	AXP_DESC_RANGES(AXP803, DCDC3, "dcdc3", "vin3", axp803_dcdc2_4_ranges,
+			76, AXP803_DCDC3_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(2)),
+	AXP_DESC_RANGES(AXP803, DCDC4, "dcdc4", "vin4", axp803_dcdc2_4_ranges,
+			76, AXP803_DCDC4_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(3)),
+	AXP_DESC_RANGES(AXP803, DCDC5, "dcdc5", "vin5", axp803_dcdc5_ranges,
+			69, AXP803_DCDC5_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(4)),
+	AXP_DESC_RANGES(AXP803, DCDC6, "dcdc6", "vin6", axp803_dcdc6_ranges,
+			72, AXP803_DCDC6_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(5)),
+	AXP_DESC(AXP803, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(5)),
+	AXP_DESC(AXP803, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(6)),
+	AXP_DESC(AXP803, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(7)),
+	AXP_DESC_IO(AXP803, LDO_IO0, "ldo_io0", "ips", 700, 3300, 100,
+		    AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
+		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
+	AXP_DESC_IO(AXP803, LDO_IO1, "ldo_io1", "ips", 700, 3300, 100,
+		    AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
+		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
+	AXP_DESC_FIXED(AXP803, RTC_LDO, "rtc_ldo", "ips", 1800),
+	/* secondary switchable output of DCDC1 */
+	AXP_DESC_SW(AXP803, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2,
+		    BIT(7)),
+};
+
+static const struct regmap_range axp803_writeable_ranges[] = {
+	regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
+	regmap_reg_range(AXP20X_DCDC_MODE, AXP22X_BATLOW_THRES1),
+};
+
+static const struct regmap_range axp803_volatile_ranges[] = {
+	regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_PWR_OP_MODE),
+	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
+	regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
+	regmap_reg_range(AXP20X_FG_RES, AXP20X_FG_RES),
+};
+
+static const struct regmap_access_table axp803_writeable_table = {
+	.yes_ranges	= axp803_writeable_ranges,
+	.n_yes_ranges	= ARRAY_SIZE(axp803_writeable_ranges),
+};
+
+static const struct regmap_access_table axp803_volatile_table = {
+	.yes_ranges	= axp803_volatile_ranges,
+	.n_yes_ranges	= ARRAY_SIZE(axp803_volatile_ranges),
+};
+
+static const struct regmap_config axp803_regmap_config = {
+	.reg_bits	= 8,
+	.val_bits	= 8,
+	.wr_table	= &axp803_writeable_table,
+	.volatile_table	= &axp803_volatile_table,
+	.max_register	= AXP22X_BATLOW_THRES1,
+	.cache_type	= REGCACHE_RBTREE,
+};
+
+#define INIT_REGMAP_IRQ(_irq, _off, _bit)			\
+	[AXP809_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_bit) }
+
+static const struct regmap_irq axp803_regmap_irqs[] = {
+	INIT_REGMAP_IRQ(PEK_RIS_EDGE,	        4, 6),
+	INIT_REGMAP_IRQ(PEK_FAL_EDGE,	        4, 5),
+	INIT_REGMAP_IRQ(PEK_SHORT,		4, 4),
+	INIT_REGMAP_IRQ(PEK_LONG,		4, 3),
+	INIT_REGMAP_IRQ(PEK_OVER_OFF,		4, 2),
+	INIT_REGMAP_IRQ(GPIO1_INPUT,		4, 1),
+	INIT_REGMAP_IRQ(GPIO0_INPUT,		4, 0),
+};
+
+static const struct regmap_irq_chip axp803_regmap_irq_chip = {
+	.name			= "axp803",
+	.status_base		= AXP20X_IRQ1_STATE,
+	.ack_base		= AXP20X_IRQ1_STATE,
+	.mask_base		= AXP20X_IRQ1_EN,
+	.mask_invert		= true,
+	.init_ack_masked	= true,
+	.irqs			= axp803_regmap_irqs,
+	.num_irqs		= ARRAY_SIZE(axp803_regmap_irqs),
+	.num_regs		= 6,
+};
+
+static const struct axp_cfg axp803_cfg = {
+	.regulators = axp803_regulators,
+	.nregulators= ARRAY_SIZE(axp803_regulators),
+	.dcdc1_ix = AXP803_DCDC1,
+	.dcdc5_ix = -1,
+	.dc1sw_ix = AXP803_DC1SW,
+	.dc5ldo_ix = -1,
+};
+
+static struct axp20x_dev axp803_dev = {
+	.regmap_cfg = &axp803_regmap_config,
+	.regmap_irq_chip = &axp803_regmap_irq_chip,
+};
+
+static int axp803_rsb_probe(struct sunxi_rsb_device *rdev)
+{
+	return axp_rsb_probe(rdev, &axp803_dev, &axp803_cfg);
+}
+
+static const struct of_device_id axp803_of_match[] = {
+	{ .compatible = "x-powers,axp803", .data = (void *) AXP803_ID },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, axp803_of_match);
+
+static struct sunxi_rsb_driver axp803_rsb_driver = {
+	.driver = {
+		.name	= "axp803-rsb",
+		.of_match_table	= of_match_ptr(axp803_of_match),
+	},
+	.probe	= axp803_rsb_probe,
+	.remove	= axp_rsb_remove,
+};
+module_sunxi_rsb_driver(axp803_rsb_driver);
+
+MODULE_DESCRIPTION("AXP803 RSB driver");
+MODULE_AUTHOR("Jean-Francois Moine <moinejf-GANU6spQydw@public.gmane.org>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
index fec597f..9c5fb00 100644
--- a/include/linux/mfd/axp20x.h
+++ b/include/linux/mfd/axp20x.h
@@ -20,6 +20,7 @@ enum {
 	AXP221_ID,
 	AXP223_ID,
 	AXP288_ID,
+	AXP803_ID,
 	AXP806_ID,
 	AXP809_ID,
 	NR_AXP20X_VARIANTS,
-- 
2.10.0

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 3/4] regulator: axp20x: add the AXP803
@ 2016-09-23  7:00   ` Jean-Francois Moine
  0 siblings, 0 replies; 27+ messages in thread
From: Jean-Francois Moine @ 2016-09-23  7:00 UTC (permalink / raw)
  To: linux-arm-kernel

The X-Powers AXP803 PMIC is close to the AXP809 with more outputs.
It is used in some Allwinner boards as the Sinovoip BananaPi M64
and the Pine A64.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
not tested
---
 Documentation/devicetree/bindings/mfd/axp20x.txt |  32 +++-
 drivers/mfd/axp20x.c                             |  13 ++
 drivers/regulator/Makefile                       |   3 +-
 drivers/regulator/axp803.c                       | 225 +++++++++++++++++++++++
 include/linux/mfd/axp20x.h                       |   1 +
 5 files changed, 271 insertions(+), 3 deletions(-)
 create mode 100644 drivers/regulator/axp803.c

diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
index 8f3ad9a..3332d02 100644
--- a/Documentation/devicetree/bindings/mfd/axp20x.txt
+++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
@@ -6,12 +6,13 @@ axp202 (X-Powers)
 axp209 (X-Powers)
 axp221 (X-Powers)
 axp223 (X-Powers)
+axp803 (X-Powers)
 axp809 (X-Powers)
 
 Required properties:
 - compatible: "x-powers,axp152", "x-powers,axp202", "x-powers,axp209",
-	      "x-powers,axp221", "x-powers,axp223", "x-powers,axp806",
-	      "x-powers,axp809"
+	      "x-powers,axp221", "x-powers,axp223", "x-powers,axp803",
+	      "x-powers,axp806", "x-powers,axp809"
 - reg: The I2C slave address or RSB hardware address for the AXP chip
 - interrupt-parent: The parent interrupt controller
 - interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
@@ -86,6 +87,33 @@ LDO_IO1		: LDO		: ips-supply		: GPIO 1
 RTC_LDO		: LDO		: ips-supply		: always on
 DRIVEVBUS	: Enable output	: drivevbus-supply	: external regulator
 
+AXP803 regulators, type, and corresponding input supply names:
+
+Regulator	  Type		  Supply Name		  Notes
+---------	  ----		  -----------		  -----
+DCDC1		: DC-DC buck	: vin1-supply
+DCDC2		: DC-DC buck	: vin2-supply
+DCDC3		: DC-DC	buck	: vin3-supply
+DCDC4		: DC-DC	buck	: vin4-supply
+DCDC5		: DC-DC	buck	: vin5-supply
+DCDC6		: DC-DC	buck	: vin6-supply
+ALDO1		: LDO		: aldoin-supply	: shared supply
+ALDO2		: LDO		: aldoin-supply	: shared supply
+ALDO3		: LDO		: aldoin-supply	: shared supply
+DLDO1		: LDO		: dldoin-supply	: shared supply
+DLDO2		: LDO		: dldoin-supply	: shared supply
+DLDO3		: LDO		: dldoin-supply	: shared supply
+DLDO4		: LDO		: dldoin-supply	: shared supply
+ELDO1		: LDO		: eldoin-supply	: shared supply
+ELDO2		: LDO		: eldoin-supply	: shared supply
+ELDO3		: LDO		: eldoin-supply	: shared supply
+FLDO1		: LDO		: fldoin-supply	: shared supply
+FLDO2		: LDO		: fldoin-supply	: shared supply
+RTC_LDO		: LDO		: ips-supply	: always on
+LDO_IO0		: LDO		: ips-supply	: GPIO 0
+LDO_IO1		: LDO		: ips-supply	: GPIO 1
+DC1SW		: On/Off Switch	:		: DCDC1 secondary output
+
 AXP806 regulators, type, and corresponding input supply names:
 
 Regulator	  Type		  Supply Name		  Notes
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index ba130be..7c90b12 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -38,6 +38,7 @@ static const char * const axp20x_model_names[] = {
 	"AXP221",
 	"AXP223",
 	"AXP288",
+	"AXP803",
 	"AXP806",
 	"AXP809",
 };
@@ -739,6 +740,14 @@ static struct mfd_cell axp809_cells[] = {
 	},
 };
 
+static struct mfd_cell axp803_cells[] = {
+	{
+		.name			= "axp20x-pek",
+		.num_resources		= ARRAY_SIZE(axp809_pek_resources),
+		.resources		= axp809_pek_resources,
+	},
+};
+
 static struct axp20x_dev *axp20x_pm_power_off;
 static void axp20x_power_off(void)
 {
@@ -801,6 +810,10 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
 		axp20x->regmap_cfg = &axp288_regmap_config;
 		axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
 		break;
+	case AXP803_ID:
+		axp20x->cells = axp803_cells;
+		axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
+		break;
 	case AXP806_ID:
 		axp20x->nr_cells = ARRAY_SIZE(axp806_cells);
 		axp20x->cells = axp806_cells;
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 225a026..2cbb280 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -21,7 +21,8 @@ obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
 obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
 obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
 obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
-obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o axp-regulator.o
+obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o axp-regulator.o \
+				axp803.o
 obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o
 obj-$(CONFIG_REGULATOR_DA903X)	+= da903x.o
 obj-$(CONFIG_REGULATOR_DA9052)	+= da9052-regulator.o
diff --git a/drivers/regulator/axp803.c b/drivers/regulator/axp803.c
new file mode 100644
index 0000000..bae83dd
--- /dev/null
+++ b/drivers/regulator/axp803.c
@@ -0,0 +1,225 @@
+/*
+ * AXP803 regulator driver
+ *
+ * Copyright (C) 2016 Jean-Francois Moine <moinejf@free.fr>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/axp20x.h>
+#include <linux/regulator/driver.h>
+#include <linux/sunxi-rsb.h>
+
+#include "axp-regulator.h"
+
+enum {
+	AXP803_DLDO1 = 0,
+	AXP803_DLDO2,
+	AXP803_DLDO3,
+	AXP803_DLDO4,
+	AXP803_ELDO1,
+	AXP803_ELDO2,
+	AXP803_ELDO3,
+	AXP803_FLDO1,
+	AXP803_FLDO2,
+	AXP803_DCDC1,
+	AXP803_DCDC2,
+	AXP803_DCDC3,
+	AXP803_DCDC4,
+	AXP803_DCDC5,
+	AXP803_DCDC6,
+	AXP803_ALDO1,
+	AXP803_ALDO2,
+	AXP803_ALDO3,
+	AXP803_LDO_IO0,
+	AXP803_LDO_IO1,
+	AXP803_RTC_LDO,
+	AXP803_DC1SW,
+};
+
+/* AXP803 registers */
+#define AXP803_FLDO1_V_OUT		0x1c
+#define AXP803_FLDO2_V_OUT		0x1d
+#define AXP803_DCDC1_V_OUT		0x20
+#define AXP803_DCDC2_V_OUT		0x21
+#define AXP803_DCDC3_V_OUT		0x22
+#define AXP803_DCDC4_V_OUT		0x23
+#define AXP803_DCDC5_V_OUT		0x24
+#define AXP803_DCDC6_V_OUT		0x25
+
+static const struct regulator_linear_range axp803_dldo2_ranges[] = {
+	REGULATOR_LINEAR_RANGE(700000, 0, 26, 100000),
+	REGULATOR_LINEAR_RANGE(3400000, 27, 31, 200000),
+};
+
+static const struct regulator_linear_range axp803_dcdc2_4_ranges[] = {
+	REGULATOR_LINEAR_RANGE(500000, 0, 71, 10000),
+	REGULATOR_LINEAR_RANGE(1220000, 72, 76, 20000),
+};
+
+static const struct regulator_linear_range axp803_dcdc5_ranges[] = {
+	REGULATOR_LINEAR_RANGE(800000, 0, 33, 10000),
+	REGULATOR_LINEAR_RANGE(1140000, 34, 69, 20000),
+};
+
+static const struct regulator_linear_range axp803_dcdc6_ranges[] = {
+	REGULATOR_LINEAR_RANGE(600000, 0, 51, 10000),
+	REGULATOR_LINEAR_RANGE(1120000, 52, 72, 20000),
+};
+
+static const struct regulator_desc axp803_regulators[] = {
+	AXP_DESC(AXP803, DLDO1, "dldo1", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(3)),
+	AXP_DESC_RANGES(AXP803, DLDO2, "dldo2", "dldoin", axp803_dldo2_ranges,
+			31, AXP22X_DLDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
+			BIT(4)),
+	AXP_DESC(AXP803, DLDO3, "dldo3", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
+	AXP_DESC(AXP803, DLDO4, "dldo4", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO4_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(6)),
+	AXP_DESC(AXP803, ELDO1, "eldo1", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(0)),
+	AXP_DESC(AXP803, ELDO2, "eldo2", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
+	AXP_DESC(AXP803, ELDO3, "eldo3", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
+	AXP_DESC(AXP803, FLDO1, "fldo1", "fldoin", 700, 1450, 50,
+		 AXP803_FLDO1_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(2)),
+	AXP_DESC(AXP803, FLDO2, "fldo2", "fldoin", 700, 1450, 50,
+		 AXP803_FLDO2_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(3)),
+	AXP_DESC(AXP803, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
+		 AXP803_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(0)),
+	AXP_DESC_RANGES(AXP803, DCDC2, "dcdc2", "vin2", axp803_dcdc2_4_ranges,
+			76, AXP803_DCDC2_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(1)),
+	AXP_DESC_RANGES(AXP803, DCDC3, "dcdc3", "vin3", axp803_dcdc2_4_ranges,
+			76, AXP803_DCDC3_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(2)),
+	AXP_DESC_RANGES(AXP803, DCDC4, "dcdc4", "vin4", axp803_dcdc2_4_ranges,
+			76, AXP803_DCDC4_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(3)),
+	AXP_DESC_RANGES(AXP803, DCDC5, "dcdc5", "vin5", axp803_dcdc5_ranges,
+			69, AXP803_DCDC5_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(4)),
+	AXP_DESC_RANGES(AXP803, DCDC6, "dcdc6", "vin6", axp803_dcdc6_ranges,
+			72, AXP803_DCDC6_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(5)),
+	AXP_DESC(AXP803, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(5)),
+	AXP_DESC(AXP803, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(6)),
+	AXP_DESC(AXP803, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(7)),
+	AXP_DESC_IO(AXP803, LDO_IO0, "ldo_io0", "ips", 700, 3300, 100,
+		    AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
+		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
+	AXP_DESC_IO(AXP803, LDO_IO1, "ldo_io1", "ips", 700, 3300, 100,
+		    AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
+		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
+	AXP_DESC_FIXED(AXP803, RTC_LDO, "rtc_ldo", "ips", 1800),
+	/* secondary switchable output of DCDC1 */
+	AXP_DESC_SW(AXP803, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2,
+		    BIT(7)),
+};
+
+static const struct regmap_range axp803_writeable_ranges[] = {
+	regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
+	regmap_reg_range(AXP20X_DCDC_MODE, AXP22X_BATLOW_THRES1),
+};
+
+static const struct regmap_range axp803_volatile_ranges[] = {
+	regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_PWR_OP_MODE),
+	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
+	regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
+	regmap_reg_range(AXP20X_FG_RES, AXP20X_FG_RES),
+};
+
+static const struct regmap_access_table axp803_writeable_table = {
+	.yes_ranges	= axp803_writeable_ranges,
+	.n_yes_ranges	= ARRAY_SIZE(axp803_writeable_ranges),
+};
+
+static const struct regmap_access_table axp803_volatile_table = {
+	.yes_ranges	= axp803_volatile_ranges,
+	.n_yes_ranges	= ARRAY_SIZE(axp803_volatile_ranges),
+};
+
+static const struct regmap_config axp803_regmap_config = {
+	.reg_bits	= 8,
+	.val_bits	= 8,
+	.wr_table	= &axp803_writeable_table,
+	.volatile_table	= &axp803_volatile_table,
+	.max_register	= AXP22X_BATLOW_THRES1,
+	.cache_type	= REGCACHE_RBTREE,
+};
+
+#define INIT_REGMAP_IRQ(_irq, _off, _bit)			\
+	[AXP809_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_bit) }
+
+static const struct regmap_irq axp803_regmap_irqs[] = {
+	INIT_REGMAP_IRQ(PEK_RIS_EDGE,	        4, 6),
+	INIT_REGMAP_IRQ(PEK_FAL_EDGE,	        4, 5),
+	INIT_REGMAP_IRQ(PEK_SHORT,		4, 4),
+	INIT_REGMAP_IRQ(PEK_LONG,		4, 3),
+	INIT_REGMAP_IRQ(PEK_OVER_OFF,		4, 2),
+	INIT_REGMAP_IRQ(GPIO1_INPUT,		4, 1),
+	INIT_REGMAP_IRQ(GPIO0_INPUT,		4, 0),
+};
+
+static const struct regmap_irq_chip axp803_regmap_irq_chip = {
+	.name			= "axp803",
+	.status_base		= AXP20X_IRQ1_STATE,
+	.ack_base		= AXP20X_IRQ1_STATE,
+	.mask_base		= AXP20X_IRQ1_EN,
+	.mask_invert		= true,
+	.init_ack_masked	= true,
+	.irqs			= axp803_regmap_irqs,
+	.num_irqs		= ARRAY_SIZE(axp803_regmap_irqs),
+	.num_regs		= 6,
+};
+
+static const struct axp_cfg axp803_cfg = {
+	.regulators = axp803_regulators,
+	.nregulators= ARRAY_SIZE(axp803_regulators),
+	.dcdc1_ix = AXP803_DCDC1,
+	.dcdc5_ix = -1,
+	.dc1sw_ix = AXP803_DC1SW,
+	.dc5ldo_ix = -1,
+};
+
+static struct axp20x_dev axp803_dev = {
+	.regmap_cfg = &axp803_regmap_config,
+	.regmap_irq_chip = &axp803_regmap_irq_chip,
+};
+
+static int axp803_rsb_probe(struct sunxi_rsb_device *rdev)
+{
+	return axp_rsb_probe(rdev, &axp803_dev, &axp803_cfg);
+}
+
+static const struct of_device_id axp803_of_match[] = {
+	{ .compatible = "x-powers,axp803", .data = (void *) AXP803_ID },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, axp803_of_match);
+
+static struct sunxi_rsb_driver axp803_rsb_driver = {
+	.driver = {
+		.name	= "axp803-rsb",
+		.of_match_table	= of_match_ptr(axp803_of_match),
+	},
+	.probe	= axp803_rsb_probe,
+	.remove	= axp_rsb_remove,
+};
+module_sunxi_rsb_driver(axp803_rsb_driver);
+
+MODULE_DESCRIPTION("AXP803 RSB driver");
+MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
index fec597f..9c5fb00 100644
--- a/include/linux/mfd/axp20x.h
+++ b/include/linux/mfd/axp20x.h
@@ -20,6 +20,7 @@ enum {
 	AXP221_ID,
 	AXP223_ID,
 	AXP288_ID,
+	AXP803_ID,
 	AXP806_ID,
 	AXP809_ID,
 	NR_AXP20X_VARIANTS,
-- 
2.10.0

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 4/4] regulator: axp20x: add the AXP813
@ 2016-09-23  7:22   ` Jean-Francois Moine
  0 siblings, 0 replies; 27+ messages in thread
From: Jean-Francois Moine @ 2016-09-23  7:22 UTC (permalink / raw)
  To: Chen-Yu Tsai, Mark Rutland, Rob Herring
  Cc: devicetree, linux-arm-kernel, linux-kernel, linux-sunxi

The X-Powers AXP813 PMIC is close to the AXP803.
It is used in some Allwinner boards as the Sinovoip BananaPi M3+.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
 Documentation/devicetree/bindings/mfd/axp20x.txt |   9 +-
 drivers/mfd/axp20x.c                             |   2 +
 drivers/regulator/Makefile                       |   2 +-
 drivers/regulator/axp813.c                       | 229 +++++++++++++++++++++++
 include/linux/mfd/axp20x.h                       |   1 +
 5 files changed, 239 insertions(+), 4 deletions(-)
 create mode 100644 drivers/regulator/axp813.c

diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
index 3332d02..62019fb 100644
--- a/Documentation/devicetree/bindings/mfd/axp20x.txt
+++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
@@ -8,11 +8,12 @@ axp221 (X-Powers)
 axp223 (X-Powers)
 axp803 (X-Powers)
 axp809 (X-Powers)
+axp813 (X-Powers)
 
 Required properties:
 - compatible: "x-powers,axp152", "x-powers,axp202", "x-powers,axp209",
 	      "x-powers,axp221", "x-powers,axp223", "x-powers,axp803",
-	      "x-powers,axp806", "x-powers,axp809"
+	      "x-powers,axp806", "x-powers,axp809", "x-powers,axp813"
 - reg: The I2C slave address or RSB hardware address for the AXP chip
 - interrupt-parent: The parent interrupt controller
 - interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
@@ -87,7 +88,7 @@ LDO_IO1		: LDO		: ips-supply		: GPIO 1
 RTC_LDO		: LDO		: ips-supply		: always on
 DRIVEVBUS	: Enable output	: drivevbus-supply	: external regulator
 
-AXP803 regulators, type, and corresponding input supply names:
+AXP803/AXP813 regulators, type, and corresponding input supply names:
 
 Regulator	  Type		  Supply Name		  Notes
 ---------	  ----		  -----------		  -----
@@ -97,6 +98,7 @@ DCDC3		: DC-DC	buck	: vin3-supply
 DCDC4		: DC-DC	buck	: vin4-supply
 DCDC5		: DC-DC	buck	: vin5-supply
 DCDC6		: DC-DC	buck	: vin6-supply
+DCDC7		: DC-DC	buck	: vin7-supply	: (813 only)
 ALDO1		: LDO		: aldoin-supply	: shared supply
 ALDO2		: LDO		: aldoin-supply	: shared supply
 ALDO3		: LDO		: aldoin-supply	: shared supply
@@ -109,10 +111,11 @@ ELDO2		: LDO		: eldoin-supply	: shared supply
 ELDO3		: LDO		: eldoin-supply	: shared supply
 FLDO1		: LDO		: fldoin-supply	: shared supply
 FLDO2		: LDO		: fldoin-supply	: shared supply
+FLDO3		: LDO		: fldoin-supply	: shared supply (813 only)
 RTC_LDO		: LDO		: ips-supply	: always on
 LDO_IO0		: LDO		: ips-supply	: GPIO 0
 LDO_IO1		: LDO		: ips-supply	: GPIO 1
-DC1SW		: On/Off Switch	:		: DCDC1 secondary output
+DC1SW		: On/Off Switch	:		: DCDC1 secondary output (803 only)
 
 AXP806 regulators, type, and corresponding input supply names:
 
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index 7c90b12..4f2303d 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -41,6 +41,7 @@ static const char * const axp20x_model_names[] = {
 	"AXP803",
 	"AXP806",
 	"AXP809",
+	"AXP813",
 };
 
 static const struct regmap_range axp152_writeable_ranges[] = {
@@ -811,6 +812,7 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
 		axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
 		break;
 	case AXP803_ID:
+	case AXP813_ID:
 		axp20x->cells = axp803_cells;
 		axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
 		break;
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 2cbb280..a678ba6 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -22,7 +22,7 @@ obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
 obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
 obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
 obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o axp-regulator.o \
-				axp803.o
+				axp803.o axp813.o
 obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o
 obj-$(CONFIG_REGULATOR_DA903X)	+= da903x.o
 obj-$(CONFIG_REGULATOR_DA9052)	+= da9052-regulator.o
diff --git a/drivers/regulator/axp813.c b/drivers/regulator/axp813.c
new file mode 100644
index 0000000..99bfaaa
--- /dev/null
+++ b/drivers/regulator/axp813.c
@@ -0,0 +1,229 @@
+/*
+ * AXP813 regulator driver
+ *
+ * Copyright (C) 2016 Jean-Francois Moine <moinejf@free.fr>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/axp20x.h>
+#include <linux/regulator/driver.h>
+#include <linux/sunxi-rsb.h>
+
+#include "axp-regulator.h"
+
+enum {
+	AXP813_DLDO1 = 0,
+	AXP813_DLDO2,
+	AXP813_DLDO3,
+	AXP813_DLDO4,
+	AXP813_ELDO1,
+	AXP813_ELDO2,
+	AXP813_ELDO3,
+	AXP813_FLDO1,
+	AXP813_FLDO2,
+	AXP813_FLDO3,
+	AXP813_DCDC1,
+	AXP813_DCDC2,
+	AXP813_DCDC3,
+	AXP813_DCDC4,
+	AXP813_DCDC5,
+	AXP813_DCDC6,
+	AXP813_DCDC7,
+	AXP813_ALDO1,
+	AXP813_ALDO2,
+	AXP813_ALDO3,
+	AXP813_LDO_IO0,
+	AXP813_LDO_IO1,
+	AXP813_RTC_LDO,
+};
+
+/* AXP813 registers */
+#define AXP813_FLDO1_V_OUT		0x1c
+#define AXP813_FLDO2_V_OUT		0x1d
+#define AXP813_DCDC1_V_OUT		0x20
+#define AXP813_DCDC2_V_OUT		0x21
+#define AXP813_DCDC3_V_OUT		0x22
+#define AXP813_DCDC4_V_OUT		0x23
+#define AXP813_DCDC5_V_OUT		0x24
+#define AXP813_DCDC6_V_OUT		0x25
+#define AXP813_DCDC7_V_OUT		0x26
+
+static const struct regulator_linear_range axp813_dcdc2_4_ranges[] = {
+	REGULATOR_LINEAR_RANGE(500000, 0, 71, 10000),
+	REGULATOR_LINEAR_RANGE(1220000, 72, 76, 20000),
+};
+
+static const struct regulator_linear_range axp813_dcdc5_ranges[] = {
+	REGULATOR_LINEAR_RANGE(800000, 0, 33, 10000),
+	REGULATOR_LINEAR_RANGE(1140000, 34, 69, 20000),
+};
+
+static const struct regulator_linear_range axp813_dcdc6_7_ranges[] = {
+	REGULATOR_LINEAR_RANGE(600000, 0, 51, 10000),
+	REGULATOR_LINEAR_RANGE(1120000, 52, 72, 20000),
+};
+
+static const struct regulator_linear_range axp813_dldo2_ranges[] = {
+	REGULATOR_LINEAR_RANGE(700000, 0, 26, 100000),
+	REGULATOR_LINEAR_RANGE(3400000, 27, 31, 200000),
+};
+
+static const struct regulator_desc axp813_regulators[] = {
+	AXP_DESC(AXP813, DLDO1, "dldo1", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(3)),
+	AXP_DESC_RANGES(AXP813, DLDO2, "dldo2", "dldoin", axp813_dldo2_ranges,
+			31, AXP22X_DLDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
+			BIT(4)),
+	AXP_DESC(AXP813, DLDO3, "dldo3", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
+	AXP_DESC(AXP813, DLDO4, "dldo4", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO4_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(6)),
+	AXP_DESC(AXP813, ELDO1, "eldo1", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(0)),
+	AXP_DESC(AXP813, ELDO2, "eldo2", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
+	AXP_DESC(AXP813, ELDO3, "eldo3", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
+	AXP_DESC(AXP813, FLDO1, "fldo1", "fldoin", 700, 1450, 50,
+		 AXP813_FLDO1_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(2)),
+	AXP_DESC(AXP813, FLDO2, "fldo2", "fldoin", 700, 1450, 50,
+		 AXP813_FLDO2_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(3)),
+/*	FLDO3 not described (output = DCDC5/2 or FLDOIN/2 */
+	AXP_DESC(AXP813, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
+		 AXP813_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(0)),
+	AXP_DESC_RANGES(AXP813, DCDC2, "dcdc2", "vin2", axp813_dcdc2_4_ranges,
+			76, AXP813_DCDC2_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(1)),
+	AXP_DESC_RANGES(AXP813, DCDC3, "dcdc3", "vin3", axp813_dcdc2_4_ranges,
+			76, AXP813_DCDC3_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(2)),
+	AXP_DESC_RANGES(AXP813, DCDC4, "dcdc4", "vin4", axp813_dcdc2_4_ranges,
+			76, AXP813_DCDC4_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(3)),
+	AXP_DESC_RANGES(AXP813, DCDC5, "dcdc5", "vin5", axp813_dcdc5_ranges,
+			69, AXP813_DCDC5_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(4)),
+	AXP_DESC_RANGES(AXP813, DCDC6, "dcdc6", "vin6", axp813_dcdc6_7_ranges,
+			72, AXP813_DCDC6_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(5)),
+	AXP_DESC_RANGES(AXP813, DCDC7, "dcdc7", "vin7", axp813_dcdc6_7_ranges,
+			72, AXP813_DCDC7_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(6)),
+	AXP_DESC(AXP813, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(5)),
+	AXP_DESC(AXP813, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(6)),
+	AXP_DESC(AXP813, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(7)),
+	AXP_DESC_IO(AXP813, LDO_IO0, "ldo_io0", "ips", 700, 3300, 100,
+		    AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
+		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
+	AXP_DESC_IO(AXP813, LDO_IO1, "ldo_io1", "ips", 700, 3300, 100,
+		    AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
+		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
+	AXP_DESC_FIXED(AXP813, RTC_LDO, "rtc_ldo", "ips", 1800),
+};
+
+static const struct regmap_range axp813_writeable_ranges[] = {
+	regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
+	regmap_reg_range(AXP20X_DCDC_MODE, AXP22X_BATLOW_THRES1),
+};
+
+static const struct regmap_range axp813_volatile_ranges[] = {
+	regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_PWR_OP_MODE),
+	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
+	regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
+	regmap_reg_range(AXP20X_FG_RES, AXP20X_FG_RES),
+};
+
+static const struct regmap_access_table axp813_writeable_table = {
+	.yes_ranges	= axp813_writeable_ranges,
+	.n_yes_ranges	= ARRAY_SIZE(axp813_writeable_ranges),
+};
+
+static const struct regmap_access_table axp813_volatile_table = {
+	.yes_ranges	= axp813_volatile_ranges,
+	.n_yes_ranges	= ARRAY_SIZE(axp813_volatile_ranges),
+};
+
+static const struct regmap_config axp813_regmap_config = {
+	.reg_bits	= 8,
+	.val_bits	= 8,
+	.wr_table	= &axp813_writeable_table,
+	.volatile_table	= &axp813_volatile_table,
+	.max_register	= AXP22X_BATLOW_THRES1,
+	.cache_type	= REGCACHE_RBTREE,
+};
+
+#define INIT_REGMAP_IRQ(_irq, _off, _bit)			\
+	[AXP809_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_bit) }
+
+static const struct regmap_irq axp813_regmap_irqs[] = {
+	INIT_REGMAP_IRQ(PEK_RIS_EDGE,	        4, 6),
+	INIT_REGMAP_IRQ(PEK_FAL_EDGE,	        4, 5),
+	INIT_REGMAP_IRQ(PEK_SHORT,		4, 4),
+	INIT_REGMAP_IRQ(PEK_LONG,		4, 3),
+	INIT_REGMAP_IRQ(PEK_OVER_OFF,		4, 2),
+	INIT_REGMAP_IRQ(GPIO1_INPUT,		4, 1),
+	INIT_REGMAP_IRQ(GPIO0_INPUT,		4, 0),
+};
+
+static const struct regmap_irq_chip axp813_regmap_irq_chip = {
+	.name			= "axp813",
+	.status_base		= AXP20X_IRQ1_STATE,
+	.ack_base		= AXP20X_IRQ1_STATE,
+	.mask_base		= AXP20X_IRQ1_EN,
+	.mask_invert		= true,
+	.init_ack_masked	= true,
+	.irqs			= axp813_regmap_irqs,
+	.num_irqs		= ARRAY_SIZE(axp813_regmap_irqs),
+	.num_regs		= 6,
+};
+
+static const struct axp_cfg axp813_cfg = {
+	.regulators = axp813_regulators,
+	.nregulators= ARRAY_SIZE(axp813_regulators),
+	.dcdc1_ix = -1,
+	.dcdc5_ix = -1,
+	.dc1sw_ix = -1,
+	.dc5ldo_ix = -1,
+	.skip_bitmap = 1 << AXP813_FLDO3,
+};
+
+static struct axp20x_dev axp813_dev = {
+	.regmap_cfg = &axp813_regmap_config,
+	.regmap_irq_chip = &axp813_regmap_irq_chip,
+};
+
+static int axp813_rsb_probe(struct sunxi_rsb_device *rdev)
+{
+	return axp_rsb_probe(rdev, &axp813_dev, &axp813_cfg);
+}
+
+static const struct of_device_id axp813_of_match[] = {
+	{ .compatible = "x-powers,axp813", .data = (void *) AXP813_ID },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, axp813_of_match);
+
+static struct sunxi_rsb_driver axp813_rsb_driver = {
+	.driver = {
+		.name	= "axp813-rsb",
+		.of_match_table	= of_match_ptr(axp813_of_match),
+	},
+	.probe	= axp813_rsb_probe,
+	.remove	= axp_rsb_remove,
+};
+module_sunxi_rsb_driver(axp813_rsb_driver);
+
+MODULE_DESCRIPTION("AXP813 RSB driver");
+MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
index 9c5fb00..90296f0 100644
--- a/include/linux/mfd/axp20x.h
+++ b/include/linux/mfd/axp20x.h
@@ -23,6 +23,7 @@ enum {
 	AXP803_ID,
 	AXP806_ID,
 	AXP809_ID,
+	AXP813_ID,
 	NR_AXP20X_VARIANTS,
 };
 
-- 
2.10.0

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 4/4] regulator: axp20x: add the AXP813
@ 2016-09-23  7:22   ` Jean-Francois Moine
  0 siblings, 0 replies; 27+ messages in thread
From: Jean-Francois Moine @ 2016-09-23  7:22 UTC (permalink / raw)
  To: Chen-Yu Tsai, Mark Rutland, Rob Herring
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw

The X-Powers AXP813 PMIC is close to the AXP803.
It is used in some Allwinner boards as the Sinovoip BananaPi M3+.

Signed-off-by: Jean-Francois Moine <moinejf-GANU6spQydw@public.gmane.org>
---
 Documentation/devicetree/bindings/mfd/axp20x.txt |   9 +-
 drivers/mfd/axp20x.c                             |   2 +
 drivers/regulator/Makefile                       |   2 +-
 drivers/regulator/axp813.c                       | 229 +++++++++++++++++++++++
 include/linux/mfd/axp20x.h                       |   1 +
 5 files changed, 239 insertions(+), 4 deletions(-)
 create mode 100644 drivers/regulator/axp813.c

diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
index 3332d02..62019fb 100644
--- a/Documentation/devicetree/bindings/mfd/axp20x.txt
+++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
@@ -8,11 +8,12 @@ axp221 (X-Powers)
 axp223 (X-Powers)
 axp803 (X-Powers)
 axp809 (X-Powers)
+axp813 (X-Powers)
 
 Required properties:
 - compatible: "x-powers,axp152", "x-powers,axp202", "x-powers,axp209",
 	      "x-powers,axp221", "x-powers,axp223", "x-powers,axp803",
-	      "x-powers,axp806", "x-powers,axp809"
+	      "x-powers,axp806", "x-powers,axp809", "x-powers,axp813"
 - reg: The I2C slave address or RSB hardware address for the AXP chip
 - interrupt-parent: The parent interrupt controller
 - interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
@@ -87,7 +88,7 @@ LDO_IO1		: LDO		: ips-supply		: GPIO 1
 RTC_LDO		: LDO		: ips-supply		: always on
 DRIVEVBUS	: Enable output	: drivevbus-supply	: external regulator
 
-AXP803 regulators, type, and corresponding input supply names:
+AXP803/AXP813 regulators, type, and corresponding input supply names:
 
 Regulator	  Type		  Supply Name		  Notes
 ---------	  ----		  -----------		  -----
@@ -97,6 +98,7 @@ DCDC3		: DC-DC	buck	: vin3-supply
 DCDC4		: DC-DC	buck	: vin4-supply
 DCDC5		: DC-DC	buck	: vin5-supply
 DCDC6		: DC-DC	buck	: vin6-supply
+DCDC7		: DC-DC	buck	: vin7-supply	: (813 only)
 ALDO1		: LDO		: aldoin-supply	: shared supply
 ALDO2		: LDO		: aldoin-supply	: shared supply
 ALDO3		: LDO		: aldoin-supply	: shared supply
@@ -109,10 +111,11 @@ ELDO2		: LDO		: eldoin-supply	: shared supply
 ELDO3		: LDO		: eldoin-supply	: shared supply
 FLDO1		: LDO		: fldoin-supply	: shared supply
 FLDO2		: LDO		: fldoin-supply	: shared supply
+FLDO3		: LDO		: fldoin-supply	: shared supply (813 only)
 RTC_LDO		: LDO		: ips-supply	: always on
 LDO_IO0		: LDO		: ips-supply	: GPIO 0
 LDO_IO1		: LDO		: ips-supply	: GPIO 1
-DC1SW		: On/Off Switch	:		: DCDC1 secondary output
+DC1SW		: On/Off Switch	:		: DCDC1 secondary output (803 only)
 
 AXP806 regulators, type, and corresponding input supply names:
 
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index 7c90b12..4f2303d 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -41,6 +41,7 @@ static const char * const axp20x_model_names[] = {
 	"AXP803",
 	"AXP806",
 	"AXP809",
+	"AXP813",
 };
 
 static const struct regmap_range axp152_writeable_ranges[] = {
@@ -811,6 +812,7 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
 		axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
 		break;
 	case AXP803_ID:
+	case AXP813_ID:
 		axp20x->cells = axp803_cells;
 		axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
 		break;
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 2cbb280..a678ba6 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -22,7 +22,7 @@ obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
 obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
 obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
 obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o axp-regulator.o \
-				axp803.o
+				axp803.o axp813.o
 obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o
 obj-$(CONFIG_REGULATOR_DA903X)	+= da903x.o
 obj-$(CONFIG_REGULATOR_DA9052)	+= da9052-regulator.o
diff --git a/drivers/regulator/axp813.c b/drivers/regulator/axp813.c
new file mode 100644
index 0000000..99bfaaa
--- /dev/null
+++ b/drivers/regulator/axp813.c
@@ -0,0 +1,229 @@
+/*
+ * AXP813 regulator driver
+ *
+ * Copyright (C) 2016 Jean-Francois Moine <moinejf-GANU6spQydw@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/axp20x.h>
+#include <linux/regulator/driver.h>
+#include <linux/sunxi-rsb.h>
+
+#include "axp-regulator.h"
+
+enum {
+	AXP813_DLDO1 = 0,
+	AXP813_DLDO2,
+	AXP813_DLDO3,
+	AXP813_DLDO4,
+	AXP813_ELDO1,
+	AXP813_ELDO2,
+	AXP813_ELDO3,
+	AXP813_FLDO1,
+	AXP813_FLDO2,
+	AXP813_FLDO3,
+	AXP813_DCDC1,
+	AXP813_DCDC2,
+	AXP813_DCDC3,
+	AXP813_DCDC4,
+	AXP813_DCDC5,
+	AXP813_DCDC6,
+	AXP813_DCDC7,
+	AXP813_ALDO1,
+	AXP813_ALDO2,
+	AXP813_ALDO3,
+	AXP813_LDO_IO0,
+	AXP813_LDO_IO1,
+	AXP813_RTC_LDO,
+};
+
+/* AXP813 registers */
+#define AXP813_FLDO1_V_OUT		0x1c
+#define AXP813_FLDO2_V_OUT		0x1d
+#define AXP813_DCDC1_V_OUT		0x20
+#define AXP813_DCDC2_V_OUT		0x21
+#define AXP813_DCDC3_V_OUT		0x22
+#define AXP813_DCDC4_V_OUT		0x23
+#define AXP813_DCDC5_V_OUT		0x24
+#define AXP813_DCDC6_V_OUT		0x25
+#define AXP813_DCDC7_V_OUT		0x26
+
+static const struct regulator_linear_range axp813_dcdc2_4_ranges[] = {
+	REGULATOR_LINEAR_RANGE(500000, 0, 71, 10000),
+	REGULATOR_LINEAR_RANGE(1220000, 72, 76, 20000),
+};
+
+static const struct regulator_linear_range axp813_dcdc5_ranges[] = {
+	REGULATOR_LINEAR_RANGE(800000, 0, 33, 10000),
+	REGULATOR_LINEAR_RANGE(1140000, 34, 69, 20000),
+};
+
+static const struct regulator_linear_range axp813_dcdc6_7_ranges[] = {
+	REGULATOR_LINEAR_RANGE(600000, 0, 51, 10000),
+	REGULATOR_LINEAR_RANGE(1120000, 52, 72, 20000),
+};
+
+static const struct regulator_linear_range axp813_dldo2_ranges[] = {
+	REGULATOR_LINEAR_RANGE(700000, 0, 26, 100000),
+	REGULATOR_LINEAR_RANGE(3400000, 27, 31, 200000),
+};
+
+static const struct regulator_desc axp813_regulators[] = {
+	AXP_DESC(AXP813, DLDO1, "dldo1", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(3)),
+	AXP_DESC_RANGES(AXP813, DLDO2, "dldo2", "dldoin", axp813_dldo2_ranges,
+			31, AXP22X_DLDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
+			BIT(4)),
+	AXP_DESC(AXP813, DLDO3, "dldo3", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
+	AXP_DESC(AXP813, DLDO4, "dldo4", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO4_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(6)),
+	AXP_DESC(AXP813, ELDO1, "eldo1", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(0)),
+	AXP_DESC(AXP813, ELDO2, "eldo2", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
+	AXP_DESC(AXP813, ELDO3, "eldo3", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
+	AXP_DESC(AXP813, FLDO1, "fldo1", "fldoin", 700, 1450, 50,
+		 AXP813_FLDO1_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(2)),
+	AXP_DESC(AXP813, FLDO2, "fldo2", "fldoin", 700, 1450, 50,
+		 AXP813_FLDO2_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(3)),
+/*	FLDO3 not described (output = DCDC5/2 or FLDOIN/2 */
+	AXP_DESC(AXP813, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
+		 AXP813_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(0)),
+	AXP_DESC_RANGES(AXP813, DCDC2, "dcdc2", "vin2", axp813_dcdc2_4_ranges,
+			76, AXP813_DCDC2_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(1)),
+	AXP_DESC_RANGES(AXP813, DCDC3, "dcdc3", "vin3", axp813_dcdc2_4_ranges,
+			76, AXP813_DCDC3_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(2)),
+	AXP_DESC_RANGES(AXP813, DCDC4, "dcdc4", "vin4", axp813_dcdc2_4_ranges,
+			76, AXP813_DCDC4_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(3)),
+	AXP_DESC_RANGES(AXP813, DCDC5, "dcdc5", "vin5", axp813_dcdc5_ranges,
+			69, AXP813_DCDC5_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(4)),
+	AXP_DESC_RANGES(AXP813, DCDC6, "dcdc6", "vin6", axp813_dcdc6_7_ranges,
+			72, AXP813_DCDC6_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(5)),
+	AXP_DESC_RANGES(AXP813, DCDC7, "dcdc7", "vin7", axp813_dcdc6_7_ranges,
+			72, AXP813_DCDC7_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(6)),
+	AXP_DESC(AXP813, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(5)),
+	AXP_DESC(AXP813, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(6)),
+	AXP_DESC(AXP813, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(7)),
+	AXP_DESC_IO(AXP813, LDO_IO0, "ldo_io0", "ips", 700, 3300, 100,
+		    AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
+		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
+	AXP_DESC_IO(AXP813, LDO_IO1, "ldo_io1", "ips", 700, 3300, 100,
+		    AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
+		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
+	AXP_DESC_FIXED(AXP813, RTC_LDO, "rtc_ldo", "ips", 1800),
+};
+
+static const struct regmap_range axp813_writeable_ranges[] = {
+	regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
+	regmap_reg_range(AXP20X_DCDC_MODE, AXP22X_BATLOW_THRES1),
+};
+
+static const struct regmap_range axp813_volatile_ranges[] = {
+	regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_PWR_OP_MODE),
+	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
+	regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
+	regmap_reg_range(AXP20X_FG_RES, AXP20X_FG_RES),
+};
+
+static const struct regmap_access_table axp813_writeable_table = {
+	.yes_ranges	= axp813_writeable_ranges,
+	.n_yes_ranges	= ARRAY_SIZE(axp813_writeable_ranges),
+};
+
+static const struct regmap_access_table axp813_volatile_table = {
+	.yes_ranges	= axp813_volatile_ranges,
+	.n_yes_ranges	= ARRAY_SIZE(axp813_volatile_ranges),
+};
+
+static const struct regmap_config axp813_regmap_config = {
+	.reg_bits	= 8,
+	.val_bits	= 8,
+	.wr_table	= &axp813_writeable_table,
+	.volatile_table	= &axp813_volatile_table,
+	.max_register	= AXP22X_BATLOW_THRES1,
+	.cache_type	= REGCACHE_RBTREE,
+};
+
+#define INIT_REGMAP_IRQ(_irq, _off, _bit)			\
+	[AXP809_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_bit) }
+
+static const struct regmap_irq axp813_regmap_irqs[] = {
+	INIT_REGMAP_IRQ(PEK_RIS_EDGE,	        4, 6),
+	INIT_REGMAP_IRQ(PEK_FAL_EDGE,	        4, 5),
+	INIT_REGMAP_IRQ(PEK_SHORT,		4, 4),
+	INIT_REGMAP_IRQ(PEK_LONG,		4, 3),
+	INIT_REGMAP_IRQ(PEK_OVER_OFF,		4, 2),
+	INIT_REGMAP_IRQ(GPIO1_INPUT,		4, 1),
+	INIT_REGMAP_IRQ(GPIO0_INPUT,		4, 0),
+};
+
+static const struct regmap_irq_chip axp813_regmap_irq_chip = {
+	.name			= "axp813",
+	.status_base		= AXP20X_IRQ1_STATE,
+	.ack_base		= AXP20X_IRQ1_STATE,
+	.mask_base		= AXP20X_IRQ1_EN,
+	.mask_invert		= true,
+	.init_ack_masked	= true,
+	.irqs			= axp813_regmap_irqs,
+	.num_irqs		= ARRAY_SIZE(axp813_regmap_irqs),
+	.num_regs		= 6,
+};
+
+static const struct axp_cfg axp813_cfg = {
+	.regulators = axp813_regulators,
+	.nregulators= ARRAY_SIZE(axp813_regulators),
+	.dcdc1_ix = -1,
+	.dcdc5_ix = -1,
+	.dc1sw_ix = -1,
+	.dc5ldo_ix = -1,
+	.skip_bitmap = 1 << AXP813_FLDO3,
+};
+
+static struct axp20x_dev axp813_dev = {
+	.regmap_cfg = &axp813_regmap_config,
+	.regmap_irq_chip = &axp813_regmap_irq_chip,
+};
+
+static int axp813_rsb_probe(struct sunxi_rsb_device *rdev)
+{
+	return axp_rsb_probe(rdev, &axp813_dev, &axp813_cfg);
+}
+
+static const struct of_device_id axp813_of_match[] = {
+	{ .compatible = "x-powers,axp813", .data = (void *) AXP813_ID },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, axp813_of_match);
+
+static struct sunxi_rsb_driver axp813_rsb_driver = {
+	.driver = {
+		.name	= "axp813-rsb",
+		.of_match_table	= of_match_ptr(axp813_of_match),
+	},
+	.probe	= axp813_rsb_probe,
+	.remove	= axp_rsb_remove,
+};
+module_sunxi_rsb_driver(axp813_rsb_driver);
+
+MODULE_DESCRIPTION("AXP813 RSB driver");
+MODULE_AUTHOR("Jean-Francois Moine <moinejf-GANU6spQydw@public.gmane.org>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
index 9c5fb00..90296f0 100644
--- a/include/linux/mfd/axp20x.h
+++ b/include/linux/mfd/axp20x.h
@@ -23,6 +23,7 @@ enum {
 	AXP803_ID,
 	AXP806_ID,
 	AXP809_ID,
+	AXP813_ID,
 	NR_AXP20X_VARIANTS,
 };
 
-- 
2.10.0

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 4/4] regulator: axp20x: add the AXP813
@ 2016-09-23  7:22   ` Jean-Francois Moine
  0 siblings, 0 replies; 27+ messages in thread
From: Jean-Francois Moine @ 2016-09-23  7:22 UTC (permalink / raw)
  To: linux-arm-kernel

The X-Powers AXP813 PMIC is close to the AXP803.
It is used in some Allwinner boards as the Sinovoip BananaPi M3+.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
 Documentation/devicetree/bindings/mfd/axp20x.txt |   9 +-
 drivers/mfd/axp20x.c                             |   2 +
 drivers/regulator/Makefile                       |   2 +-
 drivers/regulator/axp813.c                       | 229 +++++++++++++++++++++++
 include/linux/mfd/axp20x.h                       |   1 +
 5 files changed, 239 insertions(+), 4 deletions(-)
 create mode 100644 drivers/regulator/axp813.c

diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
index 3332d02..62019fb 100644
--- a/Documentation/devicetree/bindings/mfd/axp20x.txt
+++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
@@ -8,11 +8,12 @@ axp221 (X-Powers)
 axp223 (X-Powers)
 axp803 (X-Powers)
 axp809 (X-Powers)
+axp813 (X-Powers)
 
 Required properties:
 - compatible: "x-powers,axp152", "x-powers,axp202", "x-powers,axp209",
 	      "x-powers,axp221", "x-powers,axp223", "x-powers,axp803",
-	      "x-powers,axp806", "x-powers,axp809"
+	      "x-powers,axp806", "x-powers,axp809", "x-powers,axp813"
 - reg: The I2C slave address or RSB hardware address for the AXP chip
 - interrupt-parent: The parent interrupt controller
 - interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
@@ -87,7 +88,7 @@ LDO_IO1		: LDO		: ips-supply		: GPIO 1
 RTC_LDO		: LDO		: ips-supply		: always on
 DRIVEVBUS	: Enable output	: drivevbus-supply	: external regulator
 
-AXP803 regulators, type, and corresponding input supply names:
+AXP803/AXP813 regulators, type, and corresponding input supply names:
 
 Regulator	  Type		  Supply Name		  Notes
 ---------	  ----		  -----------		  -----
@@ -97,6 +98,7 @@ DCDC3		: DC-DC	buck	: vin3-supply
 DCDC4		: DC-DC	buck	: vin4-supply
 DCDC5		: DC-DC	buck	: vin5-supply
 DCDC6		: DC-DC	buck	: vin6-supply
+DCDC7		: DC-DC	buck	: vin7-supply	: (813 only)
 ALDO1		: LDO		: aldoin-supply	: shared supply
 ALDO2		: LDO		: aldoin-supply	: shared supply
 ALDO3		: LDO		: aldoin-supply	: shared supply
@@ -109,10 +111,11 @@ ELDO2		: LDO		: eldoin-supply	: shared supply
 ELDO3		: LDO		: eldoin-supply	: shared supply
 FLDO1		: LDO		: fldoin-supply	: shared supply
 FLDO2		: LDO		: fldoin-supply	: shared supply
+FLDO3		: LDO		: fldoin-supply	: shared supply (813 only)
 RTC_LDO		: LDO		: ips-supply	: always on
 LDO_IO0		: LDO		: ips-supply	: GPIO 0
 LDO_IO1		: LDO		: ips-supply	: GPIO 1
-DC1SW		: On/Off Switch	:		: DCDC1 secondary output
+DC1SW		: On/Off Switch	:		: DCDC1 secondary output (803 only)
 
 AXP806 regulators, type, and corresponding input supply names:
 
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index 7c90b12..4f2303d 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -41,6 +41,7 @@ static const char * const axp20x_model_names[] = {
 	"AXP803",
 	"AXP806",
 	"AXP809",
+	"AXP813",
 };
 
 static const struct regmap_range axp152_writeable_ranges[] = {
@@ -811,6 +812,7 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
 		axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
 		break;
 	case AXP803_ID:
+	case AXP813_ID:
 		axp20x->cells = axp803_cells;
 		axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
 		break;
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 2cbb280..a678ba6 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -22,7 +22,7 @@ obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
 obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
 obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
 obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o axp-regulator.o \
-				axp803.o
+				axp803.o axp813.o
 obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o
 obj-$(CONFIG_REGULATOR_DA903X)	+= da903x.o
 obj-$(CONFIG_REGULATOR_DA9052)	+= da9052-regulator.o
diff --git a/drivers/regulator/axp813.c b/drivers/regulator/axp813.c
new file mode 100644
index 0000000..99bfaaa
--- /dev/null
+++ b/drivers/regulator/axp813.c
@@ -0,0 +1,229 @@
+/*
+ * AXP813 regulator driver
+ *
+ * Copyright (C) 2016 Jean-Francois Moine <moinejf@free.fr>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/axp20x.h>
+#include <linux/regulator/driver.h>
+#include <linux/sunxi-rsb.h>
+
+#include "axp-regulator.h"
+
+enum {
+	AXP813_DLDO1 = 0,
+	AXP813_DLDO2,
+	AXP813_DLDO3,
+	AXP813_DLDO4,
+	AXP813_ELDO1,
+	AXP813_ELDO2,
+	AXP813_ELDO3,
+	AXP813_FLDO1,
+	AXP813_FLDO2,
+	AXP813_FLDO3,
+	AXP813_DCDC1,
+	AXP813_DCDC2,
+	AXP813_DCDC3,
+	AXP813_DCDC4,
+	AXP813_DCDC5,
+	AXP813_DCDC6,
+	AXP813_DCDC7,
+	AXP813_ALDO1,
+	AXP813_ALDO2,
+	AXP813_ALDO3,
+	AXP813_LDO_IO0,
+	AXP813_LDO_IO1,
+	AXP813_RTC_LDO,
+};
+
+/* AXP813 registers */
+#define AXP813_FLDO1_V_OUT		0x1c
+#define AXP813_FLDO2_V_OUT		0x1d
+#define AXP813_DCDC1_V_OUT		0x20
+#define AXP813_DCDC2_V_OUT		0x21
+#define AXP813_DCDC3_V_OUT		0x22
+#define AXP813_DCDC4_V_OUT		0x23
+#define AXP813_DCDC5_V_OUT		0x24
+#define AXP813_DCDC6_V_OUT		0x25
+#define AXP813_DCDC7_V_OUT		0x26
+
+static const struct regulator_linear_range axp813_dcdc2_4_ranges[] = {
+	REGULATOR_LINEAR_RANGE(500000, 0, 71, 10000),
+	REGULATOR_LINEAR_RANGE(1220000, 72, 76, 20000),
+};
+
+static const struct regulator_linear_range axp813_dcdc5_ranges[] = {
+	REGULATOR_LINEAR_RANGE(800000, 0, 33, 10000),
+	REGULATOR_LINEAR_RANGE(1140000, 34, 69, 20000),
+};
+
+static const struct regulator_linear_range axp813_dcdc6_7_ranges[] = {
+	REGULATOR_LINEAR_RANGE(600000, 0, 51, 10000),
+	REGULATOR_LINEAR_RANGE(1120000, 52, 72, 20000),
+};
+
+static const struct regulator_linear_range axp813_dldo2_ranges[] = {
+	REGULATOR_LINEAR_RANGE(700000, 0, 26, 100000),
+	REGULATOR_LINEAR_RANGE(3400000, 27, 31, 200000),
+};
+
+static const struct regulator_desc axp813_regulators[] = {
+	AXP_DESC(AXP813, DLDO1, "dldo1", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(3)),
+	AXP_DESC_RANGES(AXP813, DLDO2, "dldo2", "dldoin", axp813_dldo2_ranges,
+			31, AXP22X_DLDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
+			BIT(4)),
+	AXP_DESC(AXP813, DLDO3, "dldo3", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
+	AXP_DESC(AXP813, DLDO4, "dldo4", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO4_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(6)),
+	AXP_DESC(AXP813, ELDO1, "eldo1", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(0)),
+	AXP_DESC(AXP813, ELDO2, "eldo2", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
+	AXP_DESC(AXP813, ELDO3, "eldo3", "eldoin", 700, 1900, 50,
+		 AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
+	AXP_DESC(AXP813, FLDO1, "fldo1", "fldoin", 700, 1450, 50,
+		 AXP813_FLDO1_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(2)),
+	AXP_DESC(AXP813, FLDO2, "fldo2", "fldoin", 700, 1450, 50,
+		 AXP813_FLDO2_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(3)),
+/*	FLDO3 not described (output = DCDC5/2 or FLDOIN/2 */
+	AXP_DESC(AXP813, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
+		 AXP813_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(0)),
+	AXP_DESC_RANGES(AXP813, DCDC2, "dcdc2", "vin2", axp813_dcdc2_4_ranges,
+			76, AXP813_DCDC2_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(1)),
+	AXP_DESC_RANGES(AXP813, DCDC3, "dcdc3", "vin3", axp813_dcdc2_4_ranges,
+			76, AXP813_DCDC3_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(2)),
+	AXP_DESC_RANGES(AXP813, DCDC4, "dcdc4", "vin4", axp813_dcdc2_4_ranges,
+			76, AXP813_DCDC4_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(3)),
+	AXP_DESC_RANGES(AXP813, DCDC5, "dcdc5", "vin5", axp813_dcdc5_ranges,
+			69, AXP813_DCDC5_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(4)),
+	AXP_DESC_RANGES(AXP813, DCDC6, "dcdc6", "vin6", axp813_dcdc6_7_ranges,
+			72, AXP813_DCDC6_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(5)),
+	AXP_DESC_RANGES(AXP813, DCDC7, "dcdc7", "vin7", axp813_dcdc6_7_ranges,
+			72, AXP813_DCDC7_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
+			BIT(6)),
+	AXP_DESC(AXP813, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(5)),
+	AXP_DESC(AXP813, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(6)),
+	AXP_DESC(AXP813, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(7)),
+	AXP_DESC_IO(AXP813, LDO_IO0, "ldo_io0", "ips", 700, 3300, 100,
+		    AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
+		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
+	AXP_DESC_IO(AXP813, LDO_IO1, "ldo_io1", "ips", 700, 3300, 100,
+		    AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
+		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
+	AXP_DESC_FIXED(AXP813, RTC_LDO, "rtc_ldo", "ips", 1800),
+};
+
+static const struct regmap_range axp813_writeable_ranges[] = {
+	regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
+	regmap_reg_range(AXP20X_DCDC_MODE, AXP22X_BATLOW_THRES1),
+};
+
+static const struct regmap_range axp813_volatile_ranges[] = {
+	regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_PWR_OP_MODE),
+	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
+	regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
+	regmap_reg_range(AXP20X_FG_RES, AXP20X_FG_RES),
+};
+
+static const struct regmap_access_table axp813_writeable_table = {
+	.yes_ranges	= axp813_writeable_ranges,
+	.n_yes_ranges	= ARRAY_SIZE(axp813_writeable_ranges),
+};
+
+static const struct regmap_access_table axp813_volatile_table = {
+	.yes_ranges	= axp813_volatile_ranges,
+	.n_yes_ranges	= ARRAY_SIZE(axp813_volatile_ranges),
+};
+
+static const struct regmap_config axp813_regmap_config = {
+	.reg_bits	= 8,
+	.val_bits	= 8,
+	.wr_table	= &axp813_writeable_table,
+	.volatile_table	= &axp813_volatile_table,
+	.max_register	= AXP22X_BATLOW_THRES1,
+	.cache_type	= REGCACHE_RBTREE,
+};
+
+#define INIT_REGMAP_IRQ(_irq, _off, _bit)			\
+	[AXP809_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_bit) }
+
+static const struct regmap_irq axp813_regmap_irqs[] = {
+	INIT_REGMAP_IRQ(PEK_RIS_EDGE,	        4, 6),
+	INIT_REGMAP_IRQ(PEK_FAL_EDGE,	        4, 5),
+	INIT_REGMAP_IRQ(PEK_SHORT,		4, 4),
+	INIT_REGMAP_IRQ(PEK_LONG,		4, 3),
+	INIT_REGMAP_IRQ(PEK_OVER_OFF,		4, 2),
+	INIT_REGMAP_IRQ(GPIO1_INPUT,		4, 1),
+	INIT_REGMAP_IRQ(GPIO0_INPUT,		4, 0),
+};
+
+static const struct regmap_irq_chip axp813_regmap_irq_chip = {
+	.name			= "axp813",
+	.status_base		= AXP20X_IRQ1_STATE,
+	.ack_base		= AXP20X_IRQ1_STATE,
+	.mask_base		= AXP20X_IRQ1_EN,
+	.mask_invert		= true,
+	.init_ack_masked	= true,
+	.irqs			= axp813_regmap_irqs,
+	.num_irqs		= ARRAY_SIZE(axp813_regmap_irqs),
+	.num_regs		= 6,
+};
+
+static const struct axp_cfg axp813_cfg = {
+	.regulators = axp813_regulators,
+	.nregulators= ARRAY_SIZE(axp813_regulators),
+	.dcdc1_ix = -1,
+	.dcdc5_ix = -1,
+	.dc1sw_ix = -1,
+	.dc5ldo_ix = -1,
+	.skip_bitmap = 1 << AXP813_FLDO3,
+};
+
+static struct axp20x_dev axp813_dev = {
+	.regmap_cfg = &axp813_regmap_config,
+	.regmap_irq_chip = &axp813_regmap_irq_chip,
+};
+
+static int axp813_rsb_probe(struct sunxi_rsb_device *rdev)
+{
+	return axp_rsb_probe(rdev, &axp813_dev, &axp813_cfg);
+}
+
+static const struct of_device_id axp813_of_match[] = {
+	{ .compatible = "x-powers,axp813", .data = (void *) AXP813_ID },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, axp813_of_match);
+
+static struct sunxi_rsb_driver axp813_rsb_driver = {
+	.driver = {
+		.name	= "axp813-rsb",
+		.of_match_table	= of_match_ptr(axp813_of_match),
+	},
+	.probe	= axp813_rsb_probe,
+	.remove	= axp_rsb_remove,
+};
+module_sunxi_rsb_driver(axp813_rsb_driver);
+
+MODULE_DESCRIPTION("AXP813 RSB driver");
+MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
index 9c5fb00..90296f0 100644
--- a/include/linux/mfd/axp20x.h
+++ b/include/linux/mfd/axp20x.h
@@ -23,6 +23,7 @@ enum {
 	AXP803_ID,
 	AXP806_ID,
 	AXP809_ID,
+	AXP813_ID,
 	NR_AXP20X_VARIANTS,
 };
 
-- 
2.10.0

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 0/4] regulator: axp20x: support AXP803/AXP813 variants
@ 2016-09-23  8:58 ` Jean-Francois Moine
  0 siblings, 0 replies; 27+ messages in thread
From: Jean-Francois Moine @ 2016-09-23  8:58 UTC (permalink / raw)
  To: Chen-Yu Tsai, Mark Rutland, Rob Herring
  Cc: devicetree, linux-arm-kernel, linux-kernel, linux-sunxi

This patch series adds support for the X-Powers AXP803 and AXP813 PMICs.
It is based on the previous patch series
	regulator: axp20x: Simplify various code

v3:
- put the code of the new devices in new files instead of in the common
  axp20x file.
- fix errors about the regulators and interrupts
v2:
- fix lack of support of dcdc frequency
- notice that the AXP803 is also handled
- send the patch to the DT maintainers

Jean-Francois Moine (4):
  regulator: axp20x: move device independant parts to new files
  regulator: axp20x: duplicate the MFD axp20x-rsb code
  regulator: axp20x: add the AXP803
  regulator: axp20x: add the AXP813

 Documentation/devicetree/bindings/mfd/axp20x.txt |  29 ++-
 drivers/mfd/axp20x.c                             |  15 +
 drivers/regulator/Makefile                       |   3 +-
 drivers/regulator/axp-regulator.c                | 347 +++++++++++++++++++
 drivers/regulator/axp-regulator.h                | 133 ++++++++
 drivers/regulator/axp20x-regulator.c             | 415 ++---------------------
 drivers/regulator/axp803.c                       | 225 ++++++++++++
 drivers/regulator/axp813.c                       | 229 +++++++++++++
 include/linux/mfd/axp20x.h                       |   2 +
 9 files changed, 1012 insertions(+), 388 deletions(-)
 create mode 100644 drivers/regulator/axp-regulator.c
 create mode 100644 drivers/regulator/axp-regulator.h
 create mode 100644 drivers/regulator/axp803.c
 create mode 100644 drivers/regulator/axp813.c

-- 
2.10.0

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 0/4] regulator: axp20x: support AXP803/AXP813 variants
@ 2016-09-23  8:58 ` Jean-Francois Moine
  0 siblings, 0 replies; 27+ messages in thread
From: Jean-Francois Moine @ 2016-09-23  8:58 UTC (permalink / raw)
  To: Chen-Yu Tsai, Mark Rutland, Rob Herring
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw

This patch series adds support for the X-Powers AXP803 and AXP813 PMICs.
It is based on the previous patch series
	regulator: axp20x: Simplify various code

v3:
- put the code of the new devices in new files instead of in the common
  axp20x file.
- fix errors about the regulators and interrupts
v2:
- fix lack of support of dcdc frequency
- notice that the AXP803 is also handled
- send the patch to the DT maintainers

Jean-Francois Moine (4):
  regulator: axp20x: move device independant parts to new files
  regulator: axp20x: duplicate the MFD axp20x-rsb code
  regulator: axp20x: add the AXP803
  regulator: axp20x: add the AXP813

 Documentation/devicetree/bindings/mfd/axp20x.txt |  29 ++-
 drivers/mfd/axp20x.c                             |  15 +
 drivers/regulator/Makefile                       |   3 +-
 drivers/regulator/axp-regulator.c                | 347 +++++++++++++++++++
 drivers/regulator/axp-regulator.h                | 133 ++++++++
 drivers/regulator/axp20x-regulator.c             | 415 ++---------------------
 drivers/regulator/axp803.c                       | 225 ++++++++++++
 drivers/regulator/axp813.c                       | 229 +++++++++++++
 include/linux/mfd/axp20x.h                       |   2 +
 9 files changed, 1012 insertions(+), 388 deletions(-)
 create mode 100644 drivers/regulator/axp-regulator.c
 create mode 100644 drivers/regulator/axp-regulator.h
 create mode 100644 drivers/regulator/axp803.c
 create mode 100644 drivers/regulator/axp813.c

-- 
2.10.0

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 0/4] regulator: axp20x: support AXP803/AXP813 variants
@ 2016-09-23  8:58 ` Jean-Francois Moine
  0 siblings, 0 replies; 27+ messages in thread
From: Jean-Francois Moine @ 2016-09-23  8:58 UTC (permalink / raw)
  To: linux-arm-kernel

This patch series adds support for the X-Powers AXP803 and AXP813 PMICs.
It is based on the previous patch series
	regulator: axp20x: Simplify various code

v3:
- put the code of the new devices in new files instead of in the common
  axp20x file.
- fix errors about the regulators and interrupts
v2:
- fix lack of support of dcdc frequency
- notice that the AXP803 is also handled
- send the patch to the DT maintainers

Jean-Francois Moine (4):
  regulator: axp20x: move device independant parts to new files
  regulator: axp20x: duplicate the MFD axp20x-rsb code
  regulator: axp20x: add the AXP803
  regulator: axp20x: add the AXP813

 Documentation/devicetree/bindings/mfd/axp20x.txt |  29 ++-
 drivers/mfd/axp20x.c                             |  15 +
 drivers/regulator/Makefile                       |   3 +-
 drivers/regulator/axp-regulator.c                | 347 +++++++++++++++++++
 drivers/regulator/axp-regulator.h                | 133 ++++++++
 drivers/regulator/axp20x-regulator.c             | 415 ++---------------------
 drivers/regulator/axp803.c                       | 225 ++++++++++++
 drivers/regulator/axp813.c                       | 229 +++++++++++++
 include/linux/mfd/axp20x.h                       |   2 +
 9 files changed, 1012 insertions(+), 388 deletions(-)
 create mode 100644 drivers/regulator/axp-regulator.c
 create mode 100644 drivers/regulator/axp-regulator.h
 create mode 100644 drivers/regulator/axp803.c
 create mode 100644 drivers/regulator/axp813.c

-- 
2.10.0

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 3/4] regulator: axp20x: add the AXP803
@ 2016-09-23 22:17     ` Rob Herring
  0 siblings, 0 replies; 27+ messages in thread
From: Rob Herring @ 2016-09-23 22:17 UTC (permalink / raw)
  To: Jean-Francois Moine
  Cc: Chen-Yu Tsai, Mark Rutland, devicetree, linux-arm-kernel,
	linux-kernel, linux-sunxi

On Fri, Sep 23, 2016 at 09:00:42AM +0200, Jean-Francois Moine wrote:
> The X-Powers AXP803 PMIC is close to the AXP809 with more outputs.
> It is used in some Allwinner boards as the Sinovoip BananaPi M64
> and the Pine A64.
> 
> Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
> ---
> not tested
> ---
>  Documentation/devicetree/bindings/mfd/axp20x.txt |  32 +++-
>  drivers/mfd/axp20x.c                             |  13 ++
>  drivers/regulator/Makefile                       |   3 +-
>  drivers/regulator/axp803.c                       | 225 +++++++++++++++++++++++
>  include/linux/mfd/axp20x.h                       |   1 +
>  5 files changed, 271 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/regulator/axp803.c
> 
> diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
> index 8f3ad9a..3332d02 100644
> --- a/Documentation/devicetree/bindings/mfd/axp20x.txt
> +++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
> @@ -6,12 +6,13 @@ axp202 (X-Powers)
>  axp209 (X-Powers)
>  axp221 (X-Powers)
>  axp223 (X-Powers)
> +axp803 (X-Powers)
>  axp809 (X-Powers)
>  
>  Required properties:
>  - compatible: "x-powers,axp152", "x-powers,axp202", "x-powers,axp209",
> -	      "x-powers,axp221", "x-powers,axp223", "x-powers,axp806",
> -	      "x-powers,axp809"
> +	      "x-powers,axp221", "x-powers,axp223", "x-powers,axp803",
> +	      "x-powers,axp806", "x-powers,axp809"

If you respin this, please reformat this to one per line.

Acked-by: Rob Herring <robh@kernel.org>

>  - reg: The I2C slave address or RSB hardware address for the AXP chip
>  - interrupt-parent: The parent interrupt controller
>  - interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
> @@ -86,6 +87,33 @@ LDO_IO1		: LDO		: ips-supply		: GPIO 1
>  RTC_LDO		: LDO		: ips-supply		: always on
>  DRIVEVBUS	: Enable output	: drivevbus-supply	: external regulator
>  
> +AXP803 regulators, type, and corresponding input supply names:
> +
> +Regulator	  Type		  Supply Name		  Notes
> +---------	  ----		  -----------		  -----
> +DCDC1		: DC-DC buck	: vin1-supply
> +DCDC2		: DC-DC buck	: vin2-supply
> +DCDC3		: DC-DC	buck	: vin3-supply
> +DCDC4		: DC-DC	buck	: vin4-supply
> +DCDC5		: DC-DC	buck	: vin5-supply
> +DCDC6		: DC-DC	buck	: vin6-supply
> +ALDO1		: LDO		: aldoin-supply	: shared supply
> +ALDO2		: LDO		: aldoin-supply	: shared supply
> +ALDO3		: LDO		: aldoin-supply	: shared supply
> +DLDO1		: LDO		: dldoin-supply	: shared supply
> +DLDO2		: LDO		: dldoin-supply	: shared supply
> +DLDO3		: LDO		: dldoin-supply	: shared supply
> +DLDO4		: LDO		: dldoin-supply	: shared supply
> +ELDO1		: LDO		: eldoin-supply	: shared supply
> +ELDO2		: LDO		: eldoin-supply	: shared supply
> +ELDO3		: LDO		: eldoin-supply	: shared supply
> +FLDO1		: LDO		: fldoin-supply	: shared supply
> +FLDO2		: LDO		: fldoin-supply	: shared supply
> +RTC_LDO		: LDO		: ips-supply	: always on
> +LDO_IO0		: LDO		: ips-supply	: GPIO 0
> +LDO_IO1		: LDO		: ips-supply	: GPIO 1
> +DC1SW		: On/Off Switch	:		: DCDC1 secondary output
> +
>  AXP806 regulators, type, and corresponding input supply names:
>  
>  Regulator	  Type		  Supply Name		  Notes

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 3/4] regulator: axp20x: add the AXP803
@ 2016-09-23 22:17     ` Rob Herring
  0 siblings, 0 replies; 27+ messages in thread
From: Rob Herring @ 2016-09-23 22:17 UTC (permalink / raw)
  To: Jean-Francois Moine
  Cc: Chen-Yu Tsai, Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw

On Fri, Sep 23, 2016 at 09:00:42AM +0200, Jean-Francois Moine wrote:
> The X-Powers AXP803 PMIC is close to the AXP809 with more outputs.
> It is used in some Allwinner boards as the Sinovoip BananaPi M64
> and the Pine A64.
> 
> Signed-off-by: Jean-Francois Moine <moinejf-GANU6spQydw@public.gmane.org>
> ---
> not tested
> ---
>  Documentation/devicetree/bindings/mfd/axp20x.txt |  32 +++-
>  drivers/mfd/axp20x.c                             |  13 ++
>  drivers/regulator/Makefile                       |   3 +-
>  drivers/regulator/axp803.c                       | 225 +++++++++++++++++++++++
>  include/linux/mfd/axp20x.h                       |   1 +
>  5 files changed, 271 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/regulator/axp803.c
> 
> diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
> index 8f3ad9a..3332d02 100644
> --- a/Documentation/devicetree/bindings/mfd/axp20x.txt
> +++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
> @@ -6,12 +6,13 @@ axp202 (X-Powers)
>  axp209 (X-Powers)
>  axp221 (X-Powers)
>  axp223 (X-Powers)
> +axp803 (X-Powers)
>  axp809 (X-Powers)
>  
>  Required properties:
>  - compatible: "x-powers,axp152", "x-powers,axp202", "x-powers,axp209",
> -	      "x-powers,axp221", "x-powers,axp223", "x-powers,axp806",
> -	      "x-powers,axp809"
> +	      "x-powers,axp221", "x-powers,axp223", "x-powers,axp803",
> +	      "x-powers,axp806", "x-powers,axp809"

If you respin this, please reformat this to one per line.

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

>  - reg: The I2C slave address or RSB hardware address for the AXP chip
>  - interrupt-parent: The parent interrupt controller
>  - interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
> @@ -86,6 +87,33 @@ LDO_IO1		: LDO		: ips-supply		: GPIO 1
>  RTC_LDO		: LDO		: ips-supply		: always on
>  DRIVEVBUS	: Enable output	: drivevbus-supply	: external regulator
>  
> +AXP803 regulators, type, and corresponding input supply names:
> +
> +Regulator	  Type		  Supply Name		  Notes
> +---------	  ----		  -----------		  -----
> +DCDC1		: DC-DC buck	: vin1-supply
> +DCDC2		: DC-DC buck	: vin2-supply
> +DCDC3		: DC-DC	buck	: vin3-supply
> +DCDC4		: DC-DC	buck	: vin4-supply
> +DCDC5		: DC-DC	buck	: vin5-supply
> +DCDC6		: DC-DC	buck	: vin6-supply
> +ALDO1		: LDO		: aldoin-supply	: shared supply
> +ALDO2		: LDO		: aldoin-supply	: shared supply
> +ALDO3		: LDO		: aldoin-supply	: shared supply
> +DLDO1		: LDO		: dldoin-supply	: shared supply
> +DLDO2		: LDO		: dldoin-supply	: shared supply
> +DLDO3		: LDO		: dldoin-supply	: shared supply
> +DLDO4		: LDO		: dldoin-supply	: shared supply
> +ELDO1		: LDO		: eldoin-supply	: shared supply
> +ELDO2		: LDO		: eldoin-supply	: shared supply
> +ELDO3		: LDO		: eldoin-supply	: shared supply
> +FLDO1		: LDO		: fldoin-supply	: shared supply
> +FLDO2		: LDO		: fldoin-supply	: shared supply
> +RTC_LDO		: LDO		: ips-supply	: always on
> +LDO_IO0		: LDO		: ips-supply	: GPIO 0
> +LDO_IO1		: LDO		: ips-supply	: GPIO 1
> +DC1SW		: On/Off Switch	:		: DCDC1 secondary output
> +
>  AXP806 regulators, type, and corresponding input supply names:
>  
>  Regulator	  Type		  Supply Name		  Notes
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 3/4] regulator: axp20x: add the AXP803
@ 2016-09-23 22:17     ` Rob Herring
  0 siblings, 0 replies; 27+ messages in thread
From: Rob Herring @ 2016-09-23 22:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Sep 23, 2016 at 09:00:42AM +0200, Jean-Francois Moine wrote:
> The X-Powers AXP803 PMIC is close to the AXP809 with more outputs.
> It is used in some Allwinner boards as the Sinovoip BananaPi M64
> and the Pine A64.
> 
> Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
> ---
> not tested
> ---
>  Documentation/devicetree/bindings/mfd/axp20x.txt |  32 +++-
>  drivers/mfd/axp20x.c                             |  13 ++
>  drivers/regulator/Makefile                       |   3 +-
>  drivers/regulator/axp803.c                       | 225 +++++++++++++++++++++++
>  include/linux/mfd/axp20x.h                       |   1 +
>  5 files changed, 271 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/regulator/axp803.c
> 
> diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
> index 8f3ad9a..3332d02 100644
> --- a/Documentation/devicetree/bindings/mfd/axp20x.txt
> +++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
> @@ -6,12 +6,13 @@ axp202 (X-Powers)
>  axp209 (X-Powers)
>  axp221 (X-Powers)
>  axp223 (X-Powers)
> +axp803 (X-Powers)
>  axp809 (X-Powers)
>  
>  Required properties:
>  - compatible: "x-powers,axp152", "x-powers,axp202", "x-powers,axp209",
> -	      "x-powers,axp221", "x-powers,axp223", "x-powers,axp806",
> -	      "x-powers,axp809"
> +	      "x-powers,axp221", "x-powers,axp223", "x-powers,axp803",
> +	      "x-powers,axp806", "x-powers,axp809"

If you respin this, please reformat this to one per line.

Acked-by: Rob Herring <robh@kernel.org>

>  - reg: The I2C slave address or RSB hardware address for the AXP chip
>  - interrupt-parent: The parent interrupt controller
>  - interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
> @@ -86,6 +87,33 @@ LDO_IO1		: LDO		: ips-supply		: GPIO 1
>  RTC_LDO		: LDO		: ips-supply		: always on
>  DRIVEVBUS	: Enable output	: drivevbus-supply	: external regulator
>  
> +AXP803 regulators, type, and corresponding input supply names:
> +
> +Regulator	  Type		  Supply Name		  Notes
> +---------	  ----		  -----------		  -----
> +DCDC1		: DC-DC buck	: vin1-supply
> +DCDC2		: DC-DC buck	: vin2-supply
> +DCDC3		: DC-DC	buck	: vin3-supply
> +DCDC4		: DC-DC	buck	: vin4-supply
> +DCDC5		: DC-DC	buck	: vin5-supply
> +DCDC6		: DC-DC	buck	: vin6-supply
> +ALDO1		: LDO		: aldoin-supply	: shared supply
> +ALDO2		: LDO		: aldoin-supply	: shared supply
> +ALDO3		: LDO		: aldoin-supply	: shared supply
> +DLDO1		: LDO		: dldoin-supply	: shared supply
> +DLDO2		: LDO		: dldoin-supply	: shared supply
> +DLDO3		: LDO		: dldoin-supply	: shared supply
> +DLDO4		: LDO		: dldoin-supply	: shared supply
> +ELDO1		: LDO		: eldoin-supply	: shared supply
> +ELDO2		: LDO		: eldoin-supply	: shared supply
> +ELDO3		: LDO		: eldoin-supply	: shared supply
> +FLDO1		: LDO		: fldoin-supply	: shared supply
> +FLDO2		: LDO		: fldoin-supply	: shared supply
> +RTC_LDO		: LDO		: ips-supply	: always on
> +LDO_IO0		: LDO		: ips-supply	: GPIO 0
> +LDO_IO1		: LDO		: ips-supply	: GPIO 1
> +DC1SW		: On/Off Switch	:		: DCDC1 secondary output
> +
>  AXP806 regulators, type, and corresponding input supply names:
>  
>  Regulator	  Type		  Supply Name		  Notes

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 4/4] regulator: axp20x: add the AXP813
@ 2016-09-23 22:27     ` Rob Herring
  0 siblings, 0 replies; 27+ messages in thread
From: Rob Herring @ 2016-09-23 22:27 UTC (permalink / raw)
  To: Jean-Francois Moine
  Cc: Chen-Yu Tsai, Mark Rutland, devicetree, linux-arm-kernel,
	linux-kernel, linux-sunxi

On Fri, Sep 23, 2016 at 09:22:41AM +0200, Jean-Francois Moine wrote:
> The X-Powers AXP813 PMIC is close to the AXP803.
> It is used in some Allwinner boards as the Sinovoip BananaPi M3+.
> 
> Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
> ---
>  Documentation/devicetree/bindings/mfd/axp20x.txt |   9 +-
>  drivers/mfd/axp20x.c                             |   2 +
>  drivers/regulator/Makefile                       |   2 +-
>  drivers/regulator/axp813.c                       | 229 +++++++++++++++++++++++
>  include/linux/mfd/axp20x.h                       |   1 +
>  5 files changed, 239 insertions(+), 4 deletions(-)
>  create mode 100644 drivers/regulator/axp813.c
> 
> diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
> index 3332d02..62019fb 100644
> --- a/Documentation/devicetree/bindings/mfd/axp20x.txt
> +++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
> @@ -8,11 +8,12 @@ axp221 (X-Powers)
>  axp223 (X-Powers)
>  axp803 (X-Powers)
>  axp809 (X-Powers)
> +axp813 (X-Powers)
>  
>  Required properties:
>  - compatible: "x-powers,axp152", "x-powers,axp202", "x-powers,axp209",
>  	      "x-powers,axp221", "x-powers,axp223", "x-powers,axp803",
> -	      "x-powers,axp806", "x-powers,axp809"
> +	      "x-powers,axp806", "x-powers,axp809", "x-powers,axp813"

Same comment here.

Acked-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 4/4] regulator: axp20x: add the AXP813
@ 2016-09-23 22:27     ` Rob Herring
  0 siblings, 0 replies; 27+ messages in thread
From: Rob Herring @ 2016-09-23 22:27 UTC (permalink / raw)
  To: Jean-Francois Moine
  Cc: Chen-Yu Tsai, Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw

On Fri, Sep 23, 2016 at 09:22:41AM +0200, Jean-Francois Moine wrote:
> The X-Powers AXP813 PMIC is close to the AXP803.
> It is used in some Allwinner boards as the Sinovoip BananaPi M3+.
> 
> Signed-off-by: Jean-Francois Moine <moinejf-GANU6spQydw@public.gmane.org>
> ---
>  Documentation/devicetree/bindings/mfd/axp20x.txt |   9 +-
>  drivers/mfd/axp20x.c                             |   2 +
>  drivers/regulator/Makefile                       |   2 +-
>  drivers/regulator/axp813.c                       | 229 +++++++++++++++++++++++
>  include/linux/mfd/axp20x.h                       |   1 +
>  5 files changed, 239 insertions(+), 4 deletions(-)
>  create mode 100644 drivers/regulator/axp813.c
> 
> diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
> index 3332d02..62019fb 100644
> --- a/Documentation/devicetree/bindings/mfd/axp20x.txt
> +++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
> @@ -8,11 +8,12 @@ axp221 (X-Powers)
>  axp223 (X-Powers)
>  axp803 (X-Powers)
>  axp809 (X-Powers)
> +axp813 (X-Powers)
>  
>  Required properties:
>  - compatible: "x-powers,axp152", "x-powers,axp202", "x-powers,axp209",
>  	      "x-powers,axp221", "x-powers,axp223", "x-powers,axp803",
> -	      "x-powers,axp806", "x-powers,axp809"
> +	      "x-powers,axp806", "x-powers,axp809", "x-powers,axp813"

Same comment here.

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 4/4] regulator: axp20x: add the AXP813
@ 2016-09-23 22:27     ` Rob Herring
  0 siblings, 0 replies; 27+ messages in thread
From: Rob Herring @ 2016-09-23 22:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Sep 23, 2016 at 09:22:41AM +0200, Jean-Francois Moine wrote:
> The X-Powers AXP813 PMIC is close to the AXP803.
> It is used in some Allwinner boards as the Sinovoip BananaPi M3+.
> 
> Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
> ---
>  Documentation/devicetree/bindings/mfd/axp20x.txt |   9 +-
>  drivers/mfd/axp20x.c                             |   2 +
>  drivers/regulator/Makefile                       |   2 +-
>  drivers/regulator/axp813.c                       | 229 +++++++++++++++++++++++
>  include/linux/mfd/axp20x.h                       |   1 +
>  5 files changed, 239 insertions(+), 4 deletions(-)
>  create mode 100644 drivers/regulator/axp813.c
> 
> diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
> index 3332d02..62019fb 100644
> --- a/Documentation/devicetree/bindings/mfd/axp20x.txt
> +++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
> @@ -8,11 +8,12 @@ axp221 (X-Powers)
>  axp223 (X-Powers)
>  axp803 (X-Powers)
>  axp809 (X-Powers)
> +axp813 (X-Powers)
>  
>  Required properties:
>  - compatible: "x-powers,axp152", "x-powers,axp202", "x-powers,axp209",
>  	      "x-powers,axp221", "x-powers,axp223", "x-powers,axp803",
> -	      "x-powers,axp806", "x-powers,axp809"
> +	      "x-powers,axp806", "x-powers,axp809", "x-powers,axp813"

Same comment here.

Acked-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 0/4] regulator: axp20x: support AXP803/AXP813 variants
@ 2016-09-24  8:35   ` Chen-Yu Tsai
  0 siblings, 0 replies; 27+ messages in thread
From: Chen-Yu Tsai @ 2016-09-24  8:35 UTC (permalink / raw)
  To: Jean-Francois Moine
  Cc: Chen-Yu Tsai, Mark Rutland, Rob Herring, devicetree,
	linux-arm-kernel, linux-kernel, linux-sunxi

On Fri, Sep 23, 2016 at 4:58 PM, Jean-Francois Moine <moinejf@free.fr> wrote:
> This patch series adds support for the X-Powers AXP803 and AXP813 PMICs.
> It is based on the previous patch series
>         regulator: axp20x: Simplify various code
>
> v3:
> - put the code of the new devices in new files instead of in the common
>   axp20x file.
> - fix errors about the regulators and interrupts
> v2:
> - fix lack of support of dcdc frequency
> - notice that the AXP803 is also handled
> - send the patch to the DT maintainers
>
> Jean-Francois Moine (4):
>   regulator: axp20x: move device independant parts to new files
>   regulator: axp20x: duplicate the MFD axp20x-rsb code
>   regulator: axp20x: add the AXP803
>   regulator: axp20x: add the AXP813

NAK. Please follow the axp20x mfd and sub-device driver design we
already have.

ChenYu

>  Documentation/devicetree/bindings/mfd/axp20x.txt |  29 ++-
>  drivers/mfd/axp20x.c                             |  15 +
>  drivers/regulator/Makefile                       |   3 +-
>  drivers/regulator/axp-regulator.c                | 347 +++++++++++++++++++
>  drivers/regulator/axp-regulator.h                | 133 ++++++++
>  drivers/regulator/axp20x-regulator.c             | 415 ++---------------------
>  drivers/regulator/axp803.c                       | 225 ++++++++++++
>  drivers/regulator/axp813.c                       | 229 +++++++++++++
>  include/linux/mfd/axp20x.h                       |   2 +
>  9 files changed, 1012 insertions(+), 388 deletions(-)
>  create mode 100644 drivers/regulator/axp-regulator.c
>  create mode 100644 drivers/regulator/axp-regulator.h
>  create mode 100644 drivers/regulator/axp803.c
>  create mode 100644 drivers/regulator/axp813.c
>
> --
> 2.10.0
>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 0/4] regulator: axp20x: support AXP803/AXP813 variants
@ 2016-09-24  8:35   ` Chen-Yu Tsai
  0 siblings, 0 replies; 27+ messages in thread
From: Chen-Yu Tsai @ 2016-09-24  8:35 UTC (permalink / raw)
  To: Jean-Francois Moine
  Cc: Chen-Yu Tsai, Mark Rutland, Rob Herring, devicetree,
	linux-arm-kernel, linux-kernel, linux-sunxi

On Fri, Sep 23, 2016 at 4:58 PM, Jean-Francois Moine <moinejf-GANU6spQydw@public.gmane.org> wrote:
> This patch series adds support for the X-Powers AXP803 and AXP813 PMICs.
> It is based on the previous patch series
>         regulator: axp20x: Simplify various code
>
> v3:
> - put the code of the new devices in new files instead of in the common
>   axp20x file.
> - fix errors about the regulators and interrupts
> v2:
> - fix lack of support of dcdc frequency
> - notice that the AXP803 is also handled
> - send the patch to the DT maintainers
>
> Jean-Francois Moine (4):
>   regulator: axp20x: move device independant parts to new files
>   regulator: axp20x: duplicate the MFD axp20x-rsb code
>   regulator: axp20x: add the AXP803
>   regulator: axp20x: add the AXP813

NAK. Please follow the axp20x mfd and sub-device driver design we
already have.

ChenYu

>  Documentation/devicetree/bindings/mfd/axp20x.txt |  29 ++-
>  drivers/mfd/axp20x.c                             |  15 +
>  drivers/regulator/Makefile                       |   3 +-
>  drivers/regulator/axp-regulator.c                | 347 +++++++++++++++++++
>  drivers/regulator/axp-regulator.h                | 133 ++++++++
>  drivers/regulator/axp20x-regulator.c             | 415 ++---------------------
>  drivers/regulator/axp803.c                       | 225 ++++++++++++
>  drivers/regulator/axp813.c                       | 229 +++++++++++++
>  include/linux/mfd/axp20x.h                       |   2 +
>  9 files changed, 1012 insertions(+), 388 deletions(-)
>  create mode 100644 drivers/regulator/axp-regulator.c
>  create mode 100644 drivers/regulator/axp-regulator.h
>  create mode 100644 drivers/regulator/axp803.c
>  create mode 100644 drivers/regulator/axp813.c
>
> --
> 2.10.0
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 0/4] regulator: axp20x: support AXP803/AXP813 variants
@ 2016-09-24  8:35   ` Chen-Yu Tsai
  0 siblings, 0 replies; 27+ messages in thread
From: Chen-Yu Tsai @ 2016-09-24  8:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Sep 23, 2016 at 4:58 PM, Jean-Francois Moine <moinejf@free.fr> wrote:
> This patch series adds support for the X-Powers AXP803 and AXP813 PMICs.
> It is based on the previous patch series
>         regulator: axp20x: Simplify various code
>
> v3:
> - put the code of the new devices in new files instead of in the common
>   axp20x file.
> - fix errors about the regulators and interrupts
> v2:
> - fix lack of support of dcdc frequency
> - notice that the AXP803 is also handled
> - send the patch to the DT maintainers
>
> Jean-Francois Moine (4):
>   regulator: axp20x: move device independant parts to new files
>   regulator: axp20x: duplicate the MFD axp20x-rsb code
>   regulator: axp20x: add the AXP803
>   regulator: axp20x: add the AXP813

NAK. Please follow the axp20x mfd and sub-device driver design we
already have.

ChenYu

>  Documentation/devicetree/bindings/mfd/axp20x.txt |  29 ++-
>  drivers/mfd/axp20x.c                             |  15 +
>  drivers/regulator/Makefile                       |   3 +-
>  drivers/regulator/axp-regulator.c                | 347 +++++++++++++++++++
>  drivers/regulator/axp-regulator.h                | 133 ++++++++
>  drivers/regulator/axp20x-regulator.c             | 415 ++---------------------
>  drivers/regulator/axp803.c                       | 225 ++++++++++++
>  drivers/regulator/axp813.c                       | 229 +++++++++++++
>  include/linux/mfd/axp20x.h                       |   2 +
>  9 files changed, 1012 insertions(+), 388 deletions(-)
>  create mode 100644 drivers/regulator/axp-regulator.c
>  create mode 100644 drivers/regulator/axp-regulator.h
>  create mode 100644 drivers/regulator/axp803.c
>  create mode 100644 drivers/regulator/axp813.c
>
> --
> 2.10.0
>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 0/4] regulator: axp20x: support AXP803/AXP813 variants
@ 2016-09-24  9:11     ` Jean-Francois Moine
  0 siblings, 0 replies; 27+ messages in thread
From: Jean-Francois Moine @ 2016-09-24  9:11 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Mark Rutland, Rob Herring, devicetree, linux-arm-kernel,
	linux-kernel, linux-sunxi

On Sat, 24 Sep 2016 16:35:05 +0800
Chen-Yu Tsai <wens@csie.org> wrote:

> On Fri, Sep 23, 2016 at 4:58 PM, Jean-Francois Moine <moinejf@free.fr> wrote:
> > This patch series adds support for the X-Powers AXP803 and AXP813 PMICs.
> > It is based on the previous patch series
> >         regulator: axp20x: Simplify various code
> >
> > v3:
> > - put the code of the new devices in new files instead of in the common
> >   axp20x file.
> > - fix errors about the regulators and interrupts
> > v2:
> > - fix lack of support of dcdc frequency
> > - notice that the AXP803 is also handled
> > - send the patch to the DT maintainers
> >
> > Jean-Francois Moine (4):
> >   regulator: axp20x: move device independant parts to new files
> >   regulator: axp20x: duplicate the MFD axp20x-rsb code
> >   regulator: axp20x: add the AXP803
> >   regulator: axp20x: add the AXP813
> 
> NAK. Please follow the axp20x mfd and sub-device driver design we
> already have.

Sorry, I will not: installing a lot of useless code and tables in
permanent system memory for just one regulator is not the way I think
about a good kernel.

-- 
Ken ar c'hentañ	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 0/4] regulator: axp20x: support AXP803/AXP813 variants
@ 2016-09-24  9:11     ` Jean-Francois Moine
  0 siblings, 0 replies; 27+ messages in thread
From: Jean-Francois Moine @ 2016-09-24  9:11 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Mark Rutland, Rob Herring, devicetree, linux-arm-kernel,
	linux-kernel, linux-sunxi

On Sat, 24 Sep 2016 16:35:05 +0800
Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org> wrote:

> On Fri, Sep 23, 2016 at 4:58 PM, Jean-Francois Moine <moinejf-GANU6spQydw@public.gmane.org> wrote:
> > This patch series adds support for the X-Powers AXP803 and AXP813 PMICs.
> > It is based on the previous patch series
> >         regulator: axp20x: Simplify various code
> >
> > v3:
> > - put the code of the new devices in new files instead of in the common
> >   axp20x file.
> > - fix errors about the regulators and interrupts
> > v2:
> > - fix lack of support of dcdc frequency
> > - notice that the AXP803 is also handled
> > - send the patch to the DT maintainers
> >
> > Jean-Francois Moine (4):
> >   regulator: axp20x: move device independant parts to new files
> >   regulator: axp20x: duplicate the MFD axp20x-rsb code
> >   regulator: axp20x: add the AXP803
> >   regulator: axp20x: add the AXP813
> 
> NAK. Please follow the axp20x mfd and sub-device driver design we
> already have.

Sorry, I will not: installing a lot of useless code and tables in
permanent system memory for just one regulator is not the way I think
about a good kernel.

-- 
Ken ar c'hentañ	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/

-- 
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 0/4] regulator: axp20x: support AXP803/AXP813 variants
@ 2016-09-24  9:11     ` Jean-Francois Moine
  0 siblings, 0 replies; 27+ messages in thread
From: Jean-Francois Moine @ 2016-09-24  9:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 24 Sep 2016 16:35:05 +0800
Chen-Yu Tsai <wens@csie.org> wrote:

> On Fri, Sep 23, 2016 at 4:58 PM, Jean-Francois Moine <moinejf@free.fr> wrote:
> > This patch series adds support for the X-Powers AXP803 and AXP813 PMICs.
> > It is based on the previous patch series
> >         regulator: axp20x: Simplify various code
> >
> > v3:
> > - put the code of the new devices in new files instead of in the common
> >   axp20x file.
> > - fix errors about the regulators and interrupts
> > v2:
> > - fix lack of support of dcdc frequency
> > - notice that the AXP803 is also handled
> > - send the patch to the DT maintainers
> >
> > Jean-Francois Moine (4):
> >   regulator: axp20x: move device independant parts to new files
> >   regulator: axp20x: duplicate the MFD axp20x-rsb code
> >   regulator: axp20x: add the AXP803
> >   regulator: axp20x: add the AXP813
> 
> NAK. Please follow the axp20x mfd and sub-device driver design we
> already have.

Sorry, I will not: installing a lot of useless code and tables in
permanent system memory for just one regulator is not the way I think
about a good kernel.

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2016-09-24  9:23 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-23  8:58 [PATCH v3 0/4] regulator: axp20x: support AXP803/AXP813 variants Jean-Francois Moine
2016-09-23  8:58 ` Jean-Francois Moine
2016-09-23  8:58 ` Jean-Francois Moine
2016-09-22 17:06 ` [PATCH v3 1/4] regulator: axp20x: move device independant parts to new files Jean-Francois Moine
2016-09-22 17:06   ` Jean-Francois Moine
2016-09-22 17:06   ` Jean-Francois Moine
2016-09-22 17:25 ` [PATCH v3 2/4] regulator: axp20x: duplicate the MFD axp20x-rsb code Jean-Francois Moine
2016-09-22 17:25   ` Jean-Francois Moine
2016-09-22 17:25   ` Jean-Francois Moine
2016-09-23  7:00 ` [PATCH v3 3/4] regulator: axp20x: add the AXP803 Jean-Francois Moine
2016-09-23  7:00   ` Jean-Francois Moine
2016-09-23  7:00   ` Jean-Francois Moine
2016-09-23 22:17   ` Rob Herring
2016-09-23 22:17     ` Rob Herring
2016-09-23 22:17     ` Rob Herring
2016-09-23  7:22 ` [PATCH v3 4/4] regulator: axp20x: add the AXP813 Jean-Francois Moine
2016-09-23  7:22   ` Jean-Francois Moine
2016-09-23  7:22   ` Jean-Francois Moine
2016-09-23 22:27   ` Rob Herring
2016-09-23 22:27     ` Rob Herring
2016-09-23 22:27     ` Rob Herring
2016-09-24  8:35 ` [PATCH v3 0/4] regulator: axp20x: support AXP803/AXP813 variants Chen-Yu Tsai
2016-09-24  8:35   ` Chen-Yu Tsai
2016-09-24  8:35   ` Chen-Yu Tsai
2016-09-24  9:11   ` Jean-Francois Moine
2016-09-24  9:11     ` Jean-Francois Moine
2016-09-24  9:11     ` Jean-Francois Moine

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.