All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] iio: dac: mcp4922: Add powerdown support
@ 2018-10-03  9:06 Chris Coffey
  2018-10-08 20:08 ` Jonathan Cameron
  0 siblings, 1 reply; 5+ messages in thread
From: Chris Coffey @ 2018-10-03  9:06 UTC (permalink / raw)
  To: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler
  Cc: Michael Welling, linux-iio, Chris Coffey

This patch adds support for per-channel powerdown on the Microchip MCP
4902/4912/4922 family of DACs.

Signed-off-by: Chris Coffey <cmc@babblebit.net>
---
 drivers/iio/dac/mcp4922.c | 126 ++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 110 insertions(+), 16 deletions(-)

diff --git a/drivers/iio/dac/mcp4922.c b/drivers/iio/dac/mcp4922.c
index b5190d1dae..15cd17aa9d 100644
--- a/drivers/iio/dac/mcp4922.c
+++ b/drivers/iio/dac/mcp4922.c
@@ -28,6 +28,9 @@
 
 #define MCP4922_NUM_CHANNELS	2
 
+#define MCP4922_OUTA_POWER_DOWN	0x20
+#define MCP4922_OUTB_POWER_DOWN	0xa0
+
 enum mcp4922_supported_device_ids {
 	ID_MCP4902,
 	ID_MCP4912,
@@ -37,26 +40,13 @@ enum mcp4922_supported_device_ids {
 struct mcp4922_state {
 	struct spi_device *spi;
 	unsigned int value[MCP4922_NUM_CHANNELS];
+	bool powerdown[MCP4922_NUM_CHANNELS];
+	unsigned int powerdown_mode;
 	unsigned int vref_mv;
 	struct regulator *vref_reg;
 	u8 mosi[2] ____cacheline_aligned;
 };
 
-#define MCP4922_CHAN(chan, bits) {			\
-	.type = IIO_VOLTAGE,				\
-	.output = 1,					\
-	.indexed = 1,					\
-	.channel = chan,				\
-	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
-	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
-	.scan_type = {					\
-		.sign = 'u',				\
-		.realbits = (bits),			\
-		.storagebits = 16,			\
-		.shift = 12 - (bits),			\
-	},						\
-}
-
 static int mcp4922_spi_write(struct mcp4922_state *state, u8 addr, u32 val)
 {
 	state->mosi[1] = val & 0xff;
@@ -106,8 +96,10 @@ static int mcp4922_write_raw(struct iio_dev *indio_dev,
 		val <<= chan->scan_type.shift;
 
 		ret = mcp4922_spi_write(state, chan->channel, val);
-		if (!ret)
+		if (!ret) {
 			state->value[chan->channel] = val;
+			state->powerdown[chan->channel] = false;
+		}
 		return ret;
 
 	default:
@@ -115,6 +107,108 @@ static int mcp4922_write_raw(struct iio_dev *indio_dev,
 	}
 }
 
+static const char * const mcp4922_powerdown_modes[] = {
+	"500kohm_to_gnd"
+};
+
+static int mcp4922_get_powerdown_mode(struct iio_dev *indio_dev,
+					const struct iio_chan_spec *chan)
+{
+	struct mcp4922_state *state = iio_priv(indio_dev);
+
+	return state->powerdown_mode;
+}
+
+static int mcp4922_set_powerdown_mode(struct iio_dev *indio_dev,
+					const struct iio_chan_spec *chan,
+					unsigned int mode)
+{
+	struct mcp4922_state *state = iio_priv(indio_dev);
+
+	state->powerdown_mode = mode;
+
+	return 0;
+}
+
+static ssize_t mcp4922_read_powerdown(struct iio_dev *indio_dev,
+					uintptr_t private,
+					const struct iio_chan_spec *chan,
+					char *buf)
+{
+	struct mcp4922_state *state = iio_priv(indio_dev);
+
+	return sprintf(buf, "%d\n", state->powerdown[chan->channel]);
+}
+
+static ssize_t mcp4922_write_powerdown(struct iio_dev *indio_dev,
+					 uintptr_t private,
+					 const struct iio_chan_spec *chan,
+					 const char *buf, size_t len)
+{
+	struct mcp4922_state *state = iio_priv(indio_dev);
+	bool powerdown;
+	int ret;
+
+	ret = strtobool(buf, &powerdown);
+	if (ret)
+		return ret;
+
+	if (powerdown) {
+		state->mosi[0] = (chan->channel == 0) ?
+				MCP4922_OUTA_POWER_DOWN :
+				MCP4922_OUTB_POWER_DOWN;
+		state->mosi[1] = 0x00;
+
+		ret = spi_write(state->spi, state->mosi, 2);
+	} else {
+		/* Restore previous voltage level */
+		ret = mcp4922_write_raw(indio_dev, chan,
+					state->value[chan->channel], 0,
+					IIO_CHAN_INFO_RAW);
+	}
+	if (!ret)
+		state->powerdown[chan->channel] = powerdown;
+
+	return ret ? ret : len;
+}
+
+static const struct iio_enum mcp4922_powerdown_mode_enum = {
+	.items = mcp4922_powerdown_modes,
+	.num_items = ARRAY_SIZE(mcp4922_powerdown_modes),
+	.get = mcp4922_get_powerdown_mode,
+	.set = mcp4922_set_powerdown_mode,
+};
+
+static const struct iio_chan_spec_ext_info mcp4922_ext_info[] = {
+	{
+		.name = "powerdown",
+		.read = mcp4922_read_powerdown,
+		.write = mcp4922_write_powerdown,
+		.shared = IIO_SEPARATE,
+	},
+	IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE,
+			&mcp4922_powerdown_mode_enum),
+	IIO_ENUM_AVAILABLE("powerdown_mode",
+			&mcp4922_powerdown_mode_enum),
+	{ },
+};
+
+#define MCP4922_CHAN(chan, bits) {			\
+	.type = IIO_VOLTAGE,				\
+	.output = 1,					\
+	.indexed = 1,					\
+	.channel = chan,				\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+	.scan_type = {					\
+		.sign = 'u',				\
+		.realbits = (bits),			\
+		.storagebits = 16,			\
+		.shift = 12 - (bits),			\
+	},						\
+	.ext_info = mcp4922_ext_info,			\
+}
+
 static const struct iio_chan_spec mcp4922_channels[3][MCP4922_NUM_CHANNELS] = {
 	[ID_MCP4902] = { MCP4922_CHAN(0, 8),	MCP4922_CHAN(1, 8) },
 	[ID_MCP4912] = { MCP4922_CHAN(0, 10),	MCP4922_CHAN(1, 10) },
-- 
2.11.0

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

end of thread, other threads:[~2018-10-15  5:49 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-03  9:06 [PATCH] iio: dac: mcp4922: Add powerdown support Chris Coffey
2018-10-08 20:08 ` Jonathan Cameron
2018-10-09 11:57   ` Chris Coffey
2018-10-13 12:15     ` Jonathan Cameron
2018-10-15  5:49       ` Sean Nyekjær

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.