]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/misc/ad525x_dpot.c
Merge tag 'v2.6.37' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / misc / ad525x_dpot.c
index 5e6fa8449e8b7bba11c2aca88fce59f34b80277e..7cb911028d094ca4416382806191a5e3e4b68e82 100644 (file)
@@ -29,9 +29,9 @@
  * AD5262              2               256             20, 50, 200
  * AD5263              4               256             20, 50, 200
  * AD5290              1               256             10, 50, 100
- * AD5291              1               256             20
- * AD5292              1               1024            20
- * AD5293              1               1024            20
+ * AD5291              1               256             20, 50, 100  (20-TP)
+ * AD5292              1               1024            20, 50, 100  (20-TP)
+ * AD5293              1               1024            20, 50, 100
  * AD7376              1               128             10, 50, 100, 1M
  * AD8400              1               256             1, 10, 50, 100
  * AD8402              2               256             1, 10, 50, 100
  * 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)
+ * AD5270              1               1024            20, 50, 100 (50-TP)
+ * AD5271              1               256             20, 50, 100 (50-TP)
+ * AD5272              1               1024            20, 50, 100 (50-TP)
+ * AD5274              1               256             20, 50, 100 (50-TP)
  *
  * See Documentation/misc-devices/ad525x_dpot.txt for more info.
  *
@@ -126,18 +130,38 @@ static inline int dpot_write_r8d16(struct dpot_data *dpot, u8 reg, u16 val)
 static s32 dpot_read_spi(struct dpot_data *dpot, u8 reg)
 {
        unsigned ctrl = 0;
+       int value;
 
        if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
 
                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->uid == DPOT_UID(AD5293_ID)) {
+
+                       value = dpot_read_r8d8(dpot,
                                DPOT_AD5291_READ_RDAC << 2);
 
+                       if (dpot->uid == DPOT_UID(AD5291_ID))
+                               value = value >> 2;
+
+                       return value;
+               } else if (dpot->uid == DPOT_UID(AD5270_ID) ||
+                       dpot->uid == DPOT_UID(AD5271_ID)) {
+
+                       value = dpot_read_r8d8(dpot,
+                               DPOT_AD5270_1_2_4_READ_RDAC << 2);
+
+                       if (value < 0)
+                               return value;
+
+                       if (dpot->uid == DPOT_UID(AD5271_ID))
+                               value = value >> 2;
+
+                       return value;
+               }
+
                ctrl = DPOT_SPI_READ_RDAC;
        } else if (reg & DPOT_ADDR_EEPROM) {
                ctrl = DPOT_SPI_READ_EEPROM;
@@ -153,6 +177,7 @@ static s32 dpot_read_spi(struct dpot_data *dpot, u8 reg)
 
 static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg)
 {
+       int value;
        unsigned ctrl = 0;
        switch (dpot->uid) {
        case DPOT_UID(AD5246_ID):
@@ -166,7 +191,7 @@ static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg)
        case DPOT_UID(AD5280_ID):
        case DPOT_UID(AD5282_ID):
                ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
-                       0 : DPOT_AD5291_RDAC_AB;
+                       0 : DPOT_AD5282_RDAC_AB;
                return dpot_read_r8d8(dpot, ctrl);
        case DPOT_UID(AD5170_ID):
        case DPOT_UID(AD5171_ID):
@@ -175,8 +200,27 @@ static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg)
        case DPOT_UID(AD5172_ID):
        case DPOT_UID(AD5173_ID):
                ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
-                       0 : DPOT_AD5272_3_A0;
+                       0 : DPOT_AD5172_3_A0;
                return dpot_read_r8d8(dpot, ctrl);
+       case DPOT_UID(AD5272_ID):
+       case DPOT_UID(AD5274_ID):
+                       dpot_write_r8d8(dpot,
+                               (DPOT_AD5270_1_2_4_READ_RDAC << 2), 0);
+
+                       value = dpot_read_r8d16(dpot,
+                               DPOT_AD5270_1_2_4_RDAC << 2);
+
+                       if (value < 0)
+                               return value;
+                       /*
+                        * AD5272/AD5274 returns high byte first, however
+                        * underling smbus expects low byte first.
+                        */
+                       value = swab16(value);
+
+                       if (dpot->uid == DPOT_UID(AD5271_ID))
+                               value = value >> 2;
+               return value;
        default:
                if ((reg & DPOT_REG_TOL) || (dpot->max_pos > 256))
                        return dpot_read_r8d16(dpot, (reg & 0xF8) |
@@ -198,7 +242,7 @@ static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value)
 {
        unsigned val = 0;
 
-       if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
+       if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD | DPOT_ADDR_OTP))) {
                if (dpot->feat & F_RDACS_WONLY)
                        dpot->rdac_cache[reg & DPOT_RDAC_MASK] = value;
 
@@ -219,11 +263,30 @@ static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value)
                } else {
                        if (dpot->uid == DPOT_UID(AD5291_ID) ||
                                dpot->uid == DPOT_UID(AD5292_ID) ||
-                               dpot->uid == DPOT_UID(AD5293_ID))
+                               dpot->uid == DPOT_UID(AD5293_ID)) {
+
+                               dpot_write_r8d8(dpot, DPOT_AD5291_CTRLREG << 2,
+                                               DPOT_AD5291_UNLOCK_CMD);
+
+                               if (dpot->uid == DPOT_UID(AD5291_ID))
+                                       value = value << 2;
+
                                return dpot_write_r8d8(dpot,
                                        (DPOT_AD5291_RDAC << 2) |
                                        (value >> 8), value & 0xFF);
+                       } else if (dpot->uid == DPOT_UID(AD5270_ID) ||
+                               dpot->uid == DPOT_UID(AD5271_ID)) {
+                               dpot_write_r8d8(dpot,
+                                               DPOT_AD5270_1_2_4_CTRLREG << 2,
+                                               DPOT_AD5270_1_2_4_UNLOCK_CMD);
+
+                               if (dpot->uid == DPOT_UID(AD5271_ID))
+                                       value = value << 2;
 
+                               return dpot_write_r8d8(dpot,
+                                       (DPOT_AD5270_1_2_4_RDAC << 2) |
+                                       (value >> 8), value & 0xFF);
+                       }
                        val = DPOT_SPI_RDAC | (reg & DPOT_RDAC_MASK);
                }
        } else if (reg & DPOT_ADDR_EEPROM) {
@@ -243,6 +306,16 @@ static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value)
                        val = DPOT_SPI_INC_ALL;
                        break;
                }
+       } else if (reg & DPOT_ADDR_OTP) {
+               if (dpot->uid == DPOT_UID(AD5291_ID) ||
+                       dpot->uid == DPOT_UID(AD5292_ID)) {
+                       return dpot_write_r8d8(dpot,
+                               DPOT_AD5291_STORE_XTPM << 2, 0);
+               } else if (dpot->uid == DPOT_UID(AD5270_ID) ||
+                       dpot->uid == DPOT_UID(AD5271_ID)) {
+                       return dpot_write_r8d8(dpot,
+                               DPOT_AD5270_1_2_4_STORE_XTPM << 2, 0);
+               }
        } else
                BUG();
 
@@ -273,7 +346,7 @@ static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
        case DPOT_UID(AD5280_ID):
        case DPOT_UID(AD5282_ID):
                ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
-                       0 : DPOT_AD5291_RDAC_AB;
+                       0 : DPOT_AD5282_RDAC_AB;
                return dpot_write_r8d8(dpot, ctrl, value);
                break;
        case DPOT_UID(AD5171_ID):
@@ -289,12 +362,12 @@ static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
        case DPOT_UID(AD5172_ID):
        case DPOT_UID(AD5173_ID):
                ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
-                       0 : DPOT_AD5272_3_A0;
+                       0 : DPOT_AD5172_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;
+                       ctrl |= DPOT_AD5170_2_3_FUSE;
                }
                return dpot_write_r8d8(dpot, ctrl, value);
                break;
@@ -303,10 +376,25 @@ static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
                        tmp = dpot_read_r8d16(dpot, tmp);
                        if (tmp >> 14) /* Ready to Program? */
                                return -EFAULT;
-                       ctrl = DPOT_AD5270_2_3_FUSE;
+                       ctrl = DPOT_AD5170_2_3_FUSE;
                }
                return dpot_write_r8d8(dpot, ctrl, value);
                break;
+       case DPOT_UID(AD5272_ID):
+       case DPOT_UID(AD5274_ID):
+               dpot_write_r8d8(dpot, DPOT_AD5270_1_2_4_CTRLREG << 2,
+                               DPOT_AD5270_1_2_4_UNLOCK_CMD);
+
+               if (reg & DPOT_ADDR_OTP)
+                       return dpot_write_r8d8(dpot,
+                                       DPOT_AD5270_1_2_4_STORE_XTPM << 2, 0);
+
+               if (dpot->uid == DPOT_UID(AD5274_ID))
+                       value = value << 2;
+
+               return dpot_write_r8d8(dpot, (DPOT_AD5270_1_2_4_RDAC << 2) |
+                                      (value >> 8), value & 0xFF);
+               break;
        default:
                if (reg & DPOT_ADDR_CMD)
                        return dpot_write_d8(dpot, reg);
@@ -320,7 +408,6 @@ static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
        }
 }
 
-
 static s32 dpot_write(struct dpot_data *dpot, u8 reg, u16 value)
 {
        if (dpot->feat & F_SPI)