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