aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/ad525x_dpot.c
diff options
context:
space:
mode:
authorMichael Hennerich <michael.hennerich@analog.com>2010-05-24 14:33:15 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-25 08:07:04 -0700
commite3ae68476ce0636554b5d95a33777f80ba407dc0 (patch)
tree3aa1fbefa2d573e1830914fe899f79caf90157d8 /drivers/misc/ad525x_dpot.c
parent6c536e4ce8edd61fdc4ab68e19ae164a54fc958f (diff)
downloadkernel_samsung_smdk4412-e3ae68476ce0636554b5d95a33777f80ba407dc0.tar.gz
kernel_samsung_smdk4412-e3ae68476ce0636554b5d95a33777f80ba407dc0.tar.bz2
kernel_samsung_smdk4412-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.c234
1 files changed, 146 insertions, 88 deletions
diff --git a/drivers/misc/ad525x_dpot.c b/drivers/misc/ad525x_dpot.c
index a41c2de0eae..35a4c4b343d 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,