root/drivers/misc/ad525x_dpot.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dpot_read_d8
  2. dpot_read_r8d8
  3. dpot_read_r8d16
  4. dpot_write_d8
  5. dpot_write_r8d8
  6. dpot_write_r8d16
  7. dpot_read_spi
  8. dpot_read_i2c
  9. dpot_read
  10. dpot_write_spi
  11. dpot_write_i2c
  12. dpot_write
  13. sysfs_show_reg
  14. sysfs_set_reg
  15. sysfs_do_cmd
  16. ad_dpot_add_files
  17. ad_dpot_remove_files
  18. ad_dpot_probe
  19. ad_dpot_remove

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * ad525x_dpot: Driver for the Analog Devices digital potentiometers
   4  * Copyright (c) 2009-2010 Analog Devices, Inc.
   5  * Author: Michael Hennerich <michael.hennerich@analog.com>
   6  *
   7  * DEVID                #Wipers         #Positions      Resistor Options (kOhm)
   8  * AD5258               1               64              1, 10, 50, 100
   9  * AD5259               1               256             5, 10, 50, 100
  10  * AD5251               2               64              1, 10, 50, 100
  11  * AD5252               2               256             1, 10, 50, 100
  12  * AD5255               3               512             25, 250
  13  * AD5253               4               64              1, 10, 50, 100
  14  * AD5254               4               256             1, 10, 50, 100
  15  * AD5160               1               256             5, 10, 50, 100
  16  * AD5161               1               256             5, 10, 50, 100
  17  * AD5162               2               256             2.5, 10, 50, 100
  18  * AD5165               1               256             100
  19  * AD5200               1               256             10, 50
  20  * AD5201               1               33              10, 50
  21  * AD5203               4               64              10, 100
  22  * AD5204               4               256             10, 50, 100
  23  * AD5206               6               256             10, 50, 100
  24  * AD5207               2               256             10, 50, 100
  25  * AD5231               1               1024            10, 50, 100
  26  * AD5232               2               256             10, 50, 100
  27  * AD5233               4               64              10, 50, 100
  28  * AD5235               2               1024            25, 250
  29  * AD5260               1               256             20, 50, 200
  30  * AD5262               2               256             20, 50, 200
  31  * AD5263               4               256             20, 50, 200
  32  * AD5290               1               256             10, 50, 100
  33  * AD5291               1               256             20, 50, 100  (20-TP)
  34  * AD5292               1               1024            20, 50, 100  (20-TP)
  35  * AD5293               1               1024            20, 50, 100
  36  * AD7376               1               128             10, 50, 100, 1M
  37  * AD8400               1               256             1, 10, 50, 100
  38  * AD8402               2               256             1, 10, 50, 100
  39  * AD8403               4               256             1, 10, 50, 100
  40  * ADN2850              3               512             25, 250
  41  * AD5241               1               256             10, 100, 1M
  42  * AD5246               1               128             5, 10, 50, 100
  43  * AD5247               1               128             5, 10, 50, 100
  44  * AD5245               1               256             5, 10, 50, 100
  45  * AD5243               2               256             2.5, 10, 50, 100
  46  * AD5248               2               256             2.5, 10, 50, 100
  47  * AD5242               2               256             20, 50, 200
  48  * AD5280               1               256             20, 50, 200
  49  * AD5282               2               256             20, 50, 200
  50  * ADN2860              3               512             25, 250
  51  * AD5273               1               64              1, 10, 50, 100 (OTP)
  52  * AD5171               1               64              5, 10, 50, 100 (OTP)
  53  * AD5170               1               256             2.5, 10, 50, 100 (OTP)
  54  * AD5172               2               256             2.5, 10, 50, 100 (OTP)
  55  * AD5173               2               256             2.5, 10, 50, 100 (OTP)
  56  * AD5270               1               1024            20, 50, 100 (50-TP)
  57  * AD5271               1               256             20, 50, 100 (50-TP)
  58  * AD5272               1               1024            20, 50, 100 (50-TP)
  59  * AD5274               1               256             20, 50, 100 (50-TP)
  60  *
  61  * See Documentation/misc-devices/ad525x_dpot.txt for more info.
  62  *
  63  * derived from ad5258.c
  64  * Copyright (c) 2009 Cyber Switching, Inc.
  65  * Author: Chris Verges <chrisv@cyberswitching.com>
  66  *
  67  * derived from ad5252.c
  68  * Copyright (c) 2006-2011 Michael Hennerich <michael.hennerich@analog.com>
  69  */
  70 
  71 #include <linux/module.h>
  72 #include <linux/device.h>
  73 #include <linux/kernel.h>
  74 #include <linux/delay.h>
  75 #include <linux/slab.h>
  76 
  77 #include "ad525x_dpot.h"
  78 
  79 /*
  80  * Client data (each client gets its own)
  81  */
  82 
  83 struct dpot_data {
  84         struct ad_dpot_bus_data bdata;
  85         struct mutex update_lock;
  86         unsigned int rdac_mask;
  87         unsigned int max_pos;
  88         unsigned long devid;
  89         unsigned int uid;
  90         unsigned int feat;
  91         unsigned int wipers;
  92         u16 rdac_cache[MAX_RDACS];
  93         DECLARE_BITMAP(otp_en_mask, MAX_RDACS);
  94 };
  95 
  96 static inline int dpot_read_d8(struct dpot_data *dpot)
  97 {
  98         return dpot->bdata.bops->read_d8(dpot->bdata.client);
  99 }
 100 
 101 static inline int dpot_read_r8d8(struct dpot_data *dpot, u8 reg)
 102 {
 103         return dpot->bdata.bops->read_r8d8(dpot->bdata.client, reg);
 104 }
 105 
 106 static inline int dpot_read_r8d16(struct dpot_data *dpot, u8 reg)
 107 {
 108         return dpot->bdata.bops->read_r8d16(dpot->bdata.client, reg);
 109 }
 110 
 111 static inline int dpot_write_d8(struct dpot_data *dpot, u8 val)
 112 {
 113         return dpot->bdata.bops->write_d8(dpot->bdata.client, val);
 114 }
 115 
 116 static inline int dpot_write_r8d8(struct dpot_data *dpot, u8 reg, u16 val)
 117 {
 118         return dpot->bdata.bops->write_r8d8(dpot->bdata.client, reg, val);
 119 }
 120 
 121 static inline int dpot_write_r8d16(struct dpot_data *dpot, u8 reg, u16 val)
 122 {
 123         return dpot->bdata.bops->write_r8d16(dpot->bdata.client, reg, val);
 124 }
 125 
 126 static s32 dpot_read_spi(struct dpot_data *dpot, u8 reg)
 127 {
 128         unsigned int ctrl = 0;
 129         int value;
 130 
 131         if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
 132 
 133                 if (dpot->feat & F_RDACS_WONLY)
 134                         return dpot->rdac_cache[reg & DPOT_RDAC_MASK];
 135                 if (dpot->uid == DPOT_UID(AD5291_ID) ||
 136                         dpot->uid == DPOT_UID(AD5292_ID) ||
 137                         dpot->uid == DPOT_UID(AD5293_ID)) {
 138 
 139                         value = dpot_read_r8d8(dpot,
 140                                 DPOT_AD5291_READ_RDAC << 2);
 141 
 142                         if (dpot->uid == DPOT_UID(AD5291_ID))
 143                                 value = value >> 2;
 144 
 145                         return value;
 146                 } else if (dpot->uid == DPOT_UID(AD5270_ID) ||
 147                         dpot->uid == DPOT_UID(AD5271_ID)) {
 148 
 149                         value = dpot_read_r8d8(dpot,
 150                                 DPOT_AD5270_1_2_4_READ_RDAC << 2);
 151 
 152                         if (value < 0)
 153                                 return value;
 154 
 155                         if (dpot->uid == DPOT_UID(AD5271_ID))
 156                                 value = value >> 2;
 157 
 158                         return value;
 159                 }
 160 
 161                 ctrl = DPOT_SPI_READ_RDAC;
 162         } else if (reg & DPOT_ADDR_EEPROM) {
 163                 ctrl = DPOT_SPI_READ_EEPROM;
 164         }
 165 
 166         if (dpot->feat & F_SPI_16BIT)
 167                 return dpot_read_r8d8(dpot, ctrl);
 168         else if (dpot->feat & F_SPI_24BIT)
 169                 return dpot_read_r8d16(dpot, ctrl);
 170 
 171         return -EFAULT;
 172 }
 173 
 174 static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg)
 175 {
 176         int value;
 177         unsigned int ctrl = 0;
 178 
 179         switch (dpot->uid) {
 180         case DPOT_UID(AD5246_ID):
 181         case DPOT_UID(AD5247_ID):
 182                 return dpot_read_d8(dpot);
 183         case DPOT_UID(AD5245_ID):
 184         case DPOT_UID(AD5241_ID):
 185         case DPOT_UID(AD5242_ID):
 186         case DPOT_UID(AD5243_ID):
 187         case DPOT_UID(AD5248_ID):
 188         case DPOT_UID(AD5280_ID):
 189         case DPOT_UID(AD5282_ID):
 190                 ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
 191                         0 : DPOT_AD5282_RDAC_AB;
 192                 return dpot_read_r8d8(dpot, ctrl);
 193         case DPOT_UID(AD5170_ID):
 194         case DPOT_UID(AD5171_ID):
 195         case DPOT_UID(AD5273_ID):
 196                         return dpot_read_d8(dpot);
 197         case DPOT_UID(AD5172_ID):
 198         case DPOT_UID(AD5173_ID):
 199                 ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
 200                         0 : DPOT_AD5172_3_A0;
 201                 return dpot_read_r8d8(dpot, ctrl);
 202         case DPOT_UID(AD5272_ID):
 203         case DPOT_UID(AD5274_ID):
 204                 dpot_write_r8d8(dpot,
 205                                 (DPOT_AD5270_1_2_4_READ_RDAC << 2), 0);
 206 
 207                 value = dpot_read_r8d16(dpot, DPOT_AD5270_1_2_4_RDAC << 2);
 208                 if (value < 0)
 209                         return value;
 210                 /*
 211                  * AD5272/AD5274 returns high byte first, however
 212                  * underling smbus expects low byte first.
 213                  */
 214                 value = swab16(value);
 215 
 216                 if (dpot->uid == DPOT_UID(AD5274_ID))
 217                         value = value >> 2;
 218                 return value;
 219         default:
 220                 if ((reg & DPOT_REG_TOL) || (dpot->max_pos > 256))
 221                         return dpot_read_r8d16(dpot, (reg & 0xF8) |
 222                                         ((reg & 0x7) << 1));
 223                 else
 224                         return dpot_read_r8d8(dpot, reg);
 225         }
 226 }
 227 
 228 static s32 dpot_read(struct dpot_data *dpot, u8 reg)
 229 {
 230         if (dpot->feat & F_SPI)
 231                 return dpot_read_spi(dpot, reg);
 232         else
 233                 return dpot_read_i2c(dpot, reg);
 234 }
 235 
 236 static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value)
 237 {
 238         unsigned int val = 0;
 239 
 240         if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD | DPOT_ADDR_OTP))) {
 241                 if (dpot->feat & F_RDACS_WONLY)
 242                         dpot->rdac_cache[reg & DPOT_RDAC_MASK] = value;
 243 
 244                 if (dpot->feat & F_AD_APPDATA) {
 245                         if (dpot->feat & F_SPI_8BIT) {
 246                                 val = ((reg & DPOT_RDAC_MASK) <<
 247                                         DPOT_MAX_POS(dpot->devid)) |
 248                                         value;
 249                                 return dpot_write_d8(dpot, val);
 250                         } else if (dpot->feat & F_SPI_16BIT) {
 251                                 val = ((reg & DPOT_RDAC_MASK) <<
 252                                         DPOT_MAX_POS(dpot->devid)) |
 253                                         value;
 254                                 return dpot_write_r8d8(dpot, val >> 8,
 255                                         val & 0xFF);
 256                         } else
 257                                 BUG();
 258                 } else {
 259                         if (dpot->uid == DPOT_UID(AD5291_ID) ||
 260                                 dpot->uid == DPOT_UID(AD5292_ID) ||
 261                                 dpot->uid == DPOT_UID(AD5293_ID)) {
 262 
 263                                 dpot_write_r8d8(dpot, DPOT_AD5291_CTRLREG << 2,
 264                                                 DPOT_AD5291_UNLOCK_CMD);
 265 
 266                                 if (dpot->uid == DPOT_UID(AD5291_ID))
 267                                         value = value << 2;
 268 
 269                                 return dpot_write_r8d8(dpot,
 270                                         (DPOT_AD5291_RDAC << 2) |
 271                                         (value >> 8), value & 0xFF);
 272                         } else if (dpot->uid == DPOT_UID(AD5270_ID) ||
 273                                 dpot->uid == DPOT_UID(AD5271_ID)) {
 274                                 dpot_write_r8d8(dpot,
 275                                                 DPOT_AD5270_1_2_4_CTRLREG << 2,
 276                                                 DPOT_AD5270_1_2_4_UNLOCK_CMD);
 277 
 278                                 if (dpot->uid == DPOT_UID(AD5271_ID))
 279                                         value = value << 2;
 280 
 281                                 return dpot_write_r8d8(dpot,
 282                                         (DPOT_AD5270_1_2_4_RDAC << 2) |
 283                                         (value >> 8), value & 0xFF);
 284                         }
 285                         val = DPOT_SPI_RDAC | (reg & DPOT_RDAC_MASK);
 286                 }
 287         } else if (reg & DPOT_ADDR_EEPROM) {
 288                 val = DPOT_SPI_EEPROM | (reg & DPOT_RDAC_MASK);
 289         } else if (reg & DPOT_ADDR_CMD) {
 290                 switch (reg) {
 291                 case DPOT_DEC_ALL_6DB:
 292                         val = DPOT_SPI_DEC_ALL_6DB;
 293                         break;
 294                 case DPOT_INC_ALL_6DB:
 295                         val = DPOT_SPI_INC_ALL_6DB;
 296                         break;
 297                 case DPOT_DEC_ALL:
 298                         val = DPOT_SPI_DEC_ALL;
 299                         break;
 300                 case DPOT_INC_ALL:
 301                         val = DPOT_SPI_INC_ALL;
 302                         break;
 303                 }
 304         } else if (reg & DPOT_ADDR_OTP) {
 305                 if (dpot->uid == DPOT_UID(AD5291_ID) ||
 306                         dpot->uid == DPOT_UID(AD5292_ID)) {
 307                         return dpot_write_r8d8(dpot,
 308                                 DPOT_AD5291_STORE_XTPM << 2, 0);
 309                 } else if (dpot->uid == DPOT_UID(AD5270_ID) ||
 310                         dpot->uid == DPOT_UID(AD5271_ID)) {
 311                         return dpot_write_r8d8(dpot,
 312                                 DPOT_AD5270_1_2_4_STORE_XTPM << 2, 0);
 313                 }
 314         } else
 315                 BUG();
 316 
 317         if (dpot->feat & F_SPI_16BIT)
 318                 return dpot_write_r8d8(dpot, val, value);
 319         else if (dpot->feat & F_SPI_24BIT)
 320                 return dpot_write_r8d16(dpot, val, value);
 321 
 322         return -EFAULT;
 323 }
 324 
 325 static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
 326 {
 327         /* Only write the instruction byte for certain commands */
 328         unsigned int tmp = 0, ctrl = 0;
 329 
 330         switch (dpot->uid) {
 331         case DPOT_UID(AD5246_ID):
 332         case DPOT_UID(AD5247_ID):
 333                 return dpot_write_d8(dpot, value);
 334 
 335         case DPOT_UID(AD5245_ID):
 336         case DPOT_UID(AD5241_ID):
 337         case DPOT_UID(AD5242_ID):
 338         case DPOT_UID(AD5243_ID):
 339         case DPOT_UID(AD5248_ID):
 340         case DPOT_UID(AD5280_ID):
 341         case DPOT_UID(AD5282_ID):
 342                 ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
 343                         0 : DPOT_AD5282_RDAC_AB;
 344                 return dpot_write_r8d8(dpot, ctrl, value);
 345         case DPOT_UID(AD5171_ID):
 346         case DPOT_UID(AD5273_ID):
 347                 if (reg & DPOT_ADDR_OTP) {
 348                         tmp = dpot_read_d8(dpot);
 349                         if (tmp >> 6) /* Ready to Program? */
 350                                 return -EFAULT;
 351                         ctrl = DPOT_AD5273_FUSE;
 352                 }
 353                 return dpot_write_r8d8(dpot, ctrl, value);
 354         case DPOT_UID(AD5172_ID):
 355         case DPOT_UID(AD5173_ID):
 356                 ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
 357                         0 : DPOT_AD5172_3_A0;
 358                 if (reg & DPOT_ADDR_OTP) {
 359                         tmp = dpot_read_r8d16(dpot, ctrl);
 360                         if (tmp >> 14) /* Ready to Program? */
 361                                 return -EFAULT;
 362                         ctrl |= DPOT_AD5170_2_3_FUSE;
 363                 }
 364                 return dpot_write_r8d8(dpot, ctrl, value);
 365         case DPOT_UID(AD5170_ID):
 366                 if (reg & DPOT_ADDR_OTP) {
 367                         tmp = dpot_read_r8d16(dpot, tmp);
 368                         if (tmp >> 14) /* Ready to Program? */
 369                                 return -EFAULT;
 370                         ctrl = DPOT_AD5170_2_3_FUSE;
 371                 }
 372                 return dpot_write_r8d8(dpot, ctrl, value);
 373         case DPOT_UID(AD5272_ID):
 374         case DPOT_UID(AD5274_ID):
 375                 dpot_write_r8d8(dpot, DPOT_AD5270_1_2_4_CTRLREG << 2,
 376                                 DPOT_AD5270_1_2_4_UNLOCK_CMD);
 377 
 378                 if (reg & DPOT_ADDR_OTP)
 379                         return dpot_write_r8d8(dpot,
 380                                         DPOT_AD5270_1_2_4_STORE_XTPM << 2, 0);
 381 
 382                 if (dpot->uid == DPOT_UID(AD5274_ID))
 383                         value = value << 2;
 384 
 385                 return dpot_write_r8d8(dpot, (DPOT_AD5270_1_2_4_RDAC << 2) |
 386                                        (value >> 8), value & 0xFF);
 387         default:
 388                 if (reg & DPOT_ADDR_CMD)
 389                         return dpot_write_d8(dpot, reg);
 390 
 391                 if (dpot->max_pos > 256)
 392                         return dpot_write_r8d16(dpot, (reg & 0xF8) |
 393                                                 ((reg & 0x7) << 1), value);
 394                 else
 395                         /* All other registers require instruction + data bytes */
 396                         return dpot_write_r8d8(dpot, reg, value);
 397         }
 398 }
 399 
 400 static s32 dpot_write(struct dpot_data *dpot, u8 reg, u16 value)
 401 {
 402         if (dpot->feat & F_SPI)
 403                 return dpot_write_spi(dpot, reg, value);
 404         else
 405                 return dpot_write_i2c(dpot, reg, value);
 406 }
 407 
 408 /* sysfs functions */
 409 
 410 static ssize_t sysfs_show_reg(struct device *dev,
 411                               struct device_attribute *attr,
 412                               char *buf, u32 reg)
 413 {
 414         struct dpot_data *data = dev_get_drvdata(dev);
 415         s32 value;
 416 
 417         if (reg & DPOT_ADDR_OTP_EN)
 418                 return sprintf(buf, "%s\n",
 419                         test_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask) ?
 420                         "enabled" : "disabled");
 421 
 422 
 423         mutex_lock(&data->update_lock);
 424         value = dpot_read(data, reg);
 425         mutex_unlock(&data->update_lock);
 426 
 427         if (value < 0)
 428                 return -EINVAL;
 429         /*
 430          * Let someone else deal with converting this ...
 431          * the tolerance is a two-byte value where the MSB
 432          * is a sign + integer value, and the LSB is a
 433          * decimal value.  See page 18 of the AD5258
 434          * datasheet (Rev. A) for more details.
 435          */
 436 
 437         if (reg & DPOT_REG_TOL)
 438                 return sprintf(buf, "0x%04x\n", value & 0xFFFF);
 439         else
 440                 return sprintf(buf, "%u\n", value & data->rdac_mask);
 441 }
 442 
 443 static ssize_t sysfs_set_reg(struct device *dev,
 444                              struct device_attribute *attr,
 445                              const char *buf, size_t count, u32 reg)
 446 {
 447         struct dpot_data *data = dev_get_drvdata(dev);
 448         unsigned long value;
 449         int err;
 450 
 451         if (reg & DPOT_ADDR_OTP_EN) {
 452                 if (sysfs_streq(buf, "enabled"))
 453                         set_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask);
 454                 else
 455                         clear_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask);
 456 
 457                 return count;
 458         }
 459 
 460         if ((reg & DPOT_ADDR_OTP) &&
 461                 !test_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask))
 462                 return -EPERM;
 463 
 464         err = kstrtoul(buf, 10, &value);
 465         if (err)
 466                 return err;
 467 
 468         if (value > data->rdac_mask)
 469                 value = data->rdac_mask;
 470 
 471         mutex_lock(&data->update_lock);
 472         dpot_write(data, reg, value);
 473         if (reg & DPOT_ADDR_EEPROM)
 474                 msleep(26);     /* Sleep while the EEPROM updates */
 475         else if (reg & DPOT_ADDR_OTP)
 476                 msleep(400);    /* Sleep while the OTP updates */
 477         mutex_unlock(&data->update_lock);
 478 
 479         return count;
 480 }
 481 
 482 static ssize_t sysfs_do_cmd(struct device *dev,
 483                             struct device_attribute *attr,
 484                             const char *buf, size_t count, u32 reg)
 485 {
 486         struct dpot_data *data = dev_get_drvdata(dev);
 487 
 488         mutex_lock(&data->update_lock);
 489         dpot_write(data, reg, 0);
 490         mutex_unlock(&data->update_lock);
 491 
 492         return count;
 493 }
 494 
 495 /* ------------------------------------------------------------------------- */
 496 
 497 #define DPOT_DEVICE_SHOW(_name, _reg) static ssize_t \
 498 show_##_name(struct device *dev, \
 499                           struct device_attribute *attr, char *buf) \
 500 { \
 501         return sysfs_show_reg(dev, attr, buf, _reg); \
 502 }
 503 
 504 #define DPOT_DEVICE_SET(_name, _reg) static ssize_t \
 505 set_##_name(struct device *dev, \
 506                          struct device_attribute *attr, \
 507                          const char *buf, size_t count) \
 508 { \
 509         return sysfs_set_reg(dev, attr, buf, count, _reg); \
 510 }
 511 
 512 #define DPOT_DEVICE_SHOW_SET(name, reg) \
 513 DPOT_DEVICE_SHOW(name, reg) \
 514 DPOT_DEVICE_SET(name, reg) \
 515 static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, show_##name, set_##name)
 516 
 517 #define DPOT_DEVICE_SHOW_ONLY(name, reg) \
 518 DPOT_DEVICE_SHOW(name, reg) \
 519 static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, show_##name, NULL)
 520 
 521 DPOT_DEVICE_SHOW_SET(rdac0, DPOT_ADDR_RDAC | DPOT_RDAC0);
 522 DPOT_DEVICE_SHOW_SET(eeprom0, DPOT_ADDR_EEPROM | DPOT_RDAC0);
 523 DPOT_DEVICE_SHOW_ONLY(tolerance0, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC0);
 524 DPOT_DEVICE_SHOW_SET(otp0, DPOT_ADDR_OTP | DPOT_RDAC0);
 525 DPOT_DEVICE_SHOW_SET(otp0en, DPOT_ADDR_OTP_EN | DPOT_RDAC0);
 526 
 527 DPOT_DEVICE_SHOW_SET(rdac1, DPOT_ADDR_RDAC | DPOT_RDAC1);
 528 DPOT_DEVICE_SHOW_SET(eeprom1, DPOT_ADDR_EEPROM | DPOT_RDAC1);
 529 DPOT_DEVICE_SHOW_ONLY(tolerance1, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC1);
 530 DPOT_DEVICE_SHOW_SET(otp1, DPOT_ADDR_OTP | DPOT_RDAC1);
 531 DPOT_DEVICE_SHOW_SET(otp1en, DPOT_ADDR_OTP_EN | DPOT_RDAC1);
 532 
 533 DPOT_DEVICE_SHOW_SET(rdac2, DPOT_ADDR_RDAC | DPOT_RDAC2);
 534 DPOT_DEVICE_SHOW_SET(eeprom2, DPOT_ADDR_EEPROM | DPOT_RDAC2);
 535 DPOT_DEVICE_SHOW_ONLY(tolerance2, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC2);
 536 DPOT_DEVICE_SHOW_SET(otp2, DPOT_ADDR_OTP | DPOT_RDAC2);
 537 DPOT_DEVICE_SHOW_SET(otp2en, DPOT_ADDR_OTP_EN | DPOT_RDAC2);
 538 
 539 DPOT_DEVICE_SHOW_SET(rdac3, DPOT_ADDR_RDAC | DPOT_RDAC3);
 540 DPOT_DEVICE_SHOW_SET(eeprom3, DPOT_ADDR_EEPROM | DPOT_RDAC3);
 541 DPOT_DEVICE_SHOW_ONLY(tolerance3, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC3);
 542 DPOT_DEVICE_SHOW_SET(otp3, DPOT_ADDR_OTP | DPOT_RDAC3);
 543 DPOT_DEVICE_SHOW_SET(otp3en, DPOT_ADDR_OTP_EN | DPOT_RDAC3);
 544 
 545 DPOT_DEVICE_SHOW_SET(rdac4, DPOT_ADDR_RDAC | DPOT_RDAC4);
 546 DPOT_DEVICE_SHOW_SET(eeprom4, DPOT_ADDR_EEPROM | DPOT_RDAC4);
 547 DPOT_DEVICE_SHOW_ONLY(tolerance4, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC4);
 548 DPOT_DEVICE_SHOW_SET(otp4, DPOT_ADDR_OTP | DPOT_RDAC4);
 549 DPOT_DEVICE_SHOW_SET(otp4en, DPOT_ADDR_OTP_EN | DPOT_RDAC4);
 550 
 551 DPOT_DEVICE_SHOW_SET(rdac5, DPOT_ADDR_RDAC | DPOT_RDAC5);
 552 DPOT_DEVICE_SHOW_SET(eeprom5, DPOT_ADDR_EEPROM | DPOT_RDAC5);
 553 DPOT_DEVICE_SHOW_ONLY(tolerance5, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC5);
 554 DPOT_DEVICE_SHOW_SET(otp5, DPOT_ADDR_OTP | DPOT_RDAC5);
 555 DPOT_DEVICE_SHOW_SET(otp5en, DPOT_ADDR_OTP_EN | DPOT_RDAC5);
 556 
 557 static const struct attribute *dpot_attrib_wipers[] = {
 558         &dev_attr_rdac0.attr,
 559         &dev_attr_rdac1.attr,
 560         &dev_attr_rdac2.attr,
 561         &dev_attr_rdac3.attr,
 562         &dev_attr_rdac4.attr,
 563         &dev_attr_rdac5.attr,
 564         NULL
 565 };
 566 
 567 static const struct attribute *dpot_attrib_eeprom[] = {
 568         &dev_attr_eeprom0.attr,
 569         &dev_attr_eeprom1.attr,
 570         &dev_attr_eeprom2.attr,
 571         &dev_attr_eeprom3.attr,
 572         &dev_attr_eeprom4.attr,
 573         &dev_attr_eeprom5.attr,
 574         NULL
 575 };
 576 
 577 static const struct attribute *dpot_attrib_otp[] = {
 578         &dev_attr_otp0.attr,
 579         &dev_attr_otp1.attr,
 580         &dev_attr_otp2.attr,
 581         &dev_attr_otp3.attr,
 582         &dev_attr_otp4.attr,
 583         &dev_attr_otp5.attr,
 584         NULL
 585 };
 586 
 587 static const struct attribute *dpot_attrib_otp_en[] = {
 588         &dev_attr_otp0en.attr,
 589         &dev_attr_otp1en.attr,
 590         &dev_attr_otp2en.attr,
 591         &dev_attr_otp3en.attr,
 592         &dev_attr_otp4en.attr,
 593         &dev_attr_otp5en.attr,
 594         NULL
 595 };
 596 
 597 static const struct attribute *dpot_attrib_tolerance[] = {
 598         &dev_attr_tolerance0.attr,
 599         &dev_attr_tolerance1.attr,
 600         &dev_attr_tolerance2.attr,
 601         &dev_attr_tolerance3.attr,
 602         &dev_attr_tolerance4.attr,
 603         &dev_attr_tolerance5.attr,
 604         NULL
 605 };
 606 
 607 /* ------------------------------------------------------------------------- */
 608 
 609 #define DPOT_DEVICE_DO_CMD(_name, _cmd) static ssize_t \
 610 set_##_name(struct device *dev, \
 611                          struct device_attribute *attr, \
 612                          const char *buf, size_t count) \
 613 { \
 614         return sysfs_do_cmd(dev, attr, buf, count, _cmd); \
 615 } \
 616 static DEVICE_ATTR(_name, S_IWUSR | S_IRUGO, NULL, set_##_name)
 617 
 618 DPOT_DEVICE_DO_CMD(inc_all, DPOT_INC_ALL);
 619 DPOT_DEVICE_DO_CMD(dec_all, DPOT_DEC_ALL);
 620 DPOT_DEVICE_DO_CMD(inc_all_6db, DPOT_INC_ALL_6DB);
 621 DPOT_DEVICE_DO_CMD(dec_all_6db, DPOT_DEC_ALL_6DB);
 622 
 623 static struct attribute *ad525x_attributes_commands[] = {
 624         &dev_attr_inc_all.attr,
 625         &dev_attr_dec_all.attr,
 626         &dev_attr_inc_all_6db.attr,
 627         &dev_attr_dec_all_6db.attr,
 628         NULL
 629 };
 630 
 631 static const struct attribute_group ad525x_group_commands = {
 632         .attrs = ad525x_attributes_commands,
 633 };
 634 
 635 static int ad_dpot_add_files(struct device *dev,
 636                 unsigned int features, unsigned int rdac)
 637 {
 638         int err = sysfs_create_file(&dev->kobj,
 639                 dpot_attrib_wipers[rdac]);
 640         if (features & F_CMD_EEP)
 641                 err |= sysfs_create_file(&dev->kobj,
 642                         dpot_attrib_eeprom[rdac]);
 643         if (features & F_CMD_TOL)
 644                 err |= sysfs_create_file(&dev->kobj,
 645                         dpot_attrib_tolerance[rdac]);
 646         if (features & F_CMD_OTP) {
 647                 err |= sysfs_create_file(&dev->kobj,
 648                         dpot_attrib_otp_en[rdac]);
 649                 err |= sysfs_create_file(&dev->kobj,
 650                         dpot_attrib_otp[rdac]);
 651         }
 652 
 653         if (err)
 654                 dev_err(dev, "failed to register sysfs hooks for RDAC%d\n",
 655                         rdac);
 656 
 657         return err;
 658 }
 659 
 660 static inline void ad_dpot_remove_files(struct device *dev,
 661                 unsigned int features, unsigned int rdac)
 662 {
 663         sysfs_remove_file(&dev->kobj,
 664                 dpot_attrib_wipers[rdac]);
 665         if (features & F_CMD_EEP)
 666                 sysfs_remove_file(&dev->kobj,
 667                         dpot_attrib_eeprom[rdac]);
 668         if (features & F_CMD_TOL)
 669                 sysfs_remove_file(&dev->kobj,
 670                         dpot_attrib_tolerance[rdac]);
 671         if (features & F_CMD_OTP) {
 672                 sysfs_remove_file(&dev->kobj,
 673                         dpot_attrib_otp_en[rdac]);
 674                 sysfs_remove_file(&dev->kobj,
 675                         dpot_attrib_otp[rdac]);
 676         }
 677 }
 678 
 679 int ad_dpot_probe(struct device *dev,
 680                 struct ad_dpot_bus_data *bdata, unsigned long devid,
 681                             const char *name)
 682 {
 683 
 684         struct dpot_data *data;
 685         int i, err = 0;
 686 
 687         data = kzalloc(sizeof(struct dpot_data), GFP_KERNEL);
 688         if (!data) {
 689                 err = -ENOMEM;
 690                 goto exit;
 691         }
 692 
 693         dev_set_drvdata(dev, data);
 694         mutex_init(&data->update_lock);
 695 
 696         data->bdata = *bdata;
 697         data->devid = devid;
 698 
 699         data->max_pos = 1 << DPOT_MAX_POS(devid);
 700         data->rdac_mask = data->max_pos - 1;
 701         data->feat = DPOT_FEAT(devid);
 702         data->uid = DPOT_UID(devid);
 703         data->wipers = DPOT_WIPERS(devid);
 704 
 705         for (i = DPOT_RDAC0; i < MAX_RDACS; i++)
 706                 if (data->wipers & (1 << i)) {
 707                         err = ad_dpot_add_files(dev, data->feat, i);
 708                         if (err)
 709                                 goto exit_remove_files;
 710                         /* power-up midscale */
 711                         if (data->feat & F_RDACS_WONLY)
 712                                 data->rdac_cache[i] = data->max_pos / 2;
 713                 }
 714 
 715         if (data->feat & F_CMD_INC)
 716                 err = sysfs_create_group(&dev->kobj, &ad525x_group_commands);
 717 
 718         if (err) {
 719                 dev_err(dev, "failed to register sysfs hooks\n");
 720                 goto exit_free;
 721         }
 722 
 723         dev_info(dev, "%s %d-Position Digital Potentiometer registered\n",
 724                  name, data->max_pos);
 725 
 726         return 0;
 727 
 728 exit_remove_files:
 729         for (i = DPOT_RDAC0; i < MAX_RDACS; i++)
 730                 if (data->wipers & (1 << i))
 731                         ad_dpot_remove_files(dev, data->feat, i);
 732 
 733 exit_free:
 734         kfree(data);
 735         dev_set_drvdata(dev, NULL);
 736 exit:
 737         dev_err(dev, "failed to create client for %s ID 0x%lX\n",
 738                 name, devid);
 739         return err;
 740 }
 741 EXPORT_SYMBOL(ad_dpot_probe);
 742 
 743 int ad_dpot_remove(struct device *dev)
 744 {
 745         struct dpot_data *data = dev_get_drvdata(dev);
 746         int i;
 747 
 748         for (i = DPOT_RDAC0; i < MAX_RDACS; i++)
 749                 if (data->wipers & (1 << i))
 750                         ad_dpot_remove_files(dev, data->feat, i);
 751 
 752         kfree(data);
 753 
 754         return 0;
 755 }
 756 EXPORT_SYMBOL(ad_dpot_remove);
 757 
 758 
 759 MODULE_AUTHOR("Chris Verges <chrisv@cyberswitching.com>, "
 760               "Michael Hennerich <michael.hennerich@analog.com>");
 761 MODULE_DESCRIPTION("Digital potentiometer driver");
 762 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */