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