Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 59592d0c authored by Michael Hennerich's avatar Michael Hennerich Committed by Linus Torvalds
Browse files

ad525x_dpot: add support for one time programmable pots



New parts supported:
	AD5170, AD5171, AD5172, AD5173, AD5273

Signed-off-by: default avatarMichael Hennerich <michael.hennerich@analog.com>
Signed-off-by: default avatarMike Frysinger <vapier@gentoo.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent c74cba61
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -24,7 +24,7 @@ config AD525X_DPOT
	  AD5260, AD5262, AD5263, AD5290, AD5291, AD5292, AD5293,
	  AD5260, AD5262, AD5263, AD5290, AD5291, AD5292, AD5293,
	  AD7376, AD8400, AD8402, AD8403, ADN2850, AD5241, AD5242,
	  AD7376, AD8400, AD8402, AD8403, ADN2850, AD5241, AD5242,
	  AD5243, AD5245, AD5246, AD5247, AD5248, AD5280, AD5282,
	  AD5243, AD5245, AD5246, AD5247, AD5248, AD5280, AD5282,
	  ADN2860
	  ADN2860, AD5273, AD5171, AD5170, AD5172, AD5173
	  digital potentiometer chips.
	  digital potentiometer chips.


	  See Documentation/misc-devices/ad525x_dpot.txt for the
	  See Documentation/misc-devices/ad525x_dpot.txt for the
+5 −0
Original line number Original line Diff line number Diff line
@@ -97,6 +97,11 @@ static const struct i2c_device_id ad_dpot_id[] = {
	{"ad5280", AD5280_ID},
	{"ad5280", AD5280_ID},
	{"ad5282", AD5282_ID},
	{"ad5282", AD5282_ID},
	{"adn2860", ADN2860_ID},
	{"adn2860", ADN2860_ID},
	{"ad5273", AD5273_ID},
	{"ad5171", AD5171_ID},
	{"ad5170", AD5170_ID},
	{"ad5172", AD5172_ID},
	{"ad5173", AD5173_ID},
	{}
	{}
};
};
MODULE_DEVICE_TABLE(i2c, ad_dpot_id);
MODULE_DEVICE_TABLE(i2c, ad_dpot_id);
+116 −5
Original line number Original line Diff line number Diff line
@@ -47,6 +47,11 @@
 * AD5280		1		256		20, 50, 200
 * AD5280		1		256		20, 50, 200
 * AD5282		2		256		20, 50, 200
 * AD5282		2		256		20, 50, 200
 * ADN2860		3		512		25, 250
 * ADN2860		3		512		25, 250
 * AD5273		1		64		1, 10, 50, 100 (OTP)
 * AD5171		1		64		5, 10, 50, 100 (OTP)
 * AD5170		1		256		2.5, 10, 50, 100 (OTP)
 * AD5172		2		256		2.5, 10, 50, 100 (OTP)
 * AD5173		2		256		2.5, 10, 50, 100 (OTP)
 *
 *
 * See Documentation/misc-devices/ad525x_dpot.txt for more info.
 * See Documentation/misc-devices/ad525x_dpot.txt for more info.
 *
 *
@@ -84,7 +89,8 @@ struct dpot_data {
	unsigned uid;
	unsigned uid;
	unsigned feat;
	unsigned feat;
	unsigned wipers;
	unsigned wipers;
	u16 rdac_cache[8];
	u16 rdac_cache[MAX_RDACS];
	DECLARE_BITMAP(otp_en_mask, MAX_RDACS);
};
};


static inline int dpot_read_d8(struct dpot_data *dpot)
static inline int dpot_read_d8(struct dpot_data *dpot)
@@ -162,6 +168,15 @@ static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg)
		ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
		ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
			0 : DPOT_AD5291_RDAC_AB;
			0 : DPOT_AD5291_RDAC_AB;
		return dpot_read_r8d8(dpot, ctrl);
		return dpot_read_r8d8(dpot, ctrl);
	case DPOT_UID(AD5170_ID):
	case DPOT_UID(AD5171_ID):
	case DPOT_UID(AD5273_ID):
			return dpot_read_d8(dpot);
	case DPOT_UID(AD5172_ID):
	case DPOT_UID(AD5173_ID):
		ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
			0 : DPOT_AD5272_3_A0;
		return dpot_read_r8d8(dpot, ctrl);
	default:
	default:
		if ((reg & DPOT_REG_TOL) || (dpot->max_pos > 256))
		if ((reg & DPOT_REG_TOL) || (dpot->max_pos > 256))
			return dpot_read_r8d16(dpot, (reg & 0xF8) |
			return dpot_read_r8d16(dpot, (reg & 0xF8) |
@@ -242,7 +257,7 @@ static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value)
static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
{
{
	/* Only write the instruction byte for certain commands */
	/* Only write the instruction byte for certain commands */
	unsigned ctrl = 0;
	unsigned tmp = 0, ctrl = 0;


	switch (dpot->uid) {
	switch (dpot->uid) {
	case DPOT_UID(AD5246_ID):
	case DPOT_UID(AD5246_ID):
@@ -261,6 +276,37 @@ static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
			0 : DPOT_AD5291_RDAC_AB;
			0 : DPOT_AD5291_RDAC_AB;
		return dpot_write_r8d8(dpot, ctrl, value);
		return dpot_write_r8d8(dpot, ctrl, value);
		break;
		break;
	case DPOT_UID(AD5171_ID):
	case DPOT_UID(AD5273_ID):
		if (reg & DPOT_ADDR_OTP) {
			tmp = dpot_read_d8(dpot);
			if (tmp >> 6) /* Ready to Program? */
				return -EFAULT;
			ctrl = DPOT_AD5273_FUSE;
		}
		return dpot_write_r8d8(dpot, ctrl, value);
		break;
	case DPOT_UID(AD5172_ID):
	case DPOT_UID(AD5173_ID):
		ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
			0 : DPOT_AD5272_3_A0;
		if (reg & DPOT_ADDR_OTP) {
			tmp = dpot_read_r8d16(dpot, ctrl);
			if (tmp >> 14) /* Ready to Program? */
				return -EFAULT;
			ctrl |= DPOT_AD5270_2_3_FUSE;
		}
		return dpot_write_r8d8(dpot, ctrl, value);
		break;
	case DPOT_UID(AD5170_ID):
		if (reg & DPOT_ADDR_OTP) {
			tmp = dpot_read_r8d16(dpot, tmp);
			if (tmp >> 14) /* Ready to Program? */
				return -EFAULT;
			ctrl = DPOT_AD5270_2_3_FUSE;
		}
		return dpot_write_r8d8(dpot, ctrl, value);
		break;
	default:
	default:
		if (reg & DPOT_ADDR_CMD)
		if (reg & DPOT_ADDR_CMD)
			return dpot_write_d8(dpot, reg);
			return dpot_write_d8(dpot, reg);
@@ -292,6 +338,12 @@ static ssize_t sysfs_show_reg(struct device *dev,
	struct dpot_data *data = dev_get_drvdata(dev);
	struct dpot_data *data = dev_get_drvdata(dev);
	s32 value;
	s32 value;


	if (reg & DPOT_ADDR_OTP_EN)
		return sprintf(buf, "%s\n",
			test_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask) ?
			"enabled" : "disabled");


	mutex_lock(&data->update_lock);
	mutex_lock(&data->update_lock);
	value = dpot_read(data, reg);
	value = dpot_read(data, reg);
	mutex_unlock(&data->update_lock);
	mutex_unlock(&data->update_lock);
@@ -320,6 +372,19 @@ static ssize_t sysfs_set_reg(struct device *dev,
	unsigned long value;
	unsigned long value;
	int err;
	int err;


	if (reg & DPOT_ADDR_OTP_EN) {
		if (!strncmp(buf, "enabled", sizeof("enabled")))
			set_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask);
		else
			clear_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask);

		return count;
	}

	if ((reg & DPOT_ADDR_OTP) &&
		!test_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask))
		return -EPERM;

	err = strict_strtoul(buf, 10, &value);
	err = strict_strtoul(buf, 10, &value);
	if (err)
	if (err)
		return err;
		return err;
@@ -331,6 +396,8 @@ static ssize_t sysfs_set_reg(struct device *dev,
	dpot_write(data, reg, value);
	dpot_write(data, reg, value);
	if (reg & DPOT_ADDR_EEPROM)
	if (reg & DPOT_ADDR_EEPROM)
		msleep(26);	/* Sleep while the EEPROM updates */
		msleep(26);	/* Sleep while the EEPROM updates */
	else if (reg & DPOT_ADDR_OTP)
		msleep(400);	/* Sleep while the OTP updates */
	mutex_unlock(&data->update_lock);
	mutex_unlock(&data->update_lock);


	return count;
	return count;
@@ -378,26 +445,38 @@ static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, show_##name, NULL);
DPOT_DEVICE_SHOW_SET(rdac0, DPOT_ADDR_RDAC | DPOT_RDAC0);
DPOT_DEVICE_SHOW_SET(rdac0, DPOT_ADDR_RDAC | DPOT_RDAC0);
DPOT_DEVICE_SHOW_SET(eeprom0, DPOT_ADDR_EEPROM | DPOT_RDAC0);
DPOT_DEVICE_SHOW_SET(eeprom0, DPOT_ADDR_EEPROM | DPOT_RDAC0);
DPOT_DEVICE_SHOW_ONLY(tolerance0, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC0);
DPOT_DEVICE_SHOW_ONLY(tolerance0, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC0);
DPOT_DEVICE_SHOW_SET(otp0, DPOT_ADDR_OTP | DPOT_RDAC0);
DPOT_DEVICE_SHOW_SET(otp0en, DPOT_ADDR_OTP_EN | DPOT_RDAC0);


DPOT_DEVICE_SHOW_SET(rdac1, DPOT_ADDR_RDAC | DPOT_RDAC1);
DPOT_DEVICE_SHOW_SET(rdac1, DPOT_ADDR_RDAC | DPOT_RDAC1);
DPOT_DEVICE_SHOW_SET(eeprom1, DPOT_ADDR_EEPROM | DPOT_RDAC1);
DPOT_DEVICE_SHOW_SET(eeprom1, DPOT_ADDR_EEPROM | DPOT_RDAC1);
DPOT_DEVICE_SHOW_ONLY(tolerance1, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC1);
DPOT_DEVICE_SHOW_ONLY(tolerance1, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC1);
DPOT_DEVICE_SHOW_SET(otp1, DPOT_ADDR_OTP | DPOT_RDAC1);
DPOT_DEVICE_SHOW_SET(otp1en, DPOT_ADDR_OTP_EN | DPOT_RDAC1);


DPOT_DEVICE_SHOW_SET(rdac2, DPOT_ADDR_RDAC | DPOT_RDAC2);
DPOT_DEVICE_SHOW_SET(rdac2, DPOT_ADDR_RDAC | DPOT_RDAC2);
DPOT_DEVICE_SHOW_SET(eeprom2, DPOT_ADDR_EEPROM | DPOT_RDAC2);
DPOT_DEVICE_SHOW_SET(eeprom2, DPOT_ADDR_EEPROM | DPOT_RDAC2);
DPOT_DEVICE_SHOW_ONLY(tolerance2, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC2);
DPOT_DEVICE_SHOW_ONLY(tolerance2, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC2);
DPOT_DEVICE_SHOW_SET(otp2, DPOT_ADDR_OTP | DPOT_RDAC2);
DPOT_DEVICE_SHOW_SET(otp2en, DPOT_ADDR_OTP_EN | DPOT_RDAC2);


DPOT_DEVICE_SHOW_SET(rdac3, DPOT_ADDR_RDAC | DPOT_RDAC3);
DPOT_DEVICE_SHOW_SET(rdac3, DPOT_ADDR_RDAC | DPOT_RDAC3);
DPOT_DEVICE_SHOW_SET(eeprom3, DPOT_ADDR_EEPROM | DPOT_RDAC3);
DPOT_DEVICE_SHOW_SET(eeprom3, DPOT_ADDR_EEPROM | DPOT_RDAC3);
DPOT_DEVICE_SHOW_ONLY(tolerance3, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC3);
DPOT_DEVICE_SHOW_ONLY(tolerance3, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC3);
DPOT_DEVICE_SHOW_SET(otp3, DPOT_ADDR_OTP | DPOT_RDAC3);
DPOT_DEVICE_SHOW_SET(otp3en, DPOT_ADDR_OTP_EN | DPOT_RDAC3);


DPOT_DEVICE_SHOW_SET(rdac4, DPOT_ADDR_RDAC | DPOT_RDAC4);
DPOT_DEVICE_SHOW_SET(rdac4, DPOT_ADDR_RDAC | DPOT_RDAC4);
DPOT_DEVICE_SHOW_SET(eeprom4, DPOT_ADDR_EEPROM | DPOT_RDAC4);
DPOT_DEVICE_SHOW_SET(eeprom4, DPOT_ADDR_EEPROM | DPOT_RDAC4);
DPOT_DEVICE_SHOW_ONLY(tolerance4, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC4);
DPOT_DEVICE_SHOW_ONLY(tolerance4, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC4);
DPOT_DEVICE_SHOW_SET(otp4, DPOT_ADDR_OTP | DPOT_RDAC4);
DPOT_DEVICE_SHOW_SET(otp4en, DPOT_ADDR_OTP_EN | DPOT_RDAC4);


DPOT_DEVICE_SHOW_SET(rdac5, DPOT_ADDR_RDAC | DPOT_RDAC5);
DPOT_DEVICE_SHOW_SET(rdac5, DPOT_ADDR_RDAC | DPOT_RDAC5);
DPOT_DEVICE_SHOW_SET(eeprom5, DPOT_ADDR_EEPROM | DPOT_RDAC5);
DPOT_DEVICE_SHOW_SET(eeprom5, DPOT_ADDR_EEPROM | DPOT_RDAC5);
DPOT_DEVICE_SHOW_ONLY(tolerance5, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC5);
DPOT_DEVICE_SHOW_ONLY(tolerance5, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC5);
DPOT_DEVICE_SHOW_SET(otp5, DPOT_ADDR_OTP | DPOT_RDAC5);
DPOT_DEVICE_SHOW_SET(otp5en, DPOT_ADDR_OTP_EN | DPOT_RDAC5);


static const struct attribute *dpot_attrib_wipers[] = {
static const struct attribute *dpot_attrib_wipers[] = {
	&dev_attr_rdac0.attr,
	&dev_attr_rdac0.attr,
@@ -419,6 +498,26 @@ static const struct attribute *dpot_attrib_eeprom[] = {
	NULL
	NULL
};
};


static const struct attribute *dpot_attrib_otp[] = {
	&dev_attr_otp0.attr,
	&dev_attr_otp1.attr,
	&dev_attr_otp2.attr,
	&dev_attr_otp3.attr,
	&dev_attr_otp4.attr,
	&dev_attr_otp5.attr,
	NULL
};

static const struct attribute *dpot_attrib_otp_en[] = {
	&dev_attr_otp0en.attr,
	&dev_attr_otp1en.attr,
	&dev_attr_otp2en.attr,
	&dev_attr_otp3en.attr,
	&dev_attr_otp4en.attr,
	&dev_attr_otp5en.attr,
	NULL
};

static const struct attribute *dpot_attrib_tolerance[] = {
static const struct attribute *dpot_attrib_tolerance[] = {
	&dev_attr_tolerance0.attr,
	&dev_attr_tolerance0.attr,
	&dev_attr_tolerance1.attr,
	&dev_attr_tolerance1.attr,
@@ -468,6 +567,12 @@ __devinit int ad_dpot_add_files(struct device *dev,
	if (features & F_CMD_TOL)
	if (features & F_CMD_TOL)
		err |= sysfs_create_file(&dev->kobj,
		err |= sysfs_create_file(&dev->kobj,
			dpot_attrib_tolerance[rdac]);
			dpot_attrib_tolerance[rdac]);
	if (features & F_CMD_OTP) {
		err |= sysfs_create_file(&dev->kobj,
			dpot_attrib_otp_en[rdac]);
		err |= sysfs_create_file(&dev->kobj,
			dpot_attrib_otp[rdac]);
	}


	if (err)
	if (err)
		dev_err(dev, "failed to register sysfs hooks for RDAC%d\n",
		dev_err(dev, "failed to register sysfs hooks for RDAC%d\n",
@@ -487,6 +592,12 @@ inline void ad_dpot_remove_files(struct device *dev,
	if (features & F_CMD_TOL)
	if (features & F_CMD_TOL)
		sysfs_remove_file(&dev->kobj,
		sysfs_remove_file(&dev->kobj,
			dpot_attrib_tolerance[rdac]);
			dpot_attrib_tolerance[rdac]);
	if (features & F_CMD_OTP) {
		sysfs_remove_file(&dev->kobj,
			dpot_attrib_otp_en[rdac]);
		sysfs_remove_file(&dev->kobj,
			dpot_attrib_otp[rdac]);
	}
}
}


__devinit int ad_dpot_probe(struct device *dev,
__devinit int ad_dpot_probe(struct device *dev,
@@ -514,7 +625,7 @@ __devinit int ad_dpot_probe(struct device *dev,
	data->uid = DPOT_UID(data->devid);
	data->uid = DPOT_UID(data->devid);
	data->wipers = DPOT_WIPERS(data->devid);
	data->wipers = DPOT_WIPERS(data->devid);


	for (i = DPOT_RDAC0; i <= DPOT_RDAC5; i++)
	for (i = DPOT_RDAC0; i < MAX_RDACS; i++)
		if (data->wipers & (1 << i)) {
		if (data->wipers & (1 << i)) {
			err = ad_dpot_add_files(dev, data->feat, i);
			err = ad_dpot_add_files(dev, data->feat, i);
			if (err)
			if (err)
@@ -538,7 +649,7 @@ __devinit int ad_dpot_probe(struct device *dev,
	return 0;
	return 0;


exit_remove_files:
exit_remove_files:
	for (i = DPOT_RDAC0; i <= DPOT_RDAC5; i++)
	for (i = DPOT_RDAC0; i < MAX_RDACS; i++)
		if (data->wipers & (1 << i))
		if (data->wipers & (1 << i))
			ad_dpot_remove_files(dev, data->feat, i);
			ad_dpot_remove_files(dev, data->feat, i);


@@ -557,7 +668,7 @@ __devexit int ad_dpot_remove(struct device *dev)
	struct dpot_data *data = dev_get_drvdata(dev);
	struct dpot_data *data = dev_get_drvdata(dev);
	int i;
	int i;


	for (i = DPOT_RDAC0; i <= DPOT_RDAC5; i++)
	for (i = DPOT_RDAC0; i < MAX_RDACS; i++)
		if (data->wipers & (1 << i))
		if (data->wipers & (1 << i))
			ad_dpot_remove_files(dev, data->feat, i);
			ad_dpot_remove_files(dev, data->feat, i);


+28 −14
Original line number Original line Diff line number Diff line
@@ -26,6 +26,7 @@
#define BRDAC3			(1 << 3)
#define BRDAC3			(1 << 3)
#define BRDAC4			(1 << 4)
#define BRDAC4			(1 << 4)
#define BRDAC5			(1 << 5)
#define BRDAC5			(1 << 5)
#define MAX_RDACS		6


#define F_CMD_INC		(1 << 0)	/* Features INC/DEC ALL, 6dB */
#define F_CMD_INC		(1 << 0)	/* Features INC/DEC ALL, 6dB */
#define F_CMD_EEP		(1 << 1)	/* Features EEPROM */
#define F_CMD_EEP		(1 << 1)	/* Features EEPROM */
@@ -116,6 +117,11 @@ enum dpot_devid {
	AD5282_ID = DPOT_CONF(F_RDACS_RW, BRDAC0 | BRDAC1, 8, 41),
	AD5282_ID = DPOT_CONF(F_RDACS_RW, BRDAC0 | BRDAC1, 8, 41),
	ADN2860_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
	ADN2860_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
			BRDAC0 | BRDAC1 | BRDAC2, 9, 42),
			BRDAC0 | BRDAC1 | BRDAC2, 9, 42),
	AD5273_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 6, 43),
	AD5171_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 6, 44),
	AD5170_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 8, 45),
	AD5172_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0 | BRDAC1, 8, 46),
	AD5173_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0 | BRDAC1, 8, 47),
};
};


#define DPOT_RDAC0		0
#define DPOT_RDAC0		0
@@ -136,9 +142,11 @@ enum dpot_devid {
#define DPOT_TOL_RDAC5		(DPOT_REG_TOL | DPOT_RDAC5)
#define DPOT_TOL_RDAC5		(DPOT_REG_TOL | DPOT_RDAC5)


/* RDAC-to-EEPROM Interface Commands */
/* RDAC-to-EEPROM Interface Commands */
#define DPOT_ADDR_RDAC		(0x00 << 5)
#define DPOT_ADDR_RDAC		(0x0 << 5)
#define DPOT_ADDR_EEPROM	(0x01 << 5)
#define DPOT_ADDR_EEPROM	(0x1 << 5)
#define DPOT_ADDR_CMD		(0x80)
#define DPOT_ADDR_OTP		(0x1 << 6)
#define DPOT_ADDR_CMD		(0x1 << 7)
#define DPOT_ADDR_OTP_EN	(0x1 << 9)


#define DPOT_DEC_ALL_6DB	(DPOT_ADDR_CMD | (0x4 << 3))
#define DPOT_DEC_ALL_6DB	(DPOT_ADDR_CMD | (0x4 << 3))
#define DPOT_INC_ALL_6DB	(DPOT_ADDR_CMD | (0x9 << 3))
#define DPOT_INC_ALL_6DB	(DPOT_ADDR_CMD | (0x9 << 3))
@@ -161,6 +169,12 @@ enum dpot_devid {
/* AD524x use special commands */
/* AD524x use special commands */
#define DPOT_AD5291_RDAC_AB	0x80
#define DPOT_AD5291_RDAC_AB	0x80


#define DPOT_AD5273_FUSE	0x80
#define DPOT_AD5270_2_3_FUSE	0x20
#define DPOT_AD5270_2_3_OW	0x08
#define DPOT_AD5272_3_A0	0x08
#define DPOT_AD5270_2FUSE	0x80

struct dpot_data;
struct dpot_data;


struct ad_dpot_bus_ops {
struct ad_dpot_bus_ops {