diff options
author | Michael Hennerich <michael.hennerich@analog.com> | 2010-05-24 14:33:15 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-25 08:07:04 -0700 |
commit | e3ae68476ce0636554b5d95a33777f80ba407dc0 (patch) | |
tree | 3aa1fbefa2d573e1830914fe899f79caf90157d8 /drivers/misc/ad525x_dpot.c | |
parent | 6c536e4ce8edd61fdc4ab68e19ae164a54fc958f (diff) | |
download | linux-stable-e3ae68476ce0636554b5d95a33777f80ba407dc0.tar.gz linux-stable-e3ae68476ce0636554b5d95a33777f80ba407dc0.tar.bz2 linux-stable-e3ae68476ce0636554b5d95a33777f80ba407dc0.zip |
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>
Diffstat (limited to 'drivers/misc/ad525x_dpot.c')
-rw-r--r-- | drivers/misc/ad525x_dpot.c | 234 |
1 files changed, 146 insertions, 88 deletions
diff --git a/drivers/misc/ad525x_dpot.c b/drivers/misc/ad525x_dpot.c index a41c2de0eae8..35a4c4b343d4 100644 --- a/drivers/misc/ad525x_dpot.c +++ b/drivers/misc/ad525x_dpot.c @@ -37,6 +37,13 @@ * AD8402 2 256 1, 10, 50, 100 * AD8403 4 256 1, 10, 50, 100 * 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. * @@ -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); } -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) - return dpot->rdac_cache[reg & DPOT_RDAC_MASK]; + if (dpot->feat & F_RDACS_WONLY) + return dpot->rdac_cache[reg & DPOT_RDAC_MASK]; - if (dpot->uid == DPOT_UID(AD5291_ID) || - dpot->uid == DPOT_UID(AD5292_ID) || - dpot->uid == DPOT_UID(AD5293_ID)) - return dpot_read_r8d8(dpot, - DPOT_AD5291_READ_RDAC << 2); + if (dpot->uid == DPOT_UID(AD5291_ID) || + dpot->uid == DPOT_UID(AD5292_ID) || + dpot->uid == DPOT_UID(AD5293_ID)) + return dpot_read_r8d8(dpot, + DPOT_AD5291_READ_RDAC << 2); - val = DPOT_SPI_READ_RDAC; - } else if (reg & DPOT_ADDR_EEPROM) { - val = DPOT_SPI_READ_EEPROM; - } + ctrl = DPOT_SPI_READ_RDAC; + } else if (reg & DPOT_ADDR_EEPROM) { + ctrl = DPOT_SPI_READ_EEPROM; + } - if (dpot->feat & F_SPI_16BIT) - return dpot_read_r8d8(dpot, val); - else if (dpot->feat & F_SPI_24BIT) - return dpot_read_r8d16(dpot, val); + if (dpot->feat & F_SPI_16BIT) + return dpot_read_r8d8(dpot, ctrl); + else if (dpot->feat & F_SPI_24BIT) + 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)) return dpot_read_r8d16(dpot, (reg & 0xF8) | ((reg & 0x7) << 1)); else 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; - if (dpot->feat & F_SPI) { - if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) { - if (dpot->feat & F_RDACS_WONLY) - dpot->rdac_cache[reg & DPOT_RDAC_MASK] = value; - - if (dpot->feat & F_AD_APPDATA) { - if (dpot->feat & F_SPI_8BIT) { - val = ((reg & DPOT_RDAC_MASK) << - DPOT_MAX_POS(dpot->devid)) | - value; - return dpot_write_d8(dpot, val); - } else if (dpot->feat & F_SPI_16BIT) { - val = ((reg & DPOT_RDAC_MASK) << - DPOT_MAX_POS(dpot->devid)) | - value; - return dpot_write_r8d8(dpot, val >> 8, - val & 0xFF); - } else - BUG(); - } else { - if (dpot->uid == DPOT_UID(AD5291_ID) || - dpot->uid == DPOT_UID(AD5292_ID) || - dpot->uid == DPOT_UID(AD5293_ID)) - return dpot_write_r8d8(dpot, - (DPOT_AD5291_RDAC << 2) | - (value >> 8), value & 0xFF); - - val = DPOT_SPI_RDAC | (reg & DPOT_RDAC_MASK); - } - } else if (reg & DPOT_ADDR_EEPROM) { - val = DPOT_SPI_EEPROM | (reg & DPOT_RDAC_MASK); - } else if (reg & DPOT_ADDR_CMD) { - switch (reg) { - case DPOT_DEC_ALL_6DB: - val = DPOT_SPI_DEC_ALL_6DB; - break; - case DPOT_INC_ALL_6DB: - val = DPOT_SPI_INC_ALL_6DB; - break; - case DPOT_DEC_ALL: - val = DPOT_SPI_DEC_ALL; - break; - case DPOT_INC_ALL: - val = DPOT_SPI_INC_ALL; - break; - } - } else - BUG(); - - if (dpot->feat & F_SPI_16BIT) - return dpot_write_r8d8(dpot, val, value); - else if (dpot->feat & F_SPI_24BIT) - 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); + if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) { + if (dpot->feat & F_RDACS_WONLY) + dpot->rdac_cache[reg & DPOT_RDAC_MASK] = value; + + if (dpot->feat & F_AD_APPDATA) { + if (dpot->feat & F_SPI_8BIT) { + val = ((reg & DPOT_RDAC_MASK) << + DPOT_MAX_POS(dpot->devid)) | + value; + return dpot_write_d8(dpot, val); + } else if (dpot->feat & F_SPI_16BIT) { + val = ((reg & DPOT_RDAC_MASK) << + DPOT_MAX_POS(dpot->devid)) | + value; + return dpot_write_r8d8(dpot, val >> 8, + val & 0xFF); + } else + BUG(); + } else { + if (dpot->uid == DPOT_UID(AD5291_ID) || + dpot->uid == DPOT_UID(AD5292_ID) || + dpot->uid == DPOT_UID(AD5293_ID)) + return dpot_write_r8d8(dpot, + (DPOT_AD5291_RDAC << 2) | + (value >> 8), value & 0xFF); - } + val = DPOT_SPI_RDAC | (reg & DPOT_RDAC_MASK); + } + } else if (reg & DPOT_ADDR_EEPROM) { + val = DPOT_SPI_EEPROM | (reg & DPOT_RDAC_MASK); + } else if (reg & DPOT_ADDR_CMD) { + switch (reg) { + case DPOT_DEC_ALL_6DB: + val = DPOT_SPI_DEC_ALL_6DB; + break; + case DPOT_INC_ALL_6DB: + val = DPOT_SPI_INC_ALL_6DB; + break; + case DPOT_DEC_ALL: + val = DPOT_SPI_DEC_ALL; + break; + case DPOT_INC_ALL: + val = DPOT_SPI_INC_ALL; + break; + } + } else + BUG(); + + if (dpot->feat & F_SPI_16BIT) + return dpot_write_r8d8(dpot, val, value); + else if (dpot->feat & F_SPI_24BIT) + return dpot_write_r8d16(dpot, val, value); 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 */ static ssize_t sysfs_show_reg(struct device *dev, |