ad525x_dpot: add support for AD524x pots
New parts supported: AD5241, AD5242, AD5243, AD5245, AD5246, AD5247, AD5248 Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
6c536e4ce8
commit
e3ae68476c
|
@ -22,7 +22,8 @@ config AD525X_DPOT
|
||||||
AD5160, AD5161, AD5162, AD5165, AD5200, AD5201, AD5203,
|
AD5160, AD5161, AD5162, AD5165, AD5200, AD5201, AD5203,
|
||||||
AD5204, AD5206, AD5207, AD5231, AD5232, AD5233, AD5235,
|
AD5204, AD5206, AD5207, AD5231, AD5232, AD5233, AD5235,
|
||||||
AD5260, AD5262, AD5263, AD5290, AD5291, AD5292, AD5293,
|
AD5260, AD5262, AD5263, AD5290, AD5291, AD5292, AD5293,
|
||||||
AD7376, AD8400, AD8402, AD8403, ADN2850
|
AD7376, AD8400, AD8402, AD8403, ADN2850, AD5241, AD5242,
|
||||||
|
AD5243, AD5245, AD5246, AD5247, AD5248
|
||||||
digital potentiometer chips.
|
digital potentiometer chips.
|
||||||
|
|
||||||
See Documentation/misc-devices/ad525x_dpot.txt for the
|
See Documentation/misc-devices/ad525x_dpot.txt for the
|
||||||
|
|
|
@ -87,6 +87,13 @@ static const struct i2c_device_id ad_dpot_id[] = {
|
||||||
{"ad5253", AD5253_ID},
|
{"ad5253", AD5253_ID},
|
||||||
{"ad5254", AD5254_ID},
|
{"ad5254", AD5254_ID},
|
||||||
{"ad5255", AD5255_ID},
|
{"ad5255", AD5255_ID},
|
||||||
|
{"ad5241", AD5241_ID},
|
||||||
|
{"ad5242", AD5242_ID},
|
||||||
|
{"ad5243", AD5243_ID},
|
||||||
|
{"ad5245", AD5245_ID},
|
||||||
|
{"ad5246", AD5246_ID},
|
||||||
|
{"ad5247", AD5247_ID},
|
||||||
|
{"ad5248", AD5248_ID},
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, ad_dpot_id);
|
MODULE_DEVICE_TABLE(i2c, ad_dpot_id);
|
||||||
|
|
|
@ -37,6 +37,13 @@
|
||||||
* AD8402 2 256 1, 10, 50, 100
|
* AD8402 2 256 1, 10, 50, 100
|
||||||
* AD8403 4 256 1, 10, 50, 100
|
* AD8403 4 256 1, 10, 50, 100
|
||||||
* ADN2850 3 512 25, 250
|
* ADN2850 3 512 25, 250
|
||||||
|
* AD5241 1 256 10, 100, 1M
|
||||||
|
* AD5246 1 128 5, 10, 50, 100
|
||||||
|
* AD5247 1 128 5, 10, 50, 100
|
||||||
|
* AD5245 1 256 5, 10, 50, 100
|
||||||
|
* AD5243 2 256 2.5, 10, 50, 100
|
||||||
|
* AD5248 2 256 2.5, 10, 50, 100
|
||||||
|
* AD5242 2 256 20, 50, 200
|
||||||
*
|
*
|
||||||
* See Documentation/misc-devices/ad525x_dpot.txt for more info.
|
* See Documentation/misc-devices/ad525x_dpot.txt for more info.
|
||||||
*
|
*
|
||||||
|
@ -107,118 +114,169 @@ static inline int dpot_write_r8d16(struct dpot_data *dpot, u8 reg, u16 val)
|
||||||
return dpot->bdata.bops->write_r8d16(dpot->bdata.client, reg, val);
|
return dpot->bdata.bops->write_r8d16(dpot->bdata.client, reg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static s32 dpot_read(struct dpot_data *dpot, u8 reg)
|
static s32 dpot_read_spi(struct dpot_data *dpot, u8 reg)
|
||||||
{
|
{
|
||||||
unsigned val = 0;
|
unsigned ctrl = 0;
|
||||||
|
|
||||||
if (dpot->feat & F_SPI) {
|
if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
|
||||||
if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
|
|
||||||
|
|
||||||
if (dpot->feat & F_RDACS_WONLY)
|
if (dpot->feat & F_RDACS_WONLY)
|
||||||
return dpot->rdac_cache[reg & DPOT_RDAC_MASK];
|
return dpot->rdac_cache[reg & DPOT_RDAC_MASK];
|
||||||
|
|
||||||
if (dpot->uid == DPOT_UID(AD5291_ID) ||
|
if (dpot->uid == DPOT_UID(AD5291_ID) ||
|
||||||
dpot->uid == DPOT_UID(AD5292_ID) ||
|
dpot->uid == DPOT_UID(AD5292_ID) ||
|
||||||
dpot->uid == DPOT_UID(AD5293_ID))
|
dpot->uid == DPOT_UID(AD5293_ID))
|
||||||
return dpot_read_r8d8(dpot,
|
return dpot_read_r8d8(dpot,
|
||||||
DPOT_AD5291_READ_RDAC << 2);
|
DPOT_AD5291_READ_RDAC << 2);
|
||||||
|
|
||||||
val = DPOT_SPI_READ_RDAC;
|
ctrl = DPOT_SPI_READ_RDAC;
|
||||||
} else if (reg & DPOT_ADDR_EEPROM) {
|
} else if (reg & DPOT_ADDR_EEPROM) {
|
||||||
val = DPOT_SPI_READ_EEPROM;
|
ctrl = DPOT_SPI_READ_EEPROM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dpot->feat & F_SPI_16BIT)
|
if (dpot->feat & F_SPI_16BIT)
|
||||||
return dpot_read_r8d8(dpot, val);
|
return dpot_read_r8d8(dpot, ctrl);
|
||||||
else if (dpot->feat & F_SPI_24BIT)
|
else if (dpot->feat & F_SPI_24BIT)
|
||||||
return dpot_read_r8d16(dpot, val);
|
return dpot_read_r8d16(dpot, ctrl);
|
||||||
|
|
||||||
} else { /* I2C */
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg)
|
||||||
|
{
|
||||||
|
unsigned ctrl = 0;
|
||||||
|
switch (dpot->uid) {
|
||||||
|
case DPOT_UID(AD5246_ID):
|
||||||
|
case DPOT_UID(AD5247_ID):
|
||||||
|
return dpot_read_d8(dpot);
|
||||||
|
case DPOT_UID(AD5245_ID):
|
||||||
|
case DPOT_UID(AD5241_ID):
|
||||||
|
case DPOT_UID(AD5242_ID):
|
||||||
|
case DPOT_UID(AD5243_ID):
|
||||||
|
case DPOT_UID(AD5248_ID):
|
||||||
|
ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
|
||||||
|
0 : DPOT_AD5291_RDAC_AB;
|
||||||
|
return dpot_read_r8d8(dpot, ctrl);
|
||||||
|
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) |
|
||||||
((reg & 0x7) << 1));
|
((reg & 0x7) << 1));
|
||||||
else
|
else
|
||||||
return dpot_read_r8d8(dpot, reg);
|
return dpot_read_r8d8(dpot, reg);
|
||||||
|
|
||||||
}
|
}
|
||||||
return -EFAULT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static s32 dpot_write(struct dpot_data *dpot, u8 reg, u16 value)
|
static s32 dpot_read(struct dpot_data *dpot, u8 reg)
|
||||||
|
{
|
||||||
|
if (dpot->feat & F_SPI)
|
||||||
|
return dpot_read_spi(dpot, reg);
|
||||||
|
else
|
||||||
|
return dpot_read_i2c(dpot, reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value)
|
||||||
{
|
{
|
||||||
unsigned val = 0;
|
unsigned val = 0;
|
||||||
|
|
||||||
if (dpot->feat & F_SPI) {
|
if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
|
||||||
if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
|
if (dpot->feat & F_RDACS_WONLY)
|
||||||
if (dpot->feat & F_RDACS_WONLY)
|
dpot->rdac_cache[reg & DPOT_RDAC_MASK] = value;
|
||||||
dpot->rdac_cache[reg & DPOT_RDAC_MASK] = value;
|
|
||||||
|
|
||||||
if (dpot->feat & F_AD_APPDATA) {
|
if (dpot->feat & F_AD_APPDATA) {
|
||||||
if (dpot->feat & F_SPI_8BIT) {
|
if (dpot->feat & F_SPI_8BIT) {
|
||||||
val = ((reg & DPOT_RDAC_MASK) <<
|
val = ((reg & DPOT_RDAC_MASK) <<
|
||||||
DPOT_MAX_POS(dpot->devid)) |
|
DPOT_MAX_POS(dpot->devid)) |
|
||||||
value;
|
value;
|
||||||
return dpot_write_d8(dpot, val);
|
return dpot_write_d8(dpot, val);
|
||||||
} else if (dpot->feat & F_SPI_16BIT) {
|
} else if (dpot->feat & F_SPI_16BIT) {
|
||||||
val = ((reg & DPOT_RDAC_MASK) <<
|
val = ((reg & DPOT_RDAC_MASK) <<
|
||||||
DPOT_MAX_POS(dpot->devid)) |
|
DPOT_MAX_POS(dpot->devid)) |
|
||||||
value;
|
value;
|
||||||
return dpot_write_r8d8(dpot, val >> 8,
|
return dpot_write_r8d8(dpot, val >> 8,
|
||||||
val & 0xFF);
|
val & 0xFF);
|
||||||
} else
|
} else
|
||||||
BUG();
|
BUG();
|
||||||
} else {
|
} else {
|
||||||
if (dpot->uid == DPOT_UID(AD5291_ID) ||
|
if (dpot->uid == DPOT_UID(AD5291_ID) ||
|
||||||
dpot->uid == DPOT_UID(AD5292_ID) ||
|
dpot->uid == DPOT_UID(AD5292_ID) ||
|
||||||
dpot->uid == DPOT_UID(AD5293_ID))
|
dpot->uid == DPOT_UID(AD5293_ID))
|
||||||
return dpot_write_r8d8(dpot,
|
return dpot_write_r8d8(dpot,
|
||||||
(DPOT_AD5291_RDAC << 2) |
|
(DPOT_AD5291_RDAC << 2) |
|
||||||
(value >> 8), value & 0xFF);
|
(value >> 8), value & 0xFF);
|
||||||
|
|
||||||
val = DPOT_SPI_RDAC | (reg & DPOT_RDAC_MASK);
|
val = DPOT_SPI_RDAC | (reg & DPOT_RDAC_MASK);
|
||||||
}
|
}
|
||||||
} else if (reg & DPOT_ADDR_EEPROM) {
|
} else if (reg & DPOT_ADDR_EEPROM) {
|
||||||
val = DPOT_SPI_EEPROM | (reg & DPOT_RDAC_MASK);
|
val = DPOT_SPI_EEPROM | (reg & DPOT_RDAC_MASK);
|
||||||
} else if (reg & DPOT_ADDR_CMD) {
|
} else if (reg & DPOT_ADDR_CMD) {
|
||||||
switch (reg) {
|
switch (reg) {
|
||||||
case DPOT_DEC_ALL_6DB:
|
case DPOT_DEC_ALL_6DB:
|
||||||
val = DPOT_SPI_DEC_ALL_6DB;
|
val = DPOT_SPI_DEC_ALL_6DB;
|
||||||
break;
|
break;
|
||||||
case DPOT_INC_ALL_6DB:
|
case DPOT_INC_ALL_6DB:
|
||||||
val = DPOT_SPI_INC_ALL_6DB;
|
val = DPOT_SPI_INC_ALL_6DB;
|
||||||
break;
|
break;
|
||||||
case DPOT_DEC_ALL:
|
case DPOT_DEC_ALL:
|
||||||
val = DPOT_SPI_DEC_ALL;
|
val = DPOT_SPI_DEC_ALL;
|
||||||
break;
|
break;
|
||||||
case DPOT_INC_ALL:
|
case DPOT_INC_ALL:
|
||||||
val = DPOT_SPI_INC_ALL;
|
val = DPOT_SPI_INC_ALL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
BUG();
|
BUG();
|
||||||
|
|
||||||
if (dpot->feat & F_SPI_16BIT)
|
if (dpot->feat & F_SPI_16BIT)
|
||||||
return dpot_write_r8d8(dpot, val, value);
|
return dpot_write_r8d8(dpot, val, value);
|
||||||
else if (dpot->feat & F_SPI_24BIT)
|
else if (dpot->feat & F_SPI_24BIT)
|
||||||
return dpot_write_r8d16(dpot, val, value);
|
return dpot_write_r8d16(dpot, val, value);
|
||||||
} else {
|
|
||||||
/* Only write the instruction byte for certain commands */
|
|
||||||
if (reg & DPOT_ADDR_CMD)
|
|
||||||
return dpot_write_d8(dpot, reg);
|
|
||||||
|
|
||||||
if (dpot->max_pos > 256)
|
|
||||||
return dpot_write_r8d16(dpot, (reg & 0xF8) |
|
|
||||||
((reg & 0x7) << 1), value);
|
|
||||||
else
|
|
||||||
/* All other registers require instruction + data bytes */
|
|
||||||
return dpot_write_r8d8(dpot, reg, value);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
|
||||||
|
{
|
||||||
|
/* Only write the instruction byte for certain commands */
|
||||||
|
unsigned ctrl = 0;
|
||||||
|
|
||||||
|
switch (dpot->uid) {
|
||||||
|
case DPOT_UID(AD5246_ID):
|
||||||
|
case DPOT_UID(AD5247_ID):
|
||||||
|
return dpot_write_d8(dpot, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DPOT_UID(AD5245_ID):
|
||||||
|
case DPOT_UID(AD5241_ID):
|
||||||
|
case DPOT_UID(AD5242_ID):
|
||||||
|
case DPOT_UID(AD5243_ID):
|
||||||
|
case DPOT_UID(AD5248_ID):
|
||||||
|
ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ? 0 : DPOT_AD5291_RDAC_AB;
|
||||||
|
return dpot_write_r8d8(dpot, ctrl, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (reg & DPOT_ADDR_CMD)
|
||||||
|
return dpot_write_d8(dpot, reg);
|
||||||
|
|
||||||
|
if (dpot->max_pos > 256)
|
||||||
|
return dpot_write_r8d16(dpot, (reg & 0xF8) |
|
||||||
|
((reg & 0x7) << 1), value);
|
||||||
|
else
|
||||||
|
/* All other registers require instruction + data bytes */
|
||||||
|
return dpot_write_r8d8(dpot, reg, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static s32 dpot_write(struct dpot_data *dpot, u8 reg, u16 value)
|
||||||
|
{
|
||||||
|
if (dpot->feat & F_SPI)
|
||||||
|
return dpot_write_spi(dpot, reg, value);
|
||||||
|
else
|
||||||
|
return dpot_write_i2c(dpot, reg, value);
|
||||||
|
}
|
||||||
|
|
||||||
/* sysfs functions */
|
/* sysfs functions */
|
||||||
|
|
||||||
static ssize_t sysfs_show_reg(struct device *dev,
|
static ssize_t sysfs_show_reg(struct device *dev,
|
||||||
|
|
|
@ -29,13 +29,14 @@
|
||||||
|
|
||||||
#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 */
|
||||||
#define F_CMD_TOL (1 << 2) /* RDACS are Read/Write + Tolerance REG */
|
#define F_CMD_OTP (1 << 2) /* Features OTP */
|
||||||
#define F_RDACS_RW (1 << 3) /* RDACS are Read/Write + Tolerance REG */
|
#define F_CMD_TOL (1 << 3) /* RDACS feature Tolerance REG */
|
||||||
#define F_RDACS_WONLY (1 << 4) /* RDACS are Write only */
|
#define F_RDACS_RW (1 << 4) /* RDACS are Read/Write */
|
||||||
#define F_AD_APPDATA (1 << 5) /* RDAC Address append to data */
|
#define F_RDACS_WONLY (1 << 5) /* RDACS are Write only */
|
||||||
#define F_SPI_8BIT (1 << 6) /* All SPI XFERS are 8-bit */
|
#define F_AD_APPDATA (1 << 6) /* RDAC Address append to data */
|
||||||
#define F_SPI_16BIT (1 << 7) /* All SPI XFERS are 16-bit */
|
#define F_SPI_8BIT (1 << 7) /* All SPI XFERS are 8-bit */
|
||||||
#define F_SPI_24BIT (1 << 8) /* All SPI XFERS are 24-bit */
|
#define F_SPI_16BIT (1 << 8) /* All SPI XFERS are 16-bit */
|
||||||
|
#define F_SPI_24BIT (1 << 9) /* All SPI XFERS are 24-bit */
|
||||||
|
|
||||||
#define F_RDACS_RW_TOL (F_RDACS_RW | F_CMD_EEP | F_CMD_TOL)
|
#define F_RDACS_RW_TOL (F_RDACS_RW | F_CMD_EEP | F_CMD_TOL)
|
||||||
#define F_RDACS_RW_EEP (F_RDACS_RW | F_CMD_EEP)
|
#define F_RDACS_RW_EEP (F_RDACS_RW | F_CMD_EEP)
|
||||||
|
@ -104,6 +105,15 @@ enum dpot_devid {
|
||||||
BRDAC0 | BRDAC1 | BRDAC2, 8, 31),
|
BRDAC0 | BRDAC1 | BRDAC2, 8, 31),
|
||||||
ADN2850_ID = DPOT_CONF(F_RDACS_RW_EEP | F_CMD_INC | F_SPI_24BIT,
|
ADN2850_ID = DPOT_CONF(F_RDACS_RW_EEP | F_CMD_INC | F_SPI_24BIT,
|
||||||
BRDAC0 | BRDAC1, 10, 32),
|
BRDAC0 | BRDAC1, 10, 32),
|
||||||
|
AD5241_ID = DPOT_CONF(F_RDACS_RW, BRDAC0, 8, 33),
|
||||||
|
AD5242_ID = DPOT_CONF(F_RDACS_RW, BRDAC0 | BRDAC1, 8, 34),
|
||||||
|
AD5243_ID = DPOT_CONF(F_RDACS_RW, BRDAC0 | BRDAC1, 8, 35),
|
||||||
|
AD5245_ID = DPOT_CONF(F_RDACS_RW, BRDAC0, 8, 36),
|
||||||
|
AD5246_ID = DPOT_CONF(F_RDACS_RW, BRDAC0, 7, 37),
|
||||||
|
AD5247_ID = DPOT_CONF(F_RDACS_RW, BRDAC0, 7, 38),
|
||||||
|
AD5248_ID = DPOT_CONF(F_RDACS_RW, BRDAC0 | BRDAC1, 8, 39),
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DPOT_RDAC0 0
|
#define DPOT_RDAC0 0
|
||||||
|
@ -146,6 +156,9 @@ enum dpot_devid {
|
||||||
#define DPOT_AD5291_RDAC 0x01
|
#define DPOT_AD5291_RDAC 0x01
|
||||||
#define DPOT_AD5291_READ_RDAC 0x02
|
#define DPOT_AD5291_READ_RDAC 0x02
|
||||||
|
|
||||||
|
/* AD524x use special commands */
|
||||||
|
#define DPOT_AD5291_RDAC_AB 0x80
|
||||||
|
|
||||||
struct dpot_data;
|
struct dpot_data;
|
||||||
|
|
||||||
struct ad_dpot_bus_ops {
|
struct ad_dpot_bus_ops {
|
||||||
|
|
Loading…
Reference in New Issue