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