xref: /OK3568_Linux_fs/kernel/drivers/iio/dac/mcp4725.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * mcp4725.c - Support for Microchip MCP4725/6
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2012 Peter Meerwald <pmeerw@pmeerw.net>
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Based on max517 by Roland Stigge <stigge@antcom.de>
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  * driver for the Microchip I2C 12-bit digital-to-analog converter (DAC)
10*4882a593Smuzhiyun  * (7-bit I2C slave address 0x60, the three LSBs can be configured in
11*4882a593Smuzhiyun  * hardware)
12*4882a593Smuzhiyun  */
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <linux/module.h>
15*4882a593Smuzhiyun #include <linux/i2c.h>
16*4882a593Smuzhiyun #include <linux/err.h>
17*4882a593Smuzhiyun #include <linux/delay.h>
18*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
19*4882a593Smuzhiyun #include <linux/mod_devicetable.h>
20*4882a593Smuzhiyun #include <linux/property.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #include <linux/iio/iio.h>
23*4882a593Smuzhiyun #include <linux/iio/sysfs.h>
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #include <linux/iio/dac/mcp4725.h>
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #define MCP4725_DRV_NAME "mcp4725"
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #define MCP472X_REF_VDD			0x00
30*4882a593Smuzhiyun #define MCP472X_REF_VREF_UNBUFFERED	0x02
31*4882a593Smuzhiyun #define MCP472X_REF_VREF_BUFFERED	0x03
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun struct mcp4725_data {
34*4882a593Smuzhiyun 	struct i2c_client *client;
35*4882a593Smuzhiyun 	int id;
36*4882a593Smuzhiyun 	unsigned ref_mode;
37*4882a593Smuzhiyun 	bool vref_buffered;
38*4882a593Smuzhiyun 	u16 dac_value;
39*4882a593Smuzhiyun 	bool powerdown;
40*4882a593Smuzhiyun 	unsigned powerdown_mode;
41*4882a593Smuzhiyun 	struct regulator *vdd_reg;
42*4882a593Smuzhiyun 	struct regulator *vref_reg;
43*4882a593Smuzhiyun };
44*4882a593Smuzhiyun 
mcp4725_suspend(struct device * dev)45*4882a593Smuzhiyun static int __maybe_unused mcp4725_suspend(struct device *dev)
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun 	struct mcp4725_data *data = iio_priv(i2c_get_clientdata(
48*4882a593Smuzhiyun 		to_i2c_client(dev)));
49*4882a593Smuzhiyun 	u8 outbuf[2];
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	outbuf[0] = (data->powerdown_mode + 1) << 4;
52*4882a593Smuzhiyun 	outbuf[1] = 0;
53*4882a593Smuzhiyun 	data->powerdown = true;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	return i2c_master_send(data->client, outbuf, 2);
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun 
mcp4725_resume(struct device * dev)58*4882a593Smuzhiyun static int __maybe_unused mcp4725_resume(struct device *dev)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun 	struct mcp4725_data *data = iio_priv(i2c_get_clientdata(
61*4882a593Smuzhiyun 		to_i2c_client(dev)));
62*4882a593Smuzhiyun 	u8 outbuf[2];
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	/* restore previous DAC value */
65*4882a593Smuzhiyun 	outbuf[0] = (data->dac_value >> 8) & 0xf;
66*4882a593Smuzhiyun 	outbuf[1] = data->dac_value & 0xff;
67*4882a593Smuzhiyun 	data->powerdown = false;
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	return i2c_master_send(data->client, outbuf, 2);
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun static SIMPLE_DEV_PM_OPS(mcp4725_pm_ops, mcp4725_suspend, mcp4725_resume);
72*4882a593Smuzhiyun 
mcp4725_store_eeprom(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)73*4882a593Smuzhiyun static ssize_t mcp4725_store_eeprom(struct device *dev,
74*4882a593Smuzhiyun 	struct device_attribute *attr, const char *buf, size_t len)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
77*4882a593Smuzhiyun 	struct mcp4725_data *data = iio_priv(indio_dev);
78*4882a593Smuzhiyun 	int tries = 20;
79*4882a593Smuzhiyun 	u8 inoutbuf[3];
80*4882a593Smuzhiyun 	bool state;
81*4882a593Smuzhiyun 	int ret;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	ret = strtobool(buf, &state);
84*4882a593Smuzhiyun 	if (ret < 0)
85*4882a593Smuzhiyun 		return ret;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	if (!state)
88*4882a593Smuzhiyun 		return 0;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	inoutbuf[0] = 0x60; /* write EEPROM */
91*4882a593Smuzhiyun 	inoutbuf[0] |= data->ref_mode << 3;
92*4882a593Smuzhiyun 	inoutbuf[0] |= data->powerdown ? ((data->powerdown_mode + 1) << 1) : 0;
93*4882a593Smuzhiyun 	inoutbuf[1] = data->dac_value >> 4;
94*4882a593Smuzhiyun 	inoutbuf[2] = (data->dac_value & 0xf) << 4;
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	ret = i2c_master_send(data->client, inoutbuf, 3);
97*4882a593Smuzhiyun 	if (ret < 0)
98*4882a593Smuzhiyun 		return ret;
99*4882a593Smuzhiyun 	else if (ret != 3)
100*4882a593Smuzhiyun 		return -EIO;
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	/* wait for write complete, takes up to 50ms */
103*4882a593Smuzhiyun 	while (tries--) {
104*4882a593Smuzhiyun 		msleep(20);
105*4882a593Smuzhiyun 		ret = i2c_master_recv(data->client, inoutbuf, 3);
106*4882a593Smuzhiyun 		if (ret < 0)
107*4882a593Smuzhiyun 			return ret;
108*4882a593Smuzhiyun 		else if (ret != 3)
109*4882a593Smuzhiyun 			return -EIO;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 		if (inoutbuf[0] & 0x80)
112*4882a593Smuzhiyun 			break;
113*4882a593Smuzhiyun 	}
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	if (tries < 0) {
116*4882a593Smuzhiyun 		dev_err(&data->client->dev,
117*4882a593Smuzhiyun 			"mcp4725_store_eeprom() failed, incomplete\n");
118*4882a593Smuzhiyun 		return -EIO;
119*4882a593Smuzhiyun 	}
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	return len;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun static IIO_DEVICE_ATTR(store_eeprom, S_IWUSR, NULL, mcp4725_store_eeprom, 0);
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun static struct attribute *mcp4725_attributes[] = {
127*4882a593Smuzhiyun 	&iio_dev_attr_store_eeprom.dev_attr.attr,
128*4882a593Smuzhiyun 	NULL,
129*4882a593Smuzhiyun };
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun static const struct attribute_group mcp4725_attribute_group = {
132*4882a593Smuzhiyun 	.attrs = mcp4725_attributes,
133*4882a593Smuzhiyun };
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun static const char * const mcp4725_powerdown_modes[] = {
136*4882a593Smuzhiyun 	"1kohm_to_gnd",
137*4882a593Smuzhiyun 	"100kohm_to_gnd",
138*4882a593Smuzhiyun 	"500kohm_to_gnd"
139*4882a593Smuzhiyun };
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun static const char * const mcp4726_powerdown_modes[] = {
142*4882a593Smuzhiyun 	"1kohm_to_gnd",
143*4882a593Smuzhiyun 	"125kohm_to_gnd",
144*4882a593Smuzhiyun 	"640kohm_to_gnd"
145*4882a593Smuzhiyun };
146*4882a593Smuzhiyun 
mcp4725_get_powerdown_mode(struct iio_dev * indio_dev,const struct iio_chan_spec * chan)147*4882a593Smuzhiyun static int mcp4725_get_powerdown_mode(struct iio_dev *indio_dev,
148*4882a593Smuzhiyun 	const struct iio_chan_spec *chan)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun 	struct mcp4725_data *data = iio_priv(indio_dev);
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	return data->powerdown_mode;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun 
mcp4725_set_powerdown_mode(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,unsigned mode)155*4882a593Smuzhiyun static int mcp4725_set_powerdown_mode(struct iio_dev *indio_dev,
156*4882a593Smuzhiyun 	const struct iio_chan_spec *chan, unsigned mode)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun 	struct mcp4725_data *data = iio_priv(indio_dev);
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	data->powerdown_mode = mode;
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	return 0;
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun 
mcp4725_read_powerdown(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,char * buf)165*4882a593Smuzhiyun static ssize_t mcp4725_read_powerdown(struct iio_dev *indio_dev,
166*4882a593Smuzhiyun 	uintptr_t private, const struct iio_chan_spec *chan, char *buf)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun 	struct mcp4725_data *data = iio_priv(indio_dev);
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	return sprintf(buf, "%d\n", data->powerdown);
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun 
mcp4725_write_powerdown(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,const char * buf,size_t len)173*4882a593Smuzhiyun static ssize_t mcp4725_write_powerdown(struct iio_dev *indio_dev,
174*4882a593Smuzhiyun 	 uintptr_t private, const struct iio_chan_spec *chan,
175*4882a593Smuzhiyun 	 const char *buf, size_t len)
176*4882a593Smuzhiyun {
177*4882a593Smuzhiyun 	struct mcp4725_data *data = iio_priv(indio_dev);
178*4882a593Smuzhiyun 	bool state;
179*4882a593Smuzhiyun 	int ret;
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	ret = strtobool(buf, &state);
182*4882a593Smuzhiyun 	if (ret)
183*4882a593Smuzhiyun 		return ret;
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	if (state)
186*4882a593Smuzhiyun 		ret = mcp4725_suspend(&data->client->dev);
187*4882a593Smuzhiyun 	else
188*4882a593Smuzhiyun 		ret = mcp4725_resume(&data->client->dev);
189*4882a593Smuzhiyun 	if (ret < 0)
190*4882a593Smuzhiyun 		return ret;
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	return len;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun enum chip_id {
196*4882a593Smuzhiyun 	MCP4725,
197*4882a593Smuzhiyun 	MCP4726,
198*4882a593Smuzhiyun };
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun static const struct iio_enum mcp472x_powerdown_mode_enum[] = {
201*4882a593Smuzhiyun 	[MCP4725] = {
202*4882a593Smuzhiyun 		.items = mcp4725_powerdown_modes,
203*4882a593Smuzhiyun 		.num_items = ARRAY_SIZE(mcp4725_powerdown_modes),
204*4882a593Smuzhiyun 		.get = mcp4725_get_powerdown_mode,
205*4882a593Smuzhiyun 		.set = mcp4725_set_powerdown_mode,
206*4882a593Smuzhiyun 	},
207*4882a593Smuzhiyun 	[MCP4726] = {
208*4882a593Smuzhiyun 		.items = mcp4726_powerdown_modes,
209*4882a593Smuzhiyun 		.num_items = ARRAY_SIZE(mcp4726_powerdown_modes),
210*4882a593Smuzhiyun 		.get = mcp4725_get_powerdown_mode,
211*4882a593Smuzhiyun 		.set = mcp4725_set_powerdown_mode,
212*4882a593Smuzhiyun 	},
213*4882a593Smuzhiyun };
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun static const struct iio_chan_spec_ext_info mcp4725_ext_info[] = {
216*4882a593Smuzhiyun 	{
217*4882a593Smuzhiyun 		.name = "powerdown",
218*4882a593Smuzhiyun 		.read = mcp4725_read_powerdown,
219*4882a593Smuzhiyun 		.write = mcp4725_write_powerdown,
220*4882a593Smuzhiyun 		.shared = IIO_SEPARATE,
221*4882a593Smuzhiyun 	},
222*4882a593Smuzhiyun 	IIO_ENUM("powerdown_mode", IIO_SEPARATE,
223*4882a593Smuzhiyun 			&mcp472x_powerdown_mode_enum[MCP4725]),
224*4882a593Smuzhiyun 	IIO_ENUM_AVAILABLE("powerdown_mode",
225*4882a593Smuzhiyun 			&mcp472x_powerdown_mode_enum[MCP4725]),
226*4882a593Smuzhiyun 	{ },
227*4882a593Smuzhiyun };
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun static const struct iio_chan_spec_ext_info mcp4726_ext_info[] = {
230*4882a593Smuzhiyun 	{
231*4882a593Smuzhiyun 		.name = "powerdown",
232*4882a593Smuzhiyun 		.read = mcp4725_read_powerdown,
233*4882a593Smuzhiyun 		.write = mcp4725_write_powerdown,
234*4882a593Smuzhiyun 		.shared = IIO_SEPARATE,
235*4882a593Smuzhiyun 	},
236*4882a593Smuzhiyun 	IIO_ENUM("powerdown_mode", IIO_SEPARATE,
237*4882a593Smuzhiyun 			&mcp472x_powerdown_mode_enum[MCP4726]),
238*4882a593Smuzhiyun 	IIO_ENUM_AVAILABLE("powerdown_mode",
239*4882a593Smuzhiyun 			&mcp472x_powerdown_mode_enum[MCP4726]),
240*4882a593Smuzhiyun 	{ },
241*4882a593Smuzhiyun };
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun static const struct iio_chan_spec mcp472x_channel[] = {
244*4882a593Smuzhiyun 	[MCP4725] = {
245*4882a593Smuzhiyun 		.type		= IIO_VOLTAGE,
246*4882a593Smuzhiyun 		.indexed	= 1,
247*4882a593Smuzhiyun 		.output		= 1,
248*4882a593Smuzhiyun 		.channel	= 0,
249*4882a593Smuzhiyun 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
250*4882a593Smuzhiyun 		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
251*4882a593Smuzhiyun 		.ext_info	= mcp4725_ext_info,
252*4882a593Smuzhiyun 	},
253*4882a593Smuzhiyun 	[MCP4726] = {
254*4882a593Smuzhiyun 		.type		= IIO_VOLTAGE,
255*4882a593Smuzhiyun 		.indexed	= 1,
256*4882a593Smuzhiyun 		.output		= 1,
257*4882a593Smuzhiyun 		.channel	= 0,
258*4882a593Smuzhiyun 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
259*4882a593Smuzhiyun 		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
260*4882a593Smuzhiyun 		.ext_info	= mcp4726_ext_info,
261*4882a593Smuzhiyun 	},
262*4882a593Smuzhiyun };
263*4882a593Smuzhiyun 
mcp4725_set_value(struct iio_dev * indio_dev,int val)264*4882a593Smuzhiyun static int mcp4725_set_value(struct iio_dev *indio_dev, int val)
265*4882a593Smuzhiyun {
266*4882a593Smuzhiyun 	struct mcp4725_data *data = iio_priv(indio_dev);
267*4882a593Smuzhiyun 	u8 outbuf[2];
268*4882a593Smuzhiyun 	int ret;
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	if (val >= (1 << 12) || val < 0)
271*4882a593Smuzhiyun 		return -EINVAL;
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	outbuf[0] = (val >> 8) & 0xf;
274*4882a593Smuzhiyun 	outbuf[1] = val & 0xff;
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	ret = i2c_master_send(data->client, outbuf, 2);
277*4882a593Smuzhiyun 	if (ret < 0)
278*4882a593Smuzhiyun 		return ret;
279*4882a593Smuzhiyun 	else if (ret != 2)
280*4882a593Smuzhiyun 		return -EIO;
281*4882a593Smuzhiyun 	else
282*4882a593Smuzhiyun 		return 0;
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun 
mcp4726_set_cfg(struct iio_dev * indio_dev)285*4882a593Smuzhiyun static int mcp4726_set_cfg(struct iio_dev *indio_dev)
286*4882a593Smuzhiyun {
287*4882a593Smuzhiyun 	struct mcp4725_data *data = iio_priv(indio_dev);
288*4882a593Smuzhiyun 	u8 outbuf[3];
289*4882a593Smuzhiyun 	int ret;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	outbuf[0] = 0x40;
292*4882a593Smuzhiyun 	outbuf[0] |= data->ref_mode << 3;
293*4882a593Smuzhiyun 	if (data->powerdown)
294*4882a593Smuzhiyun 		outbuf[0] |= data->powerdown << 1;
295*4882a593Smuzhiyun 	outbuf[1] = data->dac_value >> 4;
296*4882a593Smuzhiyun 	outbuf[2] = (data->dac_value & 0xf) << 4;
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	ret = i2c_master_send(data->client, outbuf, 3);
299*4882a593Smuzhiyun 	if (ret < 0)
300*4882a593Smuzhiyun 		return ret;
301*4882a593Smuzhiyun 	else if (ret != 3)
302*4882a593Smuzhiyun 		return -EIO;
303*4882a593Smuzhiyun 	else
304*4882a593Smuzhiyun 		return 0;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun 
mcp4725_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)307*4882a593Smuzhiyun static int mcp4725_read_raw(struct iio_dev *indio_dev,
308*4882a593Smuzhiyun 			   struct iio_chan_spec const *chan,
309*4882a593Smuzhiyun 			   int *val, int *val2, long mask)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun 	struct mcp4725_data *data = iio_priv(indio_dev);
312*4882a593Smuzhiyun 	int ret;
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	switch (mask) {
315*4882a593Smuzhiyun 	case IIO_CHAN_INFO_RAW:
316*4882a593Smuzhiyun 		*val = data->dac_value;
317*4882a593Smuzhiyun 		return IIO_VAL_INT;
318*4882a593Smuzhiyun 	case IIO_CHAN_INFO_SCALE:
319*4882a593Smuzhiyun 		if (data->ref_mode == MCP472X_REF_VDD)
320*4882a593Smuzhiyun 			ret = regulator_get_voltage(data->vdd_reg);
321*4882a593Smuzhiyun 		else
322*4882a593Smuzhiyun 			ret = regulator_get_voltage(data->vref_reg);
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 		if (ret < 0)
325*4882a593Smuzhiyun 			return ret;
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 		*val = ret / 1000;
328*4882a593Smuzhiyun 		*val2 = 12;
329*4882a593Smuzhiyun 		return IIO_VAL_FRACTIONAL_LOG2;
330*4882a593Smuzhiyun 	}
331*4882a593Smuzhiyun 	return -EINVAL;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun 
mcp4725_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)334*4882a593Smuzhiyun static int mcp4725_write_raw(struct iio_dev *indio_dev,
335*4882a593Smuzhiyun 			       struct iio_chan_spec const *chan,
336*4882a593Smuzhiyun 			       int val, int val2, long mask)
337*4882a593Smuzhiyun {
338*4882a593Smuzhiyun 	struct mcp4725_data *data = iio_priv(indio_dev);
339*4882a593Smuzhiyun 	int ret;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	switch (mask) {
342*4882a593Smuzhiyun 	case IIO_CHAN_INFO_RAW:
343*4882a593Smuzhiyun 		ret = mcp4725_set_value(indio_dev, val);
344*4882a593Smuzhiyun 		data->dac_value = val;
345*4882a593Smuzhiyun 		break;
346*4882a593Smuzhiyun 	default:
347*4882a593Smuzhiyun 		ret = -EINVAL;
348*4882a593Smuzhiyun 		break;
349*4882a593Smuzhiyun 	}
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	return ret;
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun static const struct iio_info mcp4725_info = {
355*4882a593Smuzhiyun 	.read_raw = mcp4725_read_raw,
356*4882a593Smuzhiyun 	.write_raw = mcp4725_write_raw,
357*4882a593Smuzhiyun 	.attrs = &mcp4725_attribute_group,
358*4882a593Smuzhiyun };
359*4882a593Smuzhiyun 
mcp4725_probe_dt(struct device * dev,struct mcp4725_platform_data * pdata)360*4882a593Smuzhiyun static int mcp4725_probe_dt(struct device *dev,
361*4882a593Smuzhiyun 			    struct mcp4725_platform_data *pdata)
362*4882a593Smuzhiyun {
363*4882a593Smuzhiyun 	/* check if is the vref-supply defined */
364*4882a593Smuzhiyun 	pdata->use_vref = device_property_read_bool(dev, "vref-supply");
365*4882a593Smuzhiyun 	pdata->vref_buffered =
366*4882a593Smuzhiyun 		device_property_read_bool(dev, "microchip,vref-buffered");
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	return 0;
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun 
mcp4725_probe(struct i2c_client * client,const struct i2c_device_id * id)371*4882a593Smuzhiyun static int mcp4725_probe(struct i2c_client *client,
372*4882a593Smuzhiyun 			 const struct i2c_device_id *id)
373*4882a593Smuzhiyun {
374*4882a593Smuzhiyun 	struct mcp4725_data *data;
375*4882a593Smuzhiyun 	struct iio_dev *indio_dev;
376*4882a593Smuzhiyun 	struct mcp4725_platform_data *pdata, pdata_dt;
377*4882a593Smuzhiyun 	u8 inbuf[4];
378*4882a593Smuzhiyun 	u8 pd;
379*4882a593Smuzhiyun 	u8 ref;
380*4882a593Smuzhiyun 	int err;
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
383*4882a593Smuzhiyun 	if (indio_dev == NULL)
384*4882a593Smuzhiyun 		return -ENOMEM;
385*4882a593Smuzhiyun 	data = iio_priv(indio_dev);
386*4882a593Smuzhiyun 	i2c_set_clientdata(client, indio_dev);
387*4882a593Smuzhiyun 	data->client = client;
388*4882a593Smuzhiyun 	if (dev_fwnode(&client->dev))
389*4882a593Smuzhiyun 		data->id = (enum chip_id)device_get_match_data(&client->dev);
390*4882a593Smuzhiyun 	else
391*4882a593Smuzhiyun 		data->id = id->driver_data;
392*4882a593Smuzhiyun 	pdata = dev_get_platdata(&client->dev);
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	if (!pdata) {
395*4882a593Smuzhiyun 		err = mcp4725_probe_dt(&client->dev, &pdata_dt);
396*4882a593Smuzhiyun 		if (err) {
397*4882a593Smuzhiyun 			dev_err(&client->dev,
398*4882a593Smuzhiyun 				"invalid platform or devicetree data");
399*4882a593Smuzhiyun 			return err;
400*4882a593Smuzhiyun 		}
401*4882a593Smuzhiyun 		pdata = &pdata_dt;
402*4882a593Smuzhiyun 	}
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 	if (data->id == MCP4725 && pdata->use_vref) {
405*4882a593Smuzhiyun 		dev_err(&client->dev,
406*4882a593Smuzhiyun 			"external reference is unavailable on MCP4725");
407*4882a593Smuzhiyun 		return -EINVAL;
408*4882a593Smuzhiyun 	}
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	if (!pdata->use_vref && pdata->vref_buffered) {
411*4882a593Smuzhiyun 		dev_err(&client->dev,
412*4882a593Smuzhiyun 			"buffering is unavailable on the internal reference");
413*4882a593Smuzhiyun 		return -EINVAL;
414*4882a593Smuzhiyun 	}
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	if (!pdata->use_vref)
417*4882a593Smuzhiyun 		data->ref_mode = MCP472X_REF_VDD;
418*4882a593Smuzhiyun 	else
419*4882a593Smuzhiyun 		data->ref_mode = pdata->vref_buffered ?
420*4882a593Smuzhiyun 			MCP472X_REF_VREF_BUFFERED :
421*4882a593Smuzhiyun 			MCP472X_REF_VREF_UNBUFFERED;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	data->vdd_reg = devm_regulator_get(&client->dev, "vdd");
424*4882a593Smuzhiyun 	if (IS_ERR(data->vdd_reg))
425*4882a593Smuzhiyun 		return PTR_ERR(data->vdd_reg);
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 	err = regulator_enable(data->vdd_reg);
428*4882a593Smuzhiyun 	if (err)
429*4882a593Smuzhiyun 		return err;
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 	if (pdata->use_vref) {
432*4882a593Smuzhiyun 		data->vref_reg = devm_regulator_get(&client->dev, "vref");
433*4882a593Smuzhiyun 		if (IS_ERR(data->vref_reg)) {
434*4882a593Smuzhiyun 			err = PTR_ERR(data->vref_reg);
435*4882a593Smuzhiyun 			goto err_disable_vdd_reg;
436*4882a593Smuzhiyun 		}
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 		err = regulator_enable(data->vref_reg);
439*4882a593Smuzhiyun 		if (err)
440*4882a593Smuzhiyun 			goto err_disable_vdd_reg;
441*4882a593Smuzhiyun 	}
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	indio_dev->name = id->name;
444*4882a593Smuzhiyun 	indio_dev->info = &mcp4725_info;
445*4882a593Smuzhiyun 	indio_dev->channels = &mcp472x_channel[id->driver_data];
446*4882a593Smuzhiyun 	indio_dev->num_channels = 1;
447*4882a593Smuzhiyun 	indio_dev->modes = INDIO_DIRECT_MODE;
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	/* read current DAC value and settings */
450*4882a593Smuzhiyun 	err = i2c_master_recv(client, inbuf, data->id == MCP4725 ? 3 : 4);
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	if (err < 0) {
453*4882a593Smuzhiyun 		dev_err(&client->dev, "failed to read DAC value");
454*4882a593Smuzhiyun 		goto err_disable_vref_reg;
455*4882a593Smuzhiyun 	}
456*4882a593Smuzhiyun 	pd = (inbuf[0] >> 1) & 0x3;
457*4882a593Smuzhiyun 	data->powerdown = pd > 0;
458*4882a593Smuzhiyun 	data->powerdown_mode = pd ? pd - 1 : 2; /* largest resistor to gnd */
459*4882a593Smuzhiyun 	data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);
460*4882a593Smuzhiyun 	if (data->id == MCP4726)
461*4882a593Smuzhiyun 		ref = (inbuf[3] >> 3) & 0x3;
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	if (data->id == MCP4726 && ref != data->ref_mode) {
464*4882a593Smuzhiyun 		dev_info(&client->dev,
465*4882a593Smuzhiyun 			"voltage reference mode differs (conf: %u, eeprom: %u), setting %u",
466*4882a593Smuzhiyun 			data->ref_mode, ref, data->ref_mode);
467*4882a593Smuzhiyun 		err = mcp4726_set_cfg(indio_dev);
468*4882a593Smuzhiyun 		if (err < 0)
469*4882a593Smuzhiyun 			goto err_disable_vref_reg;
470*4882a593Smuzhiyun 	}
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun 	err = iio_device_register(indio_dev);
473*4882a593Smuzhiyun 	if (err)
474*4882a593Smuzhiyun 		goto err_disable_vref_reg;
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	return 0;
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun err_disable_vref_reg:
479*4882a593Smuzhiyun 	if (data->vref_reg)
480*4882a593Smuzhiyun 		regulator_disable(data->vref_reg);
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun err_disable_vdd_reg:
483*4882a593Smuzhiyun 	regulator_disable(data->vdd_reg);
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 	return err;
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun 
mcp4725_remove(struct i2c_client * client)488*4882a593Smuzhiyun static int mcp4725_remove(struct i2c_client *client)
489*4882a593Smuzhiyun {
490*4882a593Smuzhiyun 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
491*4882a593Smuzhiyun 	struct mcp4725_data *data = iio_priv(indio_dev);
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun 	iio_device_unregister(indio_dev);
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun 	if (data->vref_reg)
496*4882a593Smuzhiyun 		regulator_disable(data->vref_reg);
497*4882a593Smuzhiyun 	regulator_disable(data->vdd_reg);
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	return 0;
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun static const struct i2c_device_id mcp4725_id[] = {
503*4882a593Smuzhiyun 	{ "mcp4725", MCP4725 },
504*4882a593Smuzhiyun 	{ "mcp4726", MCP4726 },
505*4882a593Smuzhiyun 	{ }
506*4882a593Smuzhiyun };
507*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, mcp4725_id);
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun static const struct of_device_id mcp4725_of_match[] = {
510*4882a593Smuzhiyun 	{
511*4882a593Smuzhiyun 		.compatible = "microchip,mcp4725",
512*4882a593Smuzhiyun 		.data = (void *)MCP4725
513*4882a593Smuzhiyun 	},
514*4882a593Smuzhiyun 	{
515*4882a593Smuzhiyun 		.compatible = "microchip,mcp4726",
516*4882a593Smuzhiyun 		.data = (void *)MCP4726
517*4882a593Smuzhiyun 	},
518*4882a593Smuzhiyun 	{ }
519*4882a593Smuzhiyun };
520*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, mcp4725_of_match);
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun static struct i2c_driver mcp4725_driver = {
523*4882a593Smuzhiyun 	.driver = {
524*4882a593Smuzhiyun 		.name	= MCP4725_DRV_NAME,
525*4882a593Smuzhiyun 		.of_match_table = mcp4725_of_match,
526*4882a593Smuzhiyun 		.pm	= &mcp4725_pm_ops,
527*4882a593Smuzhiyun 	},
528*4882a593Smuzhiyun 	.probe		= mcp4725_probe,
529*4882a593Smuzhiyun 	.remove		= mcp4725_remove,
530*4882a593Smuzhiyun 	.id_table	= mcp4725_id,
531*4882a593Smuzhiyun };
532*4882a593Smuzhiyun module_i2c_driver(mcp4725_driver);
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
535*4882a593Smuzhiyun MODULE_DESCRIPTION("MCP4725/6 12-bit DAC");
536*4882a593Smuzhiyun MODULE_LICENSE("GPL");
537