[06/16] regulator: madera-ldo1: LDO1 driver for Cirrus Logic Madera codecs
diff mbox

Message ID 1491386884-30689-7-git-send-email-rf@opensource.wolfsonmicro.com
State New
Headers show

Commit Message

Richard Fitzgerald April 5, 2017, 10:07 a.m. UTC
This patch adds a driver for the internal LDO1 regulator on
some Cirrus Logic Madera class codecs.

Signed-off-by: Richard Fitzgerald <rf@opensource.wolfsonmicro.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
---
 .../devicetree/bindings/regulator/madera-ldo1.txt  |  29 +++
 MAINTAINERS                                        |   3 +
 drivers/regulator/Kconfig                          |   8 +
 drivers/regulator/Makefile                         |   1 +
 drivers/regulator/madera-ldo1.c                    | 198 +++++++++++++++++++++
 include/linux/regulator/madera-ldo1.h              |  24 +++
 6 files changed, 263 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/regulator/madera-ldo1.txt
 create mode 100644 drivers/regulator/madera-ldo1.c
 create mode 100644 include/linux/regulator/madera-ldo1.h

Comments

Mark Brown April 5, 2017, 1:28 p.m. UTC | #1
On Wed, Apr 05, 2017 at 11:07:54AM +0100, Richard Fitzgerald wrote:
> This patch adds a driver for the internal LDO1 regulator on
> some Cirrus Logic Madera class codecs.

There appear to be only data differences to the existing arizona driver,
is it possible to share the code?
Rob Herring April 10, 2017, 5:49 p.m. UTC | #2
On Wed, Apr 05, 2017 at 11:07:54AM +0100, Richard Fitzgerald wrote:
> This patch adds a driver for the internal LDO1 regulator on
> some Cirrus Logic Madera class codecs.
> 
> Signed-off-by: Richard Fitzgerald <rf@opensource.wolfsonmicro.com>
> Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
> ---
>  .../devicetree/bindings/regulator/madera-ldo1.txt  |  29 +++

cirrus-madera-ldo1.txt

Or perhaps a subdirectory. We should have done the same for arizona 
bindings.

Same question as Mark. Should this share bindings with arizona? The 
arizona one looks a bit strange, so not sure we'd want to just copy it.

>  MAINTAINERS                                        |   3 +
>  drivers/regulator/Kconfig                          |   8 +
>  drivers/regulator/Makefile                         |   1 +
>  drivers/regulator/madera-ldo1.c                    | 198 +++++++++++++++++++++
>  include/linux/regulator/madera-ldo1.h              |  24 +++
>  6 files changed, 263 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/regulator/madera-ldo1.txt
>  create mode 100644 drivers/regulator/madera-ldo1.c
>  create mode 100644 include/linux/regulator/madera-ldo1.h
> 
> diff --git a/Documentation/devicetree/bindings/regulator/madera-ldo1.txt b/Documentation/devicetree/bindings/regulator/madera-ldo1.txt
> new file mode 100644
> index 0000000..688f21d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/regulator/madera-ldo1.txt
> @@ -0,0 +1,29 @@
> +Cirrus Logic Madera class audio codecs LDO1 regulator driver
> +
> +Only required if you are using the codec internal LDO1 regulator.
> +This is a subnode of the parent mfd node.
> +
> +See also the core bindings for the parent MFD driver:
> +See Documentation/devicetree/bindings/mfd/madera.txt
> +
> +Required properties:
> +  - compatible :  must be "cirrus,madera-ldo1"
> +  - LDOVDD-supply : Power supply for the LDO1 regulator.
> +
> +  - enable-gpio	: GPIO to use to enable/disable the regulator.

enable-gpios

And define whether active high or low.

> +    As defined in bindings/gpio.txt.
> +
> +Optional subnodes:
> +  Standard regulator bindings as described in bindings/regulator/regulator.txt
> +
> +Example:
> +
> +codec: cs47l85@0 {
> +	compatible = "cirrus,cs47l85";
> +
> +	ldo1 {
> +		compatible = "cirrus,madera-ldo1";
> +		LDOVDD-supply = <&pmic_vdd1>;
> +		enable-gpio = <&gpio 0>;
> +	};
> +};
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown April 10, 2017, 6:11 p.m. UTC | #3
On Mon, Apr 10, 2017 at 12:49:17PM -0500, Rob Herring wrote:

> Same question as Mark. Should this share bindings with arizona? The 
> arizona one looks a bit strange, so not sure we'd want to just copy it.

In what way?  Other than the -gpios stuff (which would just be a trivial
thing if we wanted to change it)?
Rob Herring April 11, 2017, 7:20 p.m. UTC | #4
On Mon, Apr 10, 2017 at 1:11 PM, Mark Brown <broonie@kernel.org> wrote:
> On Mon, Apr 10, 2017 at 12:49:17PM -0500, Rob Herring wrote:
>
>> Same question as Mark. Should this share bindings with arizona? The
>> arizona one looks a bit strange, so not sure we'd want to just copy it.
>
> In what way?  Other than the -gpios stuff (which would just be a trivial
> thing if we wanted to change it)?

That's mainly it. It's not clear which node wlf,ldoena goes in either.
In the parent? ldo1?

Rob
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown April 11, 2017, 8:03 p.m. UTC | #5
On Tue, Apr 11, 2017 at 02:20:31PM -0500, Rob Herring wrote:
> On Mon, Apr 10, 2017 at 1:11 PM, Mark Brown <broonie@kernel.org> wrote:

> > In what way?  Other than the -gpios stuff (which would just be a trivial
> > thing if we wanted to change it)?

> That's mainly it.

I don't see that as meaningful or a good reason to duplicate the driver
or the binding, it'd be better to just add the new property and
deprecate the old.

>                   It's not clear which node wlf,ldoena goes in either.
> In the parent? ldo1?

Parent since it's looked up in device context, this is also something
that it seems better to fix in one binding rather than duplicate.

Patch
diff mbox

diff --git a/Documentation/devicetree/bindings/regulator/madera-ldo1.txt b/Documentation/devicetree/bindings/regulator/madera-ldo1.txt
new file mode 100644
index 0000000..688f21d
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/madera-ldo1.txt
@@ -0,0 +1,29 @@ 
+Cirrus Logic Madera class audio codecs LDO1 regulator driver
+
+Only required if you are using the codec internal LDO1 regulator.
+This is a subnode of the parent mfd node.
+
+See also the core bindings for the parent MFD driver:
+See Documentation/devicetree/bindings/mfd/madera.txt
+
+Required properties:
+  - compatible :  must be "cirrus,madera-ldo1"
+  - LDOVDD-supply : Power supply for the LDO1 regulator.
+
+  - enable-gpio	: GPIO to use to enable/disable the regulator.
+    As defined in bindings/gpio.txt.
+
+Optional subnodes:
+  Standard regulator bindings as described in bindings/regulator/regulator.txt
+
+Example:
+
+codec: cs47l85@0 {
+	compatible = "cirrus,cs47l85";
+
+	ldo1 {
+		compatible = "cirrus,madera-ldo1";
+		LDOVDD-supply = <&pmic_vdd1>;
+		enable-gpio = <&gpio 0>;
+	};
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index d28e53f..1207c9c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3267,9 +3267,12 @@  T:	git https://github.com/CirrusLogic/linux-drivers.git
 W:	https://github.com/CirrusLogic/linux-drivers/wiki
 S:	Supported
 F:	Documentation/devicetree/bindings/mfd/madera.txt
+F:	Documentation/devicetree/bindings/regulator/madera*
 F:	include/linux/mfd/madera/*
+F:	include/linux/regulator/madera*
 F:	drivers/mfd/madera*
 F:	drivers/mfd/cs47l*
+F:	drivers/regulator/madera*
 
 CLEANCACHE API
 M:	Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index be06eb2..c96d9a6 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -368,6 +368,14 @@  config REGULATOR_LTC3676
 	  This enables support for the LTC3676
 	  8-output regulators controlled via I2C.
 
+config REGULATOR_MADERA_LDO1
+	tristate "Cirrus Logic Madera codecs LDO1 regulator"
+	depends on MFD_MADERA
+	help
+	  If you want to use the internal LDO1 regulator on CS47L85 and WM1840
+	  to supply DCVDD you must include this driver. If you are using an
+	  external DCVDD regulator you do not need this driver.
+
 config REGULATOR_MAX14577
 	tristate "Maxim 14577/77836 regulator"
 	depends on MFD_MAX14577
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index ef7725e..2db3592 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -49,6 +49,7 @@  obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o
 obj-$(CONFIG_REGULATOR_LP8755) += lp8755.o
 obj-$(CONFIG_REGULATOR_LTC3589) += ltc3589.o
 obj-$(CONFIG_REGULATOR_LTC3676) += ltc3676.o
+obj-$(CONFIG_REGULATOR_MADERA_LDO1) += madera-ldo1.o
 obj-$(CONFIG_REGULATOR_MAX14577) += max14577-regulator.o
 obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
 obj-$(CONFIG_REGULATOR_MAX77620) += max77620-regulator.o
diff --git a/drivers/regulator/madera-ldo1.c b/drivers/regulator/madera-ldo1.c
new file mode 100644
index 0000000..6504d6f
--- /dev/null
+++ b/drivers/regulator/madera-ldo1.c
@@ -0,0 +1,198 @@ 
+/*
+ * madera-ldo1.c  --  Driver for the LDO1 regulator on Madera codecs
+ *
+ * Copyright 2015-2017 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+#include <linux/regulator/madera-ldo1.h>
+
+#include <linux/mfd/madera/core.h>
+#include <linux/mfd/madera/pdata.h>
+#include <linux/mfd/madera/registers.h>
+
+struct madera_ldo1 {
+	struct regulator_dev *regulator;
+
+	struct regulator_consumer_supply supply;
+	struct regulator_init_data init_data;
+};
+
+static const struct regulator_ops madera_ldo1_ops = {
+	.list_voltage = regulator_list_voltage_linear,
+	.map_voltage = regulator_map_voltage_linear,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+};
+
+static const struct regulator_desc madera_ldo1 = {
+	.name = "LDO1",
+	.supply_name = "LDOVDD",
+	.type = REGULATOR_VOLTAGE,
+	.ops = &madera_ldo1_ops,
+
+	.vsel_reg = MADERA_LDO1_CONTROL_1,
+	.vsel_mask = MADERA_LDO1_VSEL_MASK,
+	.min_uV = 900000,
+	.uV_step = 25000,
+	.n_voltages = 13,
+	.enable_time = 3000,
+
+	.owner = THIS_MODULE,
+};
+
+static const struct regulator_init_data madera_ldo1_default = {
+	.constraints = {
+		.min_uV = 1200000,
+		.max_uV = 1200000,
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies = 1,
+};
+
+static int madera_ldo1_of_get_pdata(struct madera *madera,
+				    struct regulator_config *config,
+				    const struct regulator_desc *desc)
+{
+	struct madera_pdata *pdata = &madera->pdata;
+	struct madera_ldo1 *ldo1 = config->driver_data;
+	struct device_node *dcvdd_node;
+	struct regulator_init_data *init_data;
+
+	dcvdd_node = of_parse_phandle(madera->dev->of_node, "DCVDD-supply", 0);
+
+	init_data = of_get_regulator_init_data(config->dev,
+					       config->dev->of_node,
+					       desc);
+	if (init_data) {
+		init_data->consumer_supplies = &ldo1->supply;
+		init_data->num_consumer_supplies = 1;
+		pdata->ldo1.init_data = init_data;
+
+		/* Check whether we're supplying the codec's DCVDD */
+		if (dcvdd_node && dcvdd_node != config->dev->of_node)
+			madera->internal_dcvdd = false;
+	} else if (dcvdd_node) {
+		madera->internal_dcvdd = false;
+	}
+
+	of_node_put(dcvdd_node);
+
+	if (madera->internal_dcvdd) {
+		pdata->ldo1.ldoena = of_get_named_gpio(madera->dev->of_node,
+						       "enable-gpio", 0);
+		if (pdata->ldo1.ldoena < 0)
+			if (pdata->ldo1.ldoena != -ENOENT)
+				dev_warn(madera->dev,
+					 "Malformed enable-gpio ignored: %d\n",
+					 pdata->ldo1.ldoena);
+	}
+
+	return 0;
+}
+
+static int madera_ldo1_probe(struct platform_device *pdev)
+{
+	struct madera *madera = dev_get_drvdata(pdev->dev.parent);
+	const struct regulator_desc *desc;
+	struct regulator_config config = { };
+	struct madera_ldo1 *ldo1;
+	int ret;
+
+	madera->internal_dcvdd = true;
+
+	ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL);
+	if (!ldo1)
+		return -ENOMEM;
+
+	/*
+	 * Since the chip usually supplies itself we provide some
+	 * default init_data for it.  This will be overridden with
+	 * platform data if provided.
+	 */
+	desc = &madera_ldo1;
+	ldo1->init_data = madera_ldo1_default;
+
+	ldo1->init_data.consumer_supplies = &ldo1->supply;
+	ldo1->supply.supply = "DCVDD";
+	ldo1->supply.dev_name = dev_name(madera->dev);
+
+	config.dev = &pdev->dev;
+	config.of_node = config.dev->of_node;
+	config.driver_data = ldo1;
+	config.regmap = madera->regmap;
+
+	/* pdata defaults to 0 if not explicitly set. Convert to invalid. */
+	if (madera->pdata.ldo1.ldoena == 0)
+		madera->pdata.ldo1.ldoena = -EINVAL;
+
+	if (IS_ENABLED(CONFIG_OF)) {
+		if (!dev_get_platdata(madera->dev)) {
+			ret = madera_ldo1_of_get_pdata(madera, &config, desc);
+			if (ret < 0)
+				return ret;
+		}
+	}
+
+	if (madera->pdata.ldo1.init_data)
+		ldo1->init_data = *madera->pdata.ldo1.init_data;
+
+	if (gpio_is_valid(madera->pdata.ldo1.ldoena)) {
+		config.ena_gpio = madera->pdata.ldo1.ldoena;
+		config.ena_gpio_initialized = true;
+	} else {
+		dev_warn(madera->dev,
+			 "Running without LDOENA is not recommended\n");
+	}
+	config.ena_gpio_flags = GPIOF_OUT_INIT_LOW;
+	config.init_data = &ldo1->init_data;
+
+	/*
+	 * LDO1 can only be used to supply DCVDD so if it has no
+	 * consumers then DCVDD is supplied externally.
+	 */
+	if (config.init_data->num_consumer_supplies == 0)
+		madera->internal_dcvdd = false;
+
+	ldo1->regulator = devm_regulator_register(&pdev->dev, desc, &config);
+
+	of_node_put(config.of_node);
+
+	if (IS_ERR(ldo1->regulator)) {
+		ret = PTR_ERR(ldo1->regulator);
+		dev_err(madera->dev, "Failed to register LDO1 supply: %d\n",
+			ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct platform_driver madera_ldo1_driver = {
+	.probe = madera_ldo1_probe,
+	.driver		= {
+		.name	= "madera-ldo1",
+	},
+};
+
+module_platform_driver(madera_ldo1_driver);
+
+MODULE_DESCRIPTION("Madera LDO1 driver");
+MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.wolfsonmicro.com>");
+MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:madera-ldo1");
diff --git a/include/linux/regulator/madera-ldo1.h b/include/linux/regulator/madera-ldo1.h
new file mode 100644
index 0000000..9435021
--- /dev/null
+++ b/include/linux/regulator/madera-ldo1.h
@@ -0,0 +1,24 @@ 
+/*
+ * Platform data for Madera codecs LDO1 regulator
+ *
+ * Copyright 2016-2017 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MADERA_LDO1_H
+#define MADERA_LDO1_H
+
+struct regulator_init_data;
+
+struct madera_ldo1_pdata {
+	/** GPIO controlling LODENA, if any */
+	int ldoena;
+
+	/** Regulator configuration for LDO1 */
+	const struct regulator_init_data *init_data;
+};
+
+#endif