devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/5] iio: dac: mcp4725: use regulator framework, add vref and dt support
@ 2016-10-18 17:43 Tomas Novotny
       [not found] ` <1476812589-18333-1-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
  0 siblings, 1 reply; 12+ messages in thread
From: Tomas Novotny @ 2016-10-18 17:43 UTC (permalink / raw)
  To: Jonathan Cameron, devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald, Rob Herring,
	Mark Rutland, Akinobu Mita, Yong Li,
	linux-iio-u79uwXL29TY76Z2rM5mHXA, Tomas Novotny

From: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>

Hi all,

here is a third version of a series to use regulator framework, add an
option to set external reference and to add devicetree support for
mcp4725/6.

Third version fixes mainly small bits found in the previous version.

Series is tested on MCP4726 on device tree platform.

Changes since v2:
- whitespace fix of two consecutive lines between patches (it affects
  already applied patch)
- abort probe instead of recovery in case of invalid configuration
- use local variable instead of allocation for platform data
- move unrelated comment fix to the new patch
- add ack from Rob
- fix doubled space in an assignment
- add documentation for the struct mcp4725_platform_data
- move the documentation patch forward because it is referenced in struct
  mcp4725_platform_data now
 
Changes since v1:
- add the first patch
- use regulator framework
- fix printf argument (%u instead of %d)
- add parenthesis to make expression more clear
- fix typo in documentation (Microchpip)
- move vref configuration from probe function to new mcp4726_set_cfg

Tomas Novotny (5):
  iio: dac: mcp4725: use regulator framework
  iio: dac: mcp4725: fix incorrect comment
  Documentation: dt: iio: add mcp4725/6 dac device binding
  iio: dac: mcp4725: support voltage reference selection
  iio: dac: mcp4725: add devicetree support

 .../devicetree/bindings/iio/dac/mcp4725.txt        |  35 ++++
 drivers/iio/dac/mcp4725.c                          | 177 +++++++++++++++++++--
 include/linux/iio/dac/mcp4725.h                    |  12 +-
 3 files changed, 206 insertions(+), 18 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/iio/dac/mcp4725.txt

-- 
2.1.4

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

* [PATCH v3 1/5] iio: dac: mcp4725: use regulator framework
       [not found] ` <1476812589-18333-1-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
@ 2016-10-18 17:43   ` Tomas Novotny
       [not found]     ` <1476812589-18333-2-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
  2016-10-18 17:43   ` [PATCH v3 2/5] iio: dac: mcp4725: fix incorrect comment Tomas Novotny
                     ` (3 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: Tomas Novotny @ 2016-10-18 17:43 UTC (permalink / raw)
  To: Jonathan Cameron, devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald, Rob Herring,
	Mark Rutland, Akinobu Mita, Yong Li,
	linux-iio-u79uwXL29TY76Z2rM5mHXA, Tomas Novotny

From: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>

Use a standard framework to get the reference voltage. It is done that way
in the iio subsystem and it will simplify extending of the driver.

Structure mcp4725_platform_data is left undeleted because it used in the
next patch.

This change breaks the current users of the driver, but there is no
mainline user of struct mcp4725_platform_data.

Signed-off-by: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>
---
 drivers/iio/dac/mcp4725.c       | 45 ++++++++++++++++++++++++++++++++---------
 include/linux/iio/dac/mcp4725.h |  1 -
 2 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c
index cca935c..1f55d1b 100644
--- a/drivers/iio/dac/mcp4725.c
+++ b/drivers/iio/dac/mcp4725.c
@@ -18,6 +18,7 @@
 #include <linux/i2c.h>
 #include <linux/err.h>
 #include <linux/delay.h>
+#include <linux/regulator/consumer.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
@@ -28,10 +29,10 @@
 
 struct mcp4725_data {
 	struct i2c_client *client;
-	u16 vref_mv;
 	u16 dac_value;
 	bool powerdown;
 	unsigned powerdown_mode;
+	struct regulator *vdd_reg;
 };
 
 static int mcp4725_suspend(struct device *dev)
@@ -283,13 +284,18 @@ static int mcp4725_read_raw(struct iio_dev *indio_dev,
 			   int *val, int *val2, long mask)
 {
 	struct mcp4725_data *data = iio_priv(indio_dev);
+	int ret;
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
 		*val = data->dac_value;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		*val = data->vref_mv;
+		ret = regulator_get_voltage(data->vdd_reg);
+		if (ret < 0)
+			return ret;
+
+		*val = ret / 1000;
 		*val2 = 12;
 		return IIO_VAL_FRACTIONAL_LOG2;
 	}
@@ -328,12 +334,12 @@ static int mcp4725_probe(struct i2c_client *client,
 {
 	struct mcp4725_data *data;
 	struct iio_dev *indio_dev;
-	struct mcp4725_platform_data *platform_data = client->dev.platform_data;
+	struct mcp4725_platform_data *pdata = dev_get_platdata(&client->dev);
 	u8 inbuf[3];
 	u8 pd;
 	int err;
 
-	if (!platform_data || !platform_data->vref_mv) {
+	if (!pdata) {
 		dev_err(&client->dev, "invalid platform data");
 		return -EINVAL;
 	}
@@ -345,6 +351,14 @@ static int mcp4725_probe(struct i2c_client *client,
 	i2c_set_clientdata(client, indio_dev);
 	data->client = client;
 
+	data->vdd_reg = devm_regulator_get(&client->dev, "vdd");
+	if (IS_ERR(data->vdd_reg))
+		return PTR_ERR(data->vdd_reg);
+
+	err = regulator_enable(data->vdd_reg);
+	if (err)
+		return err;
+
 	indio_dev->dev.parent = &client->dev;
 	indio_dev->name = id->name;
 	indio_dev->info = &mcp4725_info;
@@ -352,25 +366,38 @@ static int mcp4725_probe(struct i2c_client *client,
 	indio_dev->num_channels = 1;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	data->vref_mv = platform_data->vref_mv;
-
 	/* read current DAC value */
 	err = i2c_master_recv(client, inbuf, 3);
 	if (err < 0) {
 		dev_err(&client->dev, "failed to read DAC value");
-		return err;
+		goto err_disable_vdd_reg;
 	}
 	pd = (inbuf[0] >> 1) & 0x3;
 	data->powerdown = pd > 0 ? true : false;
 	data->powerdown_mode = pd ? pd - 1 : 2; /* largest register to gnd */
 	data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);
 
-	return iio_device_register(indio_dev);
+	err = iio_device_register(indio_dev);
+	if (err)
+		goto err_disable_vdd_reg;
+
+	return 0;
+
+err_disable_vdd_reg:
+	regulator_disable(data->vdd_reg);
+
+	return err;
 }
 
 static int mcp4725_remove(struct i2c_client *client)
 {
-	iio_device_unregister(i2c_get_clientdata(client));
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct mcp4725_data *data = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+
+	regulator_disable(data->vdd_reg);
+
 	return 0;
 }
 
diff --git a/include/linux/iio/dac/mcp4725.h b/include/linux/iio/dac/mcp4725.h
index 91530e6..7c062e8 100644
--- a/include/linux/iio/dac/mcp4725.h
+++ b/include/linux/iio/dac/mcp4725.h
@@ -10,7 +10,6 @@
 #define IIO_DAC_MCP4725_H_
 
 struct mcp4725_platform_data {
-	u16 vref_mv;
 };
 
 #endif /* IIO_DAC_MCP4725_H_ */
-- 
2.1.4

--
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 related	[flat|nested] 12+ messages in thread

* [PATCH v3 2/5] iio: dac: mcp4725: fix incorrect comment
       [not found] ` <1476812589-18333-1-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
  2016-10-18 17:43   ` [PATCH v3 1/5] iio: dac: mcp4725: use regulator framework Tomas Novotny
@ 2016-10-18 17:43   ` Tomas Novotny
       [not found]     ` <1476812589-18333-3-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
  2016-10-18 17:43   ` [PATCH v3 3/5] Documentation: dt: iio: add mcp4725/6 dac device binding Tomas Novotny
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: Tomas Novotny @ 2016-10-18 17:43 UTC (permalink / raw)
  To: Jonathan Cameron, devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald, Rob Herring,
	Mark Rutland, Akinobu Mita, Yong Li,
	linux-iio-u79uwXL29TY76Z2rM5mHXA, Tomas Novotny

From: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>

Number 2 is referencing to the settings with the largest available
resistor.

No functional change.

Signed-off-by: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>
---
 drivers/iio/dac/mcp4725.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c
index 1f55d1b..e481f38 100644
--- a/drivers/iio/dac/mcp4725.c
+++ b/drivers/iio/dac/mcp4725.c
@@ -374,7 +374,7 @@ static int mcp4725_probe(struct i2c_client *client,
 	}
 	pd = (inbuf[0] >> 1) & 0x3;
 	data->powerdown = pd > 0 ? true : false;
-	data->powerdown_mode = pd ? pd - 1 : 2; /* largest register to gnd */
+	data->powerdown_mode = pd ? pd - 1 : 2; /* largest resistor to gnd */
 	data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);
 
 	err = iio_device_register(indio_dev);
-- 
2.1.4

--
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 related	[flat|nested] 12+ messages in thread

* [PATCH v3 3/5] Documentation: dt: iio: add mcp4725/6 dac device binding
       [not found] ` <1476812589-18333-1-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
  2016-10-18 17:43   ` [PATCH v3 1/5] iio: dac: mcp4725: use regulator framework Tomas Novotny
  2016-10-18 17:43   ` [PATCH v3 2/5] iio: dac: mcp4725: fix incorrect comment Tomas Novotny
@ 2016-10-18 17:43   ` Tomas Novotny
       [not found]     ` <1476812589-18333-4-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
  2016-10-18 17:43   ` [PATCH v3 4/5] iio: dac: mcp4725: support voltage reference selection Tomas Novotny
  2016-10-18 17:43   ` [PATCH v3 5/5] iio: dac: mcp4725: add devicetree support Tomas Novotny
  4 siblings, 1 reply; 12+ messages in thread
From: Tomas Novotny @ 2016-10-18 17:43 UTC (permalink / raw)
  To: Jonathan Cameron, devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald, Rob Herring,
	Mark Rutland, Akinobu Mita, Yong Li,
	linux-iio-u79uwXL29TY76Z2rM5mHXA, Tomas Novotny

From: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>

Signed-off-by: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 .../devicetree/bindings/iio/dac/mcp4725.txt        | 35 ++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/dac/mcp4725.txt

diff --git a/Documentation/devicetree/bindings/iio/dac/mcp4725.txt b/Documentation/devicetree/bindings/iio/dac/mcp4725.txt
new file mode 100644
index 0000000..1bc6c09
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/mcp4725.txt
@@ -0,0 +1,35 @@
+Microchip mcp4725 and mcp4726 DAC device driver
+
+Required properties:
+	- compatible: Must be "microchip,mcp4725" or "microchip,mcp4726"
+	- reg: Should contain the DAC I2C address
+	- vdd-supply: Phandle to the Vdd power supply. This supply is used as a
+	  voltage reference on mcp4725. It is used as a voltage reference on
+	  mcp4726 if there is no vref-supply specified.
+
+Optional properties (valid only for mcp4726):
+	- vref-supply: Optional phandle to the Vref power supply. Vref pin is
+	  used as a voltage reference when this supply is specified.
+	- microchip,vref-buffered: Boolean to enable buffering of the external
+	  Vref pin. This boolean is not valid without the vref-supply. Quoting
+	  the datasheet: This is offered in cases where the reference voltage
+	  does not have the current capability not to drop its voltage when
+	  connected to the internal resistor ladder circuit.
+
+Examples:
+
+	/* simple mcp4725 */
+	mcp4725@60 {
+		compatible = "microchip,mcp4725";
+		reg = <0x60>;
+		vdd-supply = <&vdac_vdd>;
+	};
+
+	/* mcp4726 with the buffered external reference voltage */
+	mcp4726@60 {
+		compatible = "microchip,mcp4726";
+		reg = <0x60>;
+		vdd-supply = <&vdac_vdd>;
+		vref-supply = <&vdac_vref>;
+		microchip,vref-buffered;
+	};
-- 
2.1.4

--
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 related	[flat|nested] 12+ messages in thread

* [PATCH v3 4/5] iio: dac: mcp4725: support voltage reference selection
       [not found] ` <1476812589-18333-1-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
                     ` (2 preceding siblings ...)
  2016-10-18 17:43   ` [PATCH v3 3/5] Documentation: dt: iio: add mcp4725/6 dac device binding Tomas Novotny
@ 2016-10-18 17:43   ` Tomas Novotny
       [not found]     ` <1476812589-18333-5-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
  2016-10-18 17:43   ` [PATCH v3 5/5] iio: dac: mcp4725: add devicetree support Tomas Novotny
  4 siblings, 1 reply; 12+ messages in thread
From: Tomas Novotny @ 2016-10-18 17:43 UTC (permalink / raw)
  To: Jonathan Cameron, devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald, Rob Herring,
	Mark Rutland, Akinobu Mita, Yong Li,
	linux-iio-u79uwXL29TY76Z2rM5mHXA, Tomas Novotny

From: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>

MCP47x6 chip supports selection of a voltage reference (VDD, VREF buffered
or unbuffered). MCP4725 doesn't have this feature thus the eventual setting
is ignored and user is warned.

The setting is stored only in the volatile memory of the chip. You need to
manually store it to the EEPROM of the chip via 'store_eeprom' sysfs entry.

Signed-off-by: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>
---
 drivers/iio/dac/mcp4725.c       | 97 ++++++++++++++++++++++++++++++++++++++---
 include/linux/iio/dac/mcp4725.h | 11 +++++
 2 files changed, 102 insertions(+), 6 deletions(-)

diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c
index e481f38..83d431f 100644
--- a/drivers/iio/dac/mcp4725.c
+++ b/drivers/iio/dac/mcp4725.c
@@ -27,12 +27,20 @@
 
 #define MCP4725_DRV_NAME "mcp4725"
 
+#define MCP472X_REF_VDD			0x00
+#define MCP472X_REF_VREF_UNBUFFERED	0x02
+#define MCP472X_REF_VREF_BUFFERED	0x03
+
 struct mcp4725_data {
 	struct i2c_client *client;
+	int id;
+	unsigned ref_mode;
+	bool vref_buffered;
 	u16 dac_value;
 	bool powerdown;
 	unsigned powerdown_mode;
 	struct regulator *vdd_reg;
+	struct regulator *vref_reg;
 };
 
 static int mcp4725_suspend(struct device *dev)
@@ -87,6 +95,7 @@ static ssize_t mcp4725_store_eeprom(struct device *dev,
 		return 0;
 
 	inoutbuf[0] = 0x60; /* write EEPROM */
+	inoutbuf[0] |= data->ref_mode << 3;
 	inoutbuf[1] = data->dac_value >> 4;
 	inoutbuf[2] = (data->dac_value & 0xf) << 4;
 
@@ -279,6 +288,28 @@ static int mcp4725_set_value(struct iio_dev *indio_dev, int val)
 		return 0;
 }
 
+static int mcp4726_set_cfg(struct iio_dev *indio_dev)
+{
+	struct mcp4725_data *data = iio_priv(indio_dev);
+	u8 outbuf[3];
+	int ret;
+
+	outbuf[0] = 0x40;
+	outbuf[0] |= data->ref_mode << 3;
+	if (data->powerdown)
+		outbuf[0] |= data->powerdown << 1;
+	outbuf[1] = data->dac_value >> 4;
+	outbuf[2] = (data->dac_value & 0xf) << 4;
+
+	ret = i2c_master_send(data->client, outbuf, 3);
+	if (ret < 0)
+		return ret;
+	else if (ret != 3)
+		return -EIO;
+	else
+		return 0;
+}
+
 static int mcp4725_read_raw(struct iio_dev *indio_dev,
 			   struct iio_chan_spec const *chan,
 			   int *val, int *val2, long mask)
@@ -291,7 +322,11 @@ static int mcp4725_read_raw(struct iio_dev *indio_dev,
 		*val = data->dac_value;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		ret = regulator_get_voltage(data->vdd_reg);
+		if (data->ref_mode == MCP472X_REF_VDD)
+			ret = regulator_get_voltage(data->vdd_reg);
+		else
+			ret = regulator_get_voltage(data->vref_reg);
+
 		if (ret < 0)
 			return ret;
 
@@ -335,8 +370,9 @@ static int mcp4725_probe(struct i2c_client *client,
 	struct mcp4725_data *data;
 	struct iio_dev *indio_dev;
 	struct mcp4725_platform_data *pdata = dev_get_platdata(&client->dev);
-	u8 inbuf[3];
+	u8 inbuf[4];
 	u8 pd;
+	u8 ref;
 	int err;
 
 	if (!pdata) {
@@ -350,6 +386,26 @@ static int mcp4725_probe(struct i2c_client *client,
 	data = iio_priv(indio_dev);
 	i2c_set_clientdata(client, indio_dev);
 	data->client = client;
+	data->id = id->driver_data;
+
+	if (data->id == MCP4725 && pdata->use_vref) {
+		dev_err(&client->dev,
+			"external reference is unavailable on MCP4725");
+		return -EINVAL;
+	}
+
+	if (!pdata->use_vref && pdata->vref_buffered) {
+		dev_err(&client->dev,
+			"buffering is unavailable on the internal reference");
+		return -EINVAL;
+	}
+
+	if (!pdata->use_vref)
+		data->ref_mode = MCP472X_REF_VDD;
+	else
+		data->ref_mode = pdata->vref_buffered ?
+			MCP472X_REF_VREF_BUFFERED :
+			MCP472X_REF_VREF_UNBUFFERED;
 
 	data->vdd_reg = devm_regulator_get(&client->dev, "vdd");
 	if (IS_ERR(data->vdd_reg))
@@ -359,6 +415,18 @@ static int mcp4725_probe(struct i2c_client *client,
 	if (err)
 		return err;
 
+	if (pdata->use_vref) {
+		data->vref_reg = devm_regulator_get(&client->dev, "vref");
+		if (IS_ERR(data->vref_reg)) {
+			err = PTR_ERR(data->vdd_reg);
+			goto err_disable_vdd_reg;
+		}
+
+		err = regulator_enable(data->vref_reg);
+		if (err)
+			goto err_disable_vdd_reg;
+	}
+
 	indio_dev->dev.parent = &client->dev;
 	indio_dev->name = id->name;
 	indio_dev->info = &mcp4725_info;
@@ -366,23 +434,38 @@ static int mcp4725_probe(struct i2c_client *client,
 	indio_dev->num_channels = 1;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	/* read current DAC value */
-	err = i2c_master_recv(client, inbuf, 3);
+	/* read current DAC value and settings */
+	err = i2c_master_recv(client, inbuf, data->id == MCP4725 ? 3 : 4);
 	if (err < 0) {
 		dev_err(&client->dev, "failed to read DAC value");
-		goto err_disable_vdd_reg;
+		goto err_disable_vref_reg;
 	}
 	pd = (inbuf[0] >> 1) & 0x3;
 	data->powerdown = pd > 0 ? true : false;
 	data->powerdown_mode = pd ? pd - 1 : 2; /* largest resistor to gnd */
 	data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);
+	if (data->id == MCP4726)
+		ref = (inbuf[3] >> 3) & 0x3;
+
+	if (data->id == MCP4726 && ref != data->ref_mode) {
+		dev_info(&client->dev,
+			"voltage reference mode differs (conf: %u, eeprom: %u), setting %u",
+			data->ref_mode, ref, data->ref_mode);
+		err = mcp4726_set_cfg(indio_dev);
+		if (err < 0)
+			goto err_disable_vref_reg;
+	}
 
 	err = iio_device_register(indio_dev);
 	if (err)
-		goto err_disable_vdd_reg;
+		goto err_disable_vref_reg;
 
 	return 0;
 
+err_disable_vref_reg:
+	if (data->vref_reg)
+		regulator_disable(data->vref_reg);
+
 err_disable_vdd_reg:
 	regulator_disable(data->vdd_reg);
 
@@ -396,6 +479,8 @@ static int mcp4725_remove(struct i2c_client *client)
 
 	iio_device_unregister(indio_dev);
 
+	if (data->vref_reg)
+		regulator_disable(data->vref_reg);
 	regulator_disable(data->vdd_reg);
 
 	return 0;
diff --git a/include/linux/iio/dac/mcp4725.h b/include/linux/iio/dac/mcp4725.h
index 7c062e8..628b2cf 100644
--- a/include/linux/iio/dac/mcp4725.h
+++ b/include/linux/iio/dac/mcp4725.h
@@ -9,7 +9,18 @@
 #ifndef IIO_DAC_MCP4725_H_
 #define IIO_DAC_MCP4725_H_
 
+/**
+ * struct mcp4725_platform_data - MCP4725/6 DAC specific data.
+ * @use_vref: Whether an external reference voltage on Vref pin should be used.
+ *            Additional vref-supply must be specified when used.
+ * @vref_buffered: Controls buffering of the external reference voltage.
+ *
+ * Vref related settings are available only on MCP4756. See
+ * Documentation/devicetree/bindings/iio/dac/mcp4725.txt for more information.
+ */
 struct mcp4725_platform_data {
+	bool use_vref;
+	bool vref_buffered;
 };
 
 #endif /* IIO_DAC_MCP4725_H_ */
-- 
2.1.4

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

* [PATCH v3 5/5] iio: dac: mcp4725: add devicetree support
       [not found] ` <1476812589-18333-1-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
                     ` (3 preceding siblings ...)
  2016-10-18 17:43   ` [PATCH v3 4/5] iio: dac: mcp4725: support voltage reference selection Tomas Novotny
@ 2016-10-18 17:43   ` Tomas Novotny
       [not found]     ` <1476812589-18333-6-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
  4 siblings, 1 reply; 12+ messages in thread
From: Tomas Novotny @ 2016-10-18 17:43 UTC (permalink / raw)
  To: Jonathan Cameron, devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald, Rob Herring,
	Mark Rutland, Akinobu Mita, Yong Li,
	linux-iio-u79uwXL29TY76Z2rM5mHXA, Tomas Novotny

From: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>

Signed-off-by: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>
---
 drivers/iio/dac/mcp4725.c | 43 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 37 insertions(+), 6 deletions(-)

diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c
index 83d431f..05f7f4d 100644
--- a/drivers/iio/dac/mcp4725.c
+++ b/drivers/iio/dac/mcp4725.c
@@ -19,6 +19,7 @@
 #include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/regulator/consumer.h>
+#include <linux/of.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
@@ -364,22 +365,41 @@ static const struct iio_info mcp4725_info = {
 	.driver_module = THIS_MODULE,
 };
 
+#ifdef CONFIG_OF
+static int mcp4725_probe_dt(struct device *dev,
+			    struct mcp4725_platform_data *pdata)
+{
+	struct device_node *np = dev->of_node;
+
+	if (!np)
+		return -ENODEV;
+
+	/* check if is the vref-supply defined */
+	pdata->use_vref = of_property_read_bool(np, "vref-supply");
+	pdata->vref_buffered =
+		of_property_read_bool(np, "microchip,vref-buffered");
+
+	return 0;
+}
+#else
+static int mcp4725_probe_dt(struct device *dev,
+			    struct mcp4725_platform_data *platform_data)
+{
+	return -ENODEV;
+}
+#endif
+
 static int mcp4725_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct mcp4725_data *data;
 	struct iio_dev *indio_dev;
-	struct mcp4725_platform_data *pdata = dev_get_platdata(&client->dev);
+	struct mcp4725_platform_data *pdata, pdata_dt;
 	u8 inbuf[4];
 	u8 pd;
 	u8 ref;
 	int err;
 
-	if (!pdata) {
-		dev_err(&client->dev, "invalid platform data");
-		return -EINVAL;
-	}
-
 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 	if (indio_dev == NULL)
 		return -ENOMEM;
@@ -387,6 +407,17 @@ static int mcp4725_probe(struct i2c_client *client,
 	i2c_set_clientdata(client, indio_dev);
 	data->client = client;
 	data->id = id->driver_data;
+	pdata = dev_get_platdata(&client->dev);
+
+	if (!pdata) {
+		err = mcp4725_probe_dt(&client->dev, &pdata_dt);
+		if (err) {
+			dev_err(&client->dev,
+				"invalid platform or devicetree data");
+			return err;
+		}
+		pdata = &pdata_dt;
+	}
 
 	if (data->id == MCP4725 && pdata->use_vref) {
 		dev_err(&client->dev,
-- 
2.1.4

--
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 related	[flat|nested] 12+ messages in thread

* Re: [PATCH v3 1/5] iio: dac: mcp4725: use regulator framework
       [not found]     ` <1476812589-18333-2-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
@ 2016-10-22 18:01       ` Jonathan Cameron
  0 siblings, 0 replies; 12+ messages in thread
From: Jonathan Cameron @ 2016-10-22 18:01 UTC (permalink / raw)
  To: Tomas Novotny, devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald, Rob Herring,
	Mark Rutland, Akinobu Mita, Yong Li,
	linux-iio-u79uwXL29TY76Z2rM5mHXA, Tomas Novotny

On 18/10/16 18:43, Tomas Novotny wrote:
> From: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>
> 
> Use a standard framework to get the reference voltage. It is done that way
> in the iio subsystem and it will simplify extending of the driver.
> 
> Structure mcp4725_platform_data is left undeleted because it used in the
> next patch.
> 
> This change breaks the current users of the driver, but there is no
> mainline user of struct mcp4725_platform_data.
> 
> Signed-off-by: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>
I've already applied this from V2.

Thanks,

Jonathan
> ---
>  drivers/iio/dac/mcp4725.c       | 45 ++++++++++++++++++++++++++++++++---------
>  include/linux/iio/dac/mcp4725.h |  1 -
>  2 files changed, 36 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c
> index cca935c..1f55d1b 100644
> --- a/drivers/iio/dac/mcp4725.c
> +++ b/drivers/iio/dac/mcp4725.c
> @@ -18,6 +18,7 @@
>  #include <linux/i2c.h>
>  #include <linux/err.h>
>  #include <linux/delay.h>
> +#include <linux/regulator/consumer.h>
>  
>  #include <linux/iio/iio.h>
>  #include <linux/iio/sysfs.h>
> @@ -28,10 +29,10 @@
>  
>  struct mcp4725_data {
>  	struct i2c_client *client;
> -	u16 vref_mv;
>  	u16 dac_value;
>  	bool powerdown;
>  	unsigned powerdown_mode;
> +	struct regulator *vdd_reg;
>  };
>  
>  static int mcp4725_suspend(struct device *dev)
> @@ -283,13 +284,18 @@ static int mcp4725_read_raw(struct iio_dev *indio_dev,
>  			   int *val, int *val2, long mask)
>  {
>  	struct mcp4725_data *data = iio_priv(indio_dev);
> +	int ret;
>  
>  	switch (mask) {
>  	case IIO_CHAN_INFO_RAW:
>  		*val = data->dac_value;
>  		return IIO_VAL_INT;
>  	case IIO_CHAN_INFO_SCALE:
> -		*val = data->vref_mv;
> +		ret = regulator_get_voltage(data->vdd_reg);
> +		if (ret < 0)
> +			return ret;
> +
> +		*val = ret / 1000;
>  		*val2 = 12;
>  		return IIO_VAL_FRACTIONAL_LOG2;
>  	}
> @@ -328,12 +334,12 @@ static int mcp4725_probe(struct i2c_client *client,
>  {
>  	struct mcp4725_data *data;
>  	struct iio_dev *indio_dev;
> -	struct mcp4725_platform_data *platform_data = client->dev.platform_data;
> +	struct mcp4725_platform_data *pdata = dev_get_platdata(&client->dev);
>  	u8 inbuf[3];
>  	u8 pd;
>  	int err;
>  
> -	if (!platform_data || !platform_data->vref_mv) {
> +	if (!pdata) {
>  		dev_err(&client->dev, "invalid platform data");
>  		return -EINVAL;
>  	}
> @@ -345,6 +351,14 @@ static int mcp4725_probe(struct i2c_client *client,
>  	i2c_set_clientdata(client, indio_dev);
>  	data->client = client;
>  
> +	data->vdd_reg = devm_regulator_get(&client->dev, "vdd");
> +	if (IS_ERR(data->vdd_reg))
> +		return PTR_ERR(data->vdd_reg);
> +
> +	err = regulator_enable(data->vdd_reg);
> +	if (err)
> +		return err;
> +
>  	indio_dev->dev.parent = &client->dev;
>  	indio_dev->name = id->name;
>  	indio_dev->info = &mcp4725_info;
> @@ -352,25 +366,38 @@ static int mcp4725_probe(struct i2c_client *client,
>  	indio_dev->num_channels = 1;
>  	indio_dev->modes = INDIO_DIRECT_MODE;
>  
> -	data->vref_mv = platform_data->vref_mv;
> -
>  	/* read current DAC value */
>  	err = i2c_master_recv(client, inbuf, 3);
>  	if (err < 0) {
>  		dev_err(&client->dev, "failed to read DAC value");
> -		return err;
> +		goto err_disable_vdd_reg;
>  	}
>  	pd = (inbuf[0] >> 1) & 0x3;
>  	data->powerdown = pd > 0 ? true : false;
>  	data->powerdown_mode = pd ? pd - 1 : 2; /* largest register to gnd */
>  	data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);
>  
> -	return iio_device_register(indio_dev);
> +	err = iio_device_register(indio_dev);
> +	if (err)
> +		goto err_disable_vdd_reg;
> +
> +	return 0;
> +
> +err_disable_vdd_reg:
> +	regulator_disable(data->vdd_reg);
> +
> +	return err;
>  }
>  
>  static int mcp4725_remove(struct i2c_client *client)
>  {
> -	iio_device_unregister(i2c_get_clientdata(client));
> +	struct iio_dev *indio_dev = i2c_get_clientdata(client);
> +	struct mcp4725_data *data = iio_priv(indio_dev);
> +
> +	iio_device_unregister(indio_dev);
> +
> +	regulator_disable(data->vdd_reg);
> +
>  	return 0;
>  }
>  
> diff --git a/include/linux/iio/dac/mcp4725.h b/include/linux/iio/dac/mcp4725.h
> index 91530e6..7c062e8 100644
> --- a/include/linux/iio/dac/mcp4725.h
> +++ b/include/linux/iio/dac/mcp4725.h
> @@ -10,7 +10,6 @@
>  #define IIO_DAC_MCP4725_H_
>  
>  struct mcp4725_platform_data {
> -	u16 vref_mv;
>  };
>  
>  #endif /* IIO_DAC_MCP4725_H_ */
> 

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

* Re: [PATCH v3 2/5] iio: dac: mcp4725: fix incorrect comment
       [not found]     ` <1476812589-18333-3-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
@ 2016-10-22 18:02       ` Jonathan Cameron
  0 siblings, 0 replies; 12+ messages in thread
From: Jonathan Cameron @ 2016-10-22 18:02 UTC (permalink / raw)
  To: Tomas Novotny, devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald, Rob Herring,
	Mark Rutland, Akinobu Mita, Yong Li,
	linux-iio-u79uwXL29TY76Z2rM5mHXA, Tomas Novotny

On 18/10/16 18:43, Tomas Novotny wrote:
> From: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>
> 
> Number 2 is referencing to the settings with the largest available
> resistor.
> 
> No functional change.
> 
> Signed-off-by: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>
Thanks,

Applied to the togreg branch of iio.git and pushed out as testing.

Jonathan
> ---
>  drivers/iio/dac/mcp4725.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c
> index 1f55d1b..e481f38 100644
> --- a/drivers/iio/dac/mcp4725.c
> +++ b/drivers/iio/dac/mcp4725.c
> @@ -374,7 +374,7 @@ static int mcp4725_probe(struct i2c_client *client,
>  	}
>  	pd = (inbuf[0] >> 1) & 0x3;
>  	data->powerdown = pd > 0 ? true : false;
> -	data->powerdown_mode = pd ? pd - 1 : 2; /* largest register to gnd */
> +	data->powerdown_mode = pd ? pd - 1 : 2; /* largest resistor to gnd */
>  	data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);
>  
>  	err = iio_device_register(indio_dev);
> 

--
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] 12+ messages in thread

* Re: [PATCH v3 3/5] Documentation: dt: iio: add mcp4725/6 dac device binding
       [not found]     ` <1476812589-18333-4-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
@ 2016-10-22 18:02       ` Jonathan Cameron
  0 siblings, 0 replies; 12+ messages in thread
From: Jonathan Cameron @ 2016-10-22 18:02 UTC (permalink / raw)
  To: Tomas Novotny, devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald, Rob Herring,
	Mark Rutland, Akinobu Mita, Yong Li,
	linux-iio-u79uwXL29TY76Z2rM5mHXA, Tomas Novotny

On 18/10/16 18:43, Tomas Novotny wrote:
> From: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>
> 
> Signed-off-by: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>
> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Applied. Thanks,

Jonathan
> ---
>  .../devicetree/bindings/iio/dac/mcp4725.txt        | 35 ++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/iio/dac/mcp4725.txt
> 
> diff --git a/Documentation/devicetree/bindings/iio/dac/mcp4725.txt b/Documentation/devicetree/bindings/iio/dac/mcp4725.txt
> new file mode 100644
> index 0000000..1bc6c09
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/dac/mcp4725.txt
> @@ -0,0 +1,35 @@
> +Microchip mcp4725 and mcp4726 DAC device driver
> +
> +Required properties:
> +	- compatible: Must be "microchip,mcp4725" or "microchip,mcp4726"
> +	- reg: Should contain the DAC I2C address
> +	- vdd-supply: Phandle to the Vdd power supply. This supply is used as a
> +	  voltage reference on mcp4725. It is used as a voltage reference on
> +	  mcp4726 if there is no vref-supply specified.
> +
> +Optional properties (valid only for mcp4726):
> +	- vref-supply: Optional phandle to the Vref power supply. Vref pin is
> +	  used as a voltage reference when this supply is specified.
> +	- microchip,vref-buffered: Boolean to enable buffering of the external
> +	  Vref pin. This boolean is not valid without the vref-supply. Quoting
> +	  the datasheet: This is offered in cases where the reference voltage
> +	  does not have the current capability not to drop its voltage when
> +	  connected to the internal resistor ladder circuit.
> +
> +Examples:
> +
> +	/* simple mcp4725 */
> +	mcp4725@60 {
> +		compatible = "microchip,mcp4725";
> +		reg = <0x60>;
> +		vdd-supply = <&vdac_vdd>;
> +	};
> +
> +	/* mcp4726 with the buffered external reference voltage */
> +	mcp4726@60 {
> +		compatible = "microchip,mcp4726";
> +		reg = <0x60>;
> +		vdd-supply = <&vdac_vdd>;
> +		vref-supply = <&vdac_vref>;
> +		microchip,vref-buffered;
> +	};
> 

--
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] 12+ messages in thread

* Re: [PATCH v3 4/5] iio: dac: mcp4725: support voltage reference selection
       [not found]     ` <1476812589-18333-5-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
@ 2016-10-22 18:18       ` Jonathan Cameron
       [not found]         ` <2a820b1f-b6d7-88f9-7403-06a1c5e3b2ee-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
  0 siblings, 1 reply; 12+ messages in thread
From: Jonathan Cameron @ 2016-10-22 18:18 UTC (permalink / raw)
  To: Tomas Novotny, devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald, Rob Herring,
	Mark Rutland, Akinobu Mita, Yong Li,
	linux-iio-u79uwXL29TY76Z2rM5mHXA, Tomas Novotny

On 18/10/16 18:43, Tomas Novotny wrote:
> From: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>
> 
> MCP47x6 chip supports selection of a voltage reference (VDD, VREF buffered
> or unbuffered). MCP4725 doesn't have this feature thus the eventual setting
> is ignored and user is warned.
> 
> The setting is stored only in the volatile memory of the chip. You need to
> manually store it to the EEPROM of the chip via 'store_eeprom' sysfs entry.
> 
> Signed-off-by: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>
Something odd happened and this patch wouldn't apply without some manual
intervention.

Please check the result in the testing branch of iio.git.

Thanks,

Jonathan
> ---
>  drivers/iio/dac/mcp4725.c       | 97 ++++++++++++++++++++++++++++++++++++++---
>  include/linux/iio/dac/mcp4725.h | 11 +++++
>  2 files changed, 102 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c
> index e481f38..83d431f 100644
> --- a/drivers/iio/dac/mcp4725.c
> +++ b/drivers/iio/dac/mcp4725.c
> @@ -27,12 +27,20 @@
>  
>  #define MCP4725_DRV_NAME "mcp4725"
>  
> +#define MCP472X_REF_VDD			0x00
> +#define MCP472X_REF_VREF_UNBUFFERED	0x02
> +#define MCP472X_REF_VREF_BUFFERED	0x03
> +
>  struct mcp4725_data {
>  	struct i2c_client *client;
> +	int id;
> +	unsigned ref_mode;
> +	bool vref_buffered;
>  	u16 dac_value;
>  	bool powerdown;
>  	unsigned powerdown_mode;
>  	struct regulator *vdd_reg;
> +	struct regulator *vref_reg;
>  };
>  
>  static int mcp4725_suspend(struct device *dev)
> @@ -87,6 +95,7 @@ static ssize_t mcp4725_store_eeprom(struct device *dev,
>  		return 0;
>  
>  	inoutbuf[0] = 0x60; /* write EEPROM */
> +	inoutbuf[0] |= data->ref_mode << 3;
>  	inoutbuf[1] = data->dac_value >> 4;
>  	inoutbuf[2] = (data->dac_value & 0xf) << 4;
>  
> @@ -279,6 +288,28 @@ static int mcp4725_set_value(struct iio_dev *indio_dev, int val)
>  		return 0;
>  }
>  
> +static int mcp4726_set_cfg(struct iio_dev *indio_dev)
> +{
> +	struct mcp4725_data *data = iio_priv(indio_dev);
> +	u8 outbuf[3];
> +	int ret;
> +
> +	outbuf[0] = 0x40;
> +	outbuf[0] |= data->ref_mode << 3;
> +	if (data->powerdown)
> +		outbuf[0] |= data->powerdown << 1;
> +	outbuf[1] = data->dac_value >> 4;
> +	outbuf[2] = (data->dac_value & 0xf) << 4;
> +
> +	ret = i2c_master_send(data->client, outbuf, 3);
> +	if (ret < 0)
> +		return ret;
> +	else if (ret != 3)
> +		return -EIO;
> +	else
> +		return 0;
> +}
> +
>  static int mcp4725_read_raw(struct iio_dev *indio_dev,
>  			   struct iio_chan_spec const *chan,
>  			   int *val, int *val2, long mask)
> @@ -291,7 +322,11 @@ static int mcp4725_read_raw(struct iio_dev *indio_dev,
>  		*val = data->dac_value;
>  		return IIO_VAL_INT;
>  	case IIO_CHAN_INFO_SCALE:
> -		ret = regulator_get_voltage(data->vdd_reg);
> +		if (data->ref_mode == MCP472X_REF_VDD)
> +			ret = regulator_get_voltage(data->vdd_reg);
> +		else
> +			ret = regulator_get_voltage(data->vref_reg);
> +
>  		if (ret < 0)
>  			return ret;
>  
> @@ -335,8 +370,9 @@ static int mcp4725_probe(struct i2c_client *client,
>  	struct mcp4725_data *data;
>  	struct iio_dev *indio_dev;
>  	struct mcp4725_platform_data *pdata = dev_get_platdata(&client->dev);
> -	u8 inbuf[3];
> +	u8 inbuf[4];
>  	u8 pd;
> +	u8 ref;
>  	int err;
>  
>  	if (!pdata) {
> @@ -350,6 +386,26 @@ static int mcp4725_probe(struct i2c_client *client,
>  	data = iio_priv(indio_dev);
>  	i2c_set_clientdata(client, indio_dev);
>  	data->client = client;
> +	data->id = id->driver_data;
> +
> +	if (data->id == MCP4725 && pdata->use_vref) {
> +		dev_err(&client->dev,
> +			"external reference is unavailable on MCP4725");
> +		return -EINVAL;
> +	}
> +
> +	if (!pdata->use_vref && pdata->vref_buffered) {
> +		dev_err(&client->dev,
> +			"buffering is unavailable on the internal reference");
> +		return -EINVAL;
> +	}
> +
> +	if (!pdata->use_vref)
> +		data->ref_mode = MCP472X_REF_VDD;
> +	else
> +		data->ref_mode = pdata->vref_buffered ?
> +			MCP472X_REF_VREF_BUFFERED :
> +			MCP472X_REF_VREF_UNBUFFERED;
>  
>  	data->vdd_reg = devm_regulator_get(&client->dev, "vdd");
>  	if (IS_ERR(data->vdd_reg))
> @@ -359,6 +415,18 @@ static int mcp4725_probe(struct i2c_client *client,
>  	if (err)
>  		return err;
>  
> +	if (pdata->use_vref) {
> +		data->vref_reg = devm_regulator_get(&client->dev, "vref");
> +		if (IS_ERR(data->vref_reg)) {
> +			err = PTR_ERR(data->vdd_reg);
> +			goto err_disable_vdd_reg;
> +		}
> +
> +		err = regulator_enable(data->vref_reg);
> +		if (err)
> +			goto err_disable_vdd_reg;
> +	}
> +
>  	indio_dev->dev.parent = &client->dev;
>  	indio_dev->name = id->name;
>  	indio_dev->info = &mcp4725_info;
> @@ -366,23 +434,38 @@ static int mcp4725_probe(struct i2c_client *client,
>  	indio_dev->num_channels = 1;
>  	indio_dev->modes = INDIO_DIRECT_MODE;
>  
> -	/* read current DAC value */
> -	err = i2c_master_recv(client, inbuf, 3);
> +	/* read current DAC value and settings */
> +	err = i2c_master_recv(client, inbuf, data->id == MCP4725 ? 3 : 4);
>  	if (err < 0) {
>  		dev_err(&client->dev, "failed to read DAC value");
> -		goto err_disable_vdd_reg;
> +		goto err_disable_vref_reg;
>  	}
>  	pd = (inbuf[0] >> 1) & 0x3;
>  	data->powerdown = pd > 0 ? true : false;
>  	data->powerdown_mode = pd ? pd - 1 : 2; /* largest resistor to gnd */
>  	data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);
> +	if (data->id == MCP4726)
> +		ref = (inbuf[3] >> 3) & 0x3;
> +
> +	if (data->id == MCP4726 && ref != data->ref_mode) {
> +		dev_info(&client->dev,
> +			"voltage reference mode differs (conf: %u, eeprom: %u), setting %u",
> +			data->ref_mode, ref, data->ref_mode);
> +		err = mcp4726_set_cfg(indio_dev);
> +		if (err < 0)
> +			goto err_disable_vref_reg;
> +	}
>  
>  	err = iio_device_register(indio_dev);
>  	if (err)
> -		goto err_disable_vdd_reg;
> +		goto err_disable_vref_reg;
>  
>  	return 0;
>  
> +err_disable_vref_reg:
> +	if (data->vref_reg)
> +		regulator_disable(data->vref_reg);
> +
>  err_disable_vdd_reg:
>  	regulator_disable(data->vdd_reg);
>  
> @@ -396,6 +479,8 @@ static int mcp4725_remove(struct i2c_client *client)
>  
>  	iio_device_unregister(indio_dev);
>  
> +	if (data->vref_reg)
> +		regulator_disable(data->vref_reg);
>  	regulator_disable(data->vdd_reg);
>  
>  	return 0;
> diff --git a/include/linux/iio/dac/mcp4725.h b/include/linux/iio/dac/mcp4725.h
> index 7c062e8..628b2cf 100644
> --- a/include/linux/iio/dac/mcp4725.h
> +++ b/include/linux/iio/dac/mcp4725.h
> @@ -9,7 +9,18 @@
>  #ifndef IIO_DAC_MCP4725_H_
>  #define IIO_DAC_MCP4725_H_
>  
> +/**
> + * struct mcp4725_platform_data - MCP4725/6 DAC specific data.
> + * @use_vref: Whether an external reference voltage on Vref pin should be used.
> + *            Additional vref-supply must be specified when used.
> + * @vref_buffered: Controls buffering of the external reference voltage.
> + *
> + * Vref related settings are available only on MCP4756. See
> + * Documentation/devicetree/bindings/iio/dac/mcp4725.txt for more information.
> + */
>  struct mcp4725_platform_data {
> +	bool use_vref;
> +	bool vref_buffered;
>  };
>  
>  #endif /* IIO_DAC_MCP4725_H_ */
> 

--
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] 12+ messages in thread

* Re: [PATCH v3 5/5] iio: dac: mcp4725: add devicetree support
       [not found]     ` <1476812589-18333-6-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
@ 2016-10-22 18:26       ` Jonathan Cameron
  0 siblings, 0 replies; 12+ messages in thread
From: Jonathan Cameron @ 2016-10-22 18:26 UTC (permalink / raw)
  To: Tomas Novotny, devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald, Rob Herring,
	Mark Rutland, Akinobu Mita, Yong Li,
	linux-iio-u79uwXL29TY76Z2rM5mHXA, Tomas Novotny

On 18/10/16 18:43, Tomas Novotny wrote:
> From: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>
> 
> Signed-off-by: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>
Applied to the togreg branch of iio.git. Initially pushed out as
testing for the autobuilders to play with it.

thanks,

Jonathan
> ---
>  drivers/iio/dac/mcp4725.c | 43 +++++++++++++++++++++++++++++++++++++------
>  1 file changed, 37 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c
> index 83d431f..05f7f4d 100644
> --- a/drivers/iio/dac/mcp4725.c
> +++ b/drivers/iio/dac/mcp4725.c
> @@ -19,6 +19,7 @@
>  #include <linux/err.h>
>  #include <linux/delay.h>
>  #include <linux/regulator/consumer.h>
> +#include <linux/of.h>
>  
>  #include <linux/iio/iio.h>
>  #include <linux/iio/sysfs.h>
> @@ -364,22 +365,41 @@ static const struct iio_info mcp4725_info = {
>  	.driver_module = THIS_MODULE,
>  };
>  
> +#ifdef CONFIG_OF
> +static int mcp4725_probe_dt(struct device *dev,
> +			    struct mcp4725_platform_data *pdata)
> +{
> +	struct device_node *np = dev->of_node;
> +
> +	if (!np)
> +		return -ENODEV;
> +
> +	/* check if is the vref-supply defined */
> +	pdata->use_vref = of_property_read_bool(np, "vref-supply");
> +	pdata->vref_buffered =
> +		of_property_read_bool(np, "microchip,vref-buffered");
> +
> +	return 0;
> +}
> +#else
> +static int mcp4725_probe_dt(struct device *dev,
> +			    struct mcp4725_platform_data *platform_data)
> +{
> +	return -ENODEV;
> +}
> +#endif
> +
>  static int mcp4725_probe(struct i2c_client *client,
>  			 const struct i2c_device_id *id)
>  {
>  	struct mcp4725_data *data;
>  	struct iio_dev *indio_dev;
> -	struct mcp4725_platform_data *pdata = dev_get_platdata(&client->dev);
> +	struct mcp4725_platform_data *pdata, pdata_dt;
>  	u8 inbuf[4];
>  	u8 pd;
>  	u8 ref;
>  	int err;
>  
> -	if (!pdata) {
> -		dev_err(&client->dev, "invalid platform data");
> -		return -EINVAL;
> -	}
> -
>  	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
>  	if (indio_dev == NULL)
>  		return -ENOMEM;
> @@ -387,6 +407,17 @@ static int mcp4725_probe(struct i2c_client *client,
>  	i2c_set_clientdata(client, indio_dev);
>  	data->client = client;
>  	data->id = id->driver_data;
> +	pdata = dev_get_platdata(&client->dev);
> +
> +	if (!pdata) {
> +		err = mcp4725_probe_dt(&client->dev, &pdata_dt);
> +		if (err) {
> +			dev_err(&client->dev,
> +				"invalid platform or devicetree data");
> +			return err;
> +		}
> +		pdata = &pdata_dt;
> +	}
>  
>  	if (data->id == MCP4725 && pdata->use_vref) {
>  		dev_err(&client->dev,
> 

--
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] 12+ messages in thread

* Re: [PATCH v3 4/5] iio: dac: mcp4725: support voltage reference selection
       [not found]         ` <2a820b1f-b6d7-88f9-7403-06a1c5e3b2ee-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
@ 2016-10-24 10:16           ` Tomas Novotny
  0 siblings, 0 replies; 12+ messages in thread
From: Tomas Novotny @ 2016-10-24 10:16 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald, Rob Herring, Mark Rutland,
	Akinobu Mita, Yong Li, linux-iio-u79uwXL29TY76Z2rM5mHXA

Hi Jonathan,

On Sat, 22 Oct 2016 19:18:06 +0100
Jonathan Cameron <jic23-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:

> On 18/10/16 18:43, Tomas Novotny wrote:
> > From: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>
> > 
> > MCP47x6 chip supports selection of a voltage reference (VDD, VREF buffered
> > or unbuffered). MCP4725 doesn't have this feature thus the eventual setting
> > is ignored and user is warned.
> > 
> > The setting is stored only in the volatile memory of the chip. You need to
> > manually store it to the EEPROM of the chip via 'store_eeprom' sysfs entry.
> > 
> > Signed-off-by: Tomas Novotny <tomas-P46umIhNmdHrBKCeMvbIDA@public.gmane.org>
> Something odd happened and this patch wouldn't apply without some manual
> intervention.
> 
> Please check the result in the testing branch of iio.git.

It was a whitespace fix. The result is correct.

Thanks for the reviews and for taking this series,

Tomas

> Thanks,
> 
> Jonathan
> > ---
> >  drivers/iio/dac/mcp4725.c       | 97 ++++++++++++++++++++++++++++++++++++++---
> >  include/linux/iio/dac/mcp4725.h | 11 +++++
> >  2 files changed, 102 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c
> > index e481f38..83d431f 100644
> > --- a/drivers/iio/dac/mcp4725.c
> > +++ b/drivers/iio/dac/mcp4725.c
> > @@ -27,12 +27,20 @@
> >  
> >  #define MCP4725_DRV_NAME "mcp4725"
> >  
> > +#define MCP472X_REF_VDD			0x00
> > +#define MCP472X_REF_VREF_UNBUFFERED	0x02
> > +#define MCP472X_REF_VREF_BUFFERED	0x03
> > +
> >  struct mcp4725_data {
> >  	struct i2c_client *client;
> > +	int id;
> > +	unsigned ref_mode;
> > +	bool vref_buffered;
> >  	u16 dac_value;
> >  	bool powerdown;
> >  	unsigned powerdown_mode;
> >  	struct regulator *vdd_reg;
> > +	struct regulator *vref_reg;
> >  };
> >  
> >  static int mcp4725_suspend(struct device *dev)
> > @@ -87,6 +95,7 @@ static ssize_t mcp4725_store_eeprom(struct device *dev,
> >  		return 0;
> >  
> >  	inoutbuf[0] = 0x60; /* write EEPROM */
> > +	inoutbuf[0] |= data->ref_mode << 3;
> >  	inoutbuf[1] = data->dac_value >> 4;
> >  	inoutbuf[2] = (data->dac_value & 0xf) << 4;
> >  
> > @@ -279,6 +288,28 @@ static int mcp4725_set_value(struct iio_dev *indio_dev, int val)
> >  		return 0;
> >  }
> >  
> > +static int mcp4726_set_cfg(struct iio_dev *indio_dev)
> > +{
> > +	struct mcp4725_data *data = iio_priv(indio_dev);
> > +	u8 outbuf[3];
> > +	int ret;
> > +
> > +	outbuf[0] = 0x40;
> > +	outbuf[0] |= data->ref_mode << 3;
> > +	if (data->powerdown)
> > +		outbuf[0] |= data->powerdown << 1;
> > +	outbuf[1] = data->dac_value >> 4;
> > +	outbuf[2] = (data->dac_value & 0xf) << 4;
> > +
> > +	ret = i2c_master_send(data->client, outbuf, 3);
> > +	if (ret < 0)
> > +		return ret;
> > +	else if (ret != 3)
> > +		return -EIO;
> > +	else
> > +		return 0;
> > +}
> > +
> >  static int mcp4725_read_raw(struct iio_dev *indio_dev,
> >  			   struct iio_chan_spec const *chan,
> >  			   int *val, int *val2, long mask)
> > @@ -291,7 +322,11 @@ static int mcp4725_read_raw(struct iio_dev *indio_dev,
> >  		*val = data->dac_value;
> >  		return IIO_VAL_INT;
> >  	case IIO_CHAN_INFO_SCALE:
> > -		ret = regulator_get_voltage(data->vdd_reg);
> > +		if (data->ref_mode == MCP472X_REF_VDD)
> > +			ret = regulator_get_voltage(data->vdd_reg);
> > +		else
> > +			ret = regulator_get_voltage(data->vref_reg);
> > +
> >  		if (ret < 0)
> >  			return ret;
> >  
> > @@ -335,8 +370,9 @@ static int mcp4725_probe(struct i2c_client *client,
> >  	struct mcp4725_data *data;
> >  	struct iio_dev *indio_dev;
> >  	struct mcp4725_platform_data *pdata = dev_get_platdata(&client->dev);
> > -	u8 inbuf[3];
> > +	u8 inbuf[4];
> >  	u8 pd;
> > +	u8 ref;
> >  	int err;
> >  
> >  	if (!pdata) {
> > @@ -350,6 +386,26 @@ static int mcp4725_probe(struct i2c_client *client,
> >  	data = iio_priv(indio_dev);
> >  	i2c_set_clientdata(client, indio_dev);
> >  	data->client = client;
> > +	data->id = id->driver_data;
> > +
> > +	if (data->id == MCP4725 && pdata->use_vref) {
> > +		dev_err(&client->dev,
> > +			"external reference is unavailable on MCP4725");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!pdata->use_vref && pdata->vref_buffered) {
> > +		dev_err(&client->dev,
> > +			"buffering is unavailable on the internal reference");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!pdata->use_vref)
> > +		data->ref_mode = MCP472X_REF_VDD;
> > +	else
> > +		data->ref_mode = pdata->vref_buffered ?
> > +			MCP472X_REF_VREF_BUFFERED :
> > +			MCP472X_REF_VREF_UNBUFFERED;
> >  
> >  	data->vdd_reg = devm_regulator_get(&client->dev, "vdd");
> >  	if (IS_ERR(data->vdd_reg))
> > @@ -359,6 +415,18 @@ static int mcp4725_probe(struct i2c_client *client,
> >  	if (err)
> >  		return err;
> >  
> > +	if (pdata->use_vref) {
> > +		data->vref_reg = devm_regulator_get(&client->dev, "vref");
> > +		if (IS_ERR(data->vref_reg)) {
> > +			err = PTR_ERR(data->vdd_reg);
> > +			goto err_disable_vdd_reg;
> > +		}
> > +
> > +		err = regulator_enable(data->vref_reg);
> > +		if (err)
> > +			goto err_disable_vdd_reg;
> > +	}
> > +
> >  	indio_dev->dev.parent = &client->dev;
> >  	indio_dev->name = id->name;
> >  	indio_dev->info = &mcp4725_info;
> > @@ -366,23 +434,38 @@ static int mcp4725_probe(struct i2c_client *client,
> >  	indio_dev->num_channels = 1;
> >  	indio_dev->modes = INDIO_DIRECT_MODE;
> >  
> > -	/* read current DAC value */
> > -	err = i2c_master_recv(client, inbuf, 3);
> > +	/* read current DAC value and settings */
> > +	err = i2c_master_recv(client, inbuf, data->id == MCP4725 ? 3 : 4);
> >  	if (err < 0) {
> >  		dev_err(&client->dev, "failed to read DAC value");
> > -		goto err_disable_vdd_reg;
> > +		goto err_disable_vref_reg;
> >  	}
> >  	pd = (inbuf[0] >> 1) & 0x3;
> >  	data->powerdown = pd > 0 ? true : false;
> >  	data->powerdown_mode = pd ? pd - 1 : 2; /* largest resistor to gnd */
> >  	data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);
> > +	if (data->id == MCP4726)
> > +		ref = (inbuf[3] >> 3) & 0x3;
> > +
> > +	if (data->id == MCP4726 && ref != data->ref_mode) {
> > +		dev_info(&client->dev,
> > +			"voltage reference mode differs (conf: %u, eeprom: %u), setting %u",
> > +			data->ref_mode, ref, data->ref_mode);
> > +		err = mcp4726_set_cfg(indio_dev);
> > +		if (err < 0)
> > +			goto err_disable_vref_reg;
> > +	}
> >  
> >  	err = iio_device_register(indio_dev);
> >  	if (err)
> > -		goto err_disable_vdd_reg;
> > +		goto err_disable_vref_reg;
> >  
> >  	return 0;
> >  
> > +err_disable_vref_reg:
> > +	if (data->vref_reg)
> > +		regulator_disable(data->vref_reg);
> > +
> >  err_disable_vdd_reg:
> >  	regulator_disable(data->vdd_reg);
> >  
> > @@ -396,6 +479,8 @@ static int mcp4725_remove(struct i2c_client *client)
> >  
> >  	iio_device_unregister(indio_dev);
> >  
> > +	if (data->vref_reg)
> > +		regulator_disable(data->vref_reg);
> >  	regulator_disable(data->vdd_reg);
> >  
> >  	return 0;
> > diff --git a/include/linux/iio/dac/mcp4725.h b/include/linux/iio/dac/mcp4725.h
> > index 7c062e8..628b2cf 100644
> > --- a/include/linux/iio/dac/mcp4725.h
> > +++ b/include/linux/iio/dac/mcp4725.h
> > @@ -9,7 +9,18 @@
> >  #ifndef IIO_DAC_MCP4725_H_
> >  #define IIO_DAC_MCP4725_H_
> >  
> > +/**
> > + * struct mcp4725_platform_data - MCP4725/6 DAC specific data.
> > + * @use_vref: Whether an external reference voltage on Vref pin should be used.
> > + *            Additional vref-supply must be specified when used.
> > + * @vref_buffered: Controls buffering of the external reference voltage.
> > + *
> > + * Vref related settings are available only on MCP4756. See
> > + * Documentation/devicetree/bindings/iio/dac/mcp4725.txt for more information.
> > + */
> >  struct mcp4725_platform_data {
> > +	bool use_vref;
> > +	bool vref_buffered;
> >  };
> >  
> >  #endif /* IIO_DAC_MCP4725_H_ */
> > 
> 

--
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] 12+ messages in thread

end of thread, other threads:[~2016-10-24 10:16 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-10-18 17:43 [PATCH v3 0/5] iio: dac: mcp4725: use regulator framework, add vref and dt support Tomas Novotny
     [not found] ` <1476812589-18333-1-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
2016-10-18 17:43   ` [PATCH v3 1/5] iio: dac: mcp4725: use regulator framework Tomas Novotny
     [not found]     ` <1476812589-18333-2-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
2016-10-22 18:01       ` Jonathan Cameron
2016-10-18 17:43   ` [PATCH v3 2/5] iio: dac: mcp4725: fix incorrect comment Tomas Novotny
     [not found]     ` <1476812589-18333-3-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
2016-10-22 18:02       ` Jonathan Cameron
2016-10-18 17:43   ` [PATCH v3 3/5] Documentation: dt: iio: add mcp4725/6 dac device binding Tomas Novotny
     [not found]     ` <1476812589-18333-4-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
2016-10-22 18:02       ` Jonathan Cameron
2016-10-18 17:43   ` [PATCH v3 4/5] iio: dac: mcp4725: support voltage reference selection Tomas Novotny
     [not found]     ` <1476812589-18333-5-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
2016-10-22 18:18       ` Jonathan Cameron
     [not found]         ` <2a820b1f-b6d7-88f9-7403-06a1c5e3b2ee-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2016-10-24 10:16           ` Tomas Novotny
2016-10-18 17:43   ` [PATCH v3 5/5] iio: dac: mcp4725: add devicetree support Tomas Novotny
     [not found]     ` <1476812589-18333-6-git-send-email-tomas.novotny-MzfF5RY65ECbtNqbA8UwFdBPR1lH4CV8@public.gmane.org>
2016-10-22 18:26       ` Jonathan Cameron

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).