162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * AD7746 capacitive sensor driver supporting AD7745, AD7746 and AD7747 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2011 Analog Devices Inc. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/bitfield.h> 962306a36Sopenharmony_ci#include <linux/delay.h> 1062306a36Sopenharmony_ci#include <linux/device.h> 1162306a36Sopenharmony_ci#include <linux/i2c.h> 1262306a36Sopenharmony_ci#include <linux/interrupt.h> 1362306a36Sopenharmony_ci#include <linux/kernel.h> 1462306a36Sopenharmony_ci#include <linux/module.h> 1562306a36Sopenharmony_ci#include <linux/slab.h> 1662306a36Sopenharmony_ci#include <linux/stat.h> 1762306a36Sopenharmony_ci#include <linux/sysfs.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include <asm/unaligned.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include <linux/iio/iio.h> 2262306a36Sopenharmony_ci#include <linux/iio/sysfs.h> 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* AD7746 Register Definition */ 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define AD7746_REG_STATUS 0 2762306a36Sopenharmony_ci#define AD7746_REG_CAP_DATA_HIGH 1 2862306a36Sopenharmony_ci#define AD7746_REG_VT_DATA_HIGH 4 2962306a36Sopenharmony_ci#define AD7746_REG_CAP_SETUP 7 3062306a36Sopenharmony_ci#define AD7746_REG_VT_SETUP 8 3162306a36Sopenharmony_ci#define AD7746_REG_EXC_SETUP 9 3262306a36Sopenharmony_ci#define AD7746_REG_CFG 10 3362306a36Sopenharmony_ci#define AD7746_REG_CAPDACA 11 3462306a36Sopenharmony_ci#define AD7746_REG_CAPDACB 12 3562306a36Sopenharmony_ci#define AD7746_REG_CAP_OFFH 13 3662306a36Sopenharmony_ci#define AD7746_REG_CAP_GAINH 15 3762306a36Sopenharmony_ci#define AD7746_REG_VOLT_GAINH 17 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/* Status Register Bit Designations (AD7746_REG_STATUS) */ 4062306a36Sopenharmony_ci#define AD7746_STATUS_EXCERR BIT(3) 4162306a36Sopenharmony_ci#define AD7746_STATUS_RDY BIT(2) 4262306a36Sopenharmony_ci#define AD7746_STATUS_RDYVT BIT(1) 4362306a36Sopenharmony_ci#define AD7746_STATUS_RDYCAP BIT(0) 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* Capacitive Channel Setup Register Bit Designations (AD7746_REG_CAP_SETUP) */ 4662306a36Sopenharmony_ci#define AD7746_CAPSETUP_CAPEN BIT(7) 4762306a36Sopenharmony_ci#define AD7746_CAPSETUP_CIN2 BIT(6) /* AD7746 only */ 4862306a36Sopenharmony_ci#define AD7746_CAPSETUP_CAPDIFF BIT(5) 4962306a36Sopenharmony_ci#define AD7746_CAPSETUP_CACHOP BIT(0) 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci/* Voltage/Temperature Setup Register Bit Designations (AD7746_REG_VT_SETUP) */ 5262306a36Sopenharmony_ci#define AD7746_VTSETUP_VTEN BIT(7) 5362306a36Sopenharmony_ci#define AD7746_VTSETUP_VTMD_MASK GENMASK(6, 5) 5462306a36Sopenharmony_ci#define AD7746_VTSETUP_VTMD_INT_TEMP 0 5562306a36Sopenharmony_ci#define AD7746_VTSETUP_VTMD_EXT_TEMP 1 5662306a36Sopenharmony_ci#define AD7746_VTSETUP_VTMD_VDD_MON 2 5762306a36Sopenharmony_ci#define AD7746_VTSETUP_VTMD_EXT_VIN 3 5862306a36Sopenharmony_ci#define AD7746_VTSETUP_EXTREF BIT(4) 5962306a36Sopenharmony_ci#define AD7746_VTSETUP_VTSHORT BIT(1) 6062306a36Sopenharmony_ci#define AD7746_VTSETUP_VTCHOP BIT(0) 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci/* Excitation Setup Register Bit Designations (AD7746_REG_EXC_SETUP) */ 6362306a36Sopenharmony_ci#define AD7746_EXCSETUP_CLKCTRL BIT(7) 6462306a36Sopenharmony_ci#define AD7746_EXCSETUP_EXCON BIT(6) 6562306a36Sopenharmony_ci#define AD7746_EXCSETUP_EXCB BIT(5) 6662306a36Sopenharmony_ci#define AD7746_EXCSETUP_NEXCB BIT(4) 6762306a36Sopenharmony_ci#define AD7746_EXCSETUP_EXCA BIT(3) 6862306a36Sopenharmony_ci#define AD7746_EXCSETUP_NEXCA BIT(2) 6962306a36Sopenharmony_ci#define AD7746_EXCSETUP_EXCLVL_MASK GENMASK(1, 0) 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci/* Config Register Bit Designations (AD7746_REG_CFG) */ 7262306a36Sopenharmony_ci#define AD7746_CONF_VTFS_MASK GENMASK(7, 6) 7362306a36Sopenharmony_ci#define AD7746_CONF_CAPFS_MASK GENMASK(5, 3) 7462306a36Sopenharmony_ci#define AD7746_CONF_MODE_MASK GENMASK(2, 0) 7562306a36Sopenharmony_ci#define AD7746_CONF_MODE_IDLE 0 7662306a36Sopenharmony_ci#define AD7746_CONF_MODE_CONT_CONV 1 7762306a36Sopenharmony_ci#define AD7746_CONF_MODE_SINGLE_CONV 2 7862306a36Sopenharmony_ci#define AD7746_CONF_MODE_PWRDN 3 7962306a36Sopenharmony_ci#define AD7746_CONF_MODE_OFFS_CAL 5 8062306a36Sopenharmony_ci#define AD7746_CONF_MODE_GAIN_CAL 6 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci/* CAPDAC Register Bit Designations (AD7746_REG_CAPDACx) */ 8362306a36Sopenharmony_ci#define AD7746_CAPDAC_DACEN BIT(7) 8462306a36Sopenharmony_ci#define AD7746_CAPDAC_DACP_MASK GENMASK(6, 0) 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistruct ad7746_chip_info { 8762306a36Sopenharmony_ci struct i2c_client *client; 8862306a36Sopenharmony_ci struct mutex lock; /* protect sensor state */ 8962306a36Sopenharmony_ci /* 9062306a36Sopenharmony_ci * Capacitive channel digital filter setup; 9162306a36Sopenharmony_ci * conversion time/update rate setup per channel 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_ci u8 config; 9462306a36Sopenharmony_ci u8 cap_setup; 9562306a36Sopenharmony_ci u8 vt_setup; 9662306a36Sopenharmony_ci u8 capdac[2][2]; 9762306a36Sopenharmony_ci s8 capdac_set; 9862306a36Sopenharmony_ci}; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cienum ad7746_chan { 10162306a36Sopenharmony_ci VIN, 10262306a36Sopenharmony_ci VIN_VDD, 10362306a36Sopenharmony_ci TEMP_INT, 10462306a36Sopenharmony_ci TEMP_EXT, 10562306a36Sopenharmony_ci CIN1, 10662306a36Sopenharmony_ci CIN1_DIFF, 10762306a36Sopenharmony_ci CIN2, 10862306a36Sopenharmony_ci CIN2_DIFF, 10962306a36Sopenharmony_ci}; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cistruct ad7746_chan_info { 11262306a36Sopenharmony_ci u8 addr; 11362306a36Sopenharmony_ci union { 11462306a36Sopenharmony_ci u8 vtmd; 11562306a36Sopenharmony_ci struct { /* CAP SETUP fields */ 11662306a36Sopenharmony_ci unsigned int cin2 : 1; 11762306a36Sopenharmony_ci unsigned int capdiff : 1; 11862306a36Sopenharmony_ci }; 11962306a36Sopenharmony_ci }; 12062306a36Sopenharmony_ci}; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic const struct ad7746_chan_info ad7746_chan_info[] = { 12362306a36Sopenharmony_ci [VIN] = { 12462306a36Sopenharmony_ci .addr = AD7746_REG_VT_DATA_HIGH, 12562306a36Sopenharmony_ci .vtmd = AD7746_VTSETUP_VTMD_EXT_VIN, 12662306a36Sopenharmony_ci }, 12762306a36Sopenharmony_ci [VIN_VDD] = { 12862306a36Sopenharmony_ci .addr = AD7746_REG_VT_DATA_HIGH, 12962306a36Sopenharmony_ci .vtmd = AD7746_VTSETUP_VTMD_VDD_MON, 13062306a36Sopenharmony_ci }, 13162306a36Sopenharmony_ci [TEMP_INT] = { 13262306a36Sopenharmony_ci .addr = AD7746_REG_VT_DATA_HIGH, 13362306a36Sopenharmony_ci .vtmd = AD7746_VTSETUP_VTMD_INT_TEMP, 13462306a36Sopenharmony_ci }, 13562306a36Sopenharmony_ci [TEMP_EXT] = { 13662306a36Sopenharmony_ci .addr = AD7746_REG_VT_DATA_HIGH, 13762306a36Sopenharmony_ci .vtmd = AD7746_VTSETUP_VTMD_EXT_TEMP, 13862306a36Sopenharmony_ci }, 13962306a36Sopenharmony_ci [CIN1] = { 14062306a36Sopenharmony_ci .addr = AD7746_REG_CAP_DATA_HIGH, 14162306a36Sopenharmony_ci }, 14262306a36Sopenharmony_ci [CIN1_DIFF] = { 14362306a36Sopenharmony_ci .addr = AD7746_REG_CAP_DATA_HIGH, 14462306a36Sopenharmony_ci .capdiff = 1, 14562306a36Sopenharmony_ci }, 14662306a36Sopenharmony_ci [CIN2] = { 14762306a36Sopenharmony_ci .addr = AD7746_REG_CAP_DATA_HIGH, 14862306a36Sopenharmony_ci .cin2 = 1, 14962306a36Sopenharmony_ci }, 15062306a36Sopenharmony_ci [CIN2_DIFF] = { 15162306a36Sopenharmony_ci .addr = AD7746_REG_CAP_DATA_HIGH, 15262306a36Sopenharmony_ci .cin2 = 1, 15362306a36Sopenharmony_ci .capdiff = 1, 15462306a36Sopenharmony_ci }, 15562306a36Sopenharmony_ci}; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_cistatic const struct iio_chan_spec ad7746_channels[] = { 15862306a36Sopenharmony_ci [VIN] = { 15962306a36Sopenharmony_ci .type = IIO_VOLTAGE, 16062306a36Sopenharmony_ci .indexed = 1, 16162306a36Sopenharmony_ci .channel = 0, 16262306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), 16362306a36Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), 16462306a36Sopenharmony_ci .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), 16562306a36Sopenharmony_ci .address = VIN, 16662306a36Sopenharmony_ci }, 16762306a36Sopenharmony_ci [VIN_VDD] = { 16862306a36Sopenharmony_ci .type = IIO_VOLTAGE, 16962306a36Sopenharmony_ci .indexed = 1, 17062306a36Sopenharmony_ci .channel = 1, 17162306a36Sopenharmony_ci .extend_name = "supply", 17262306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), 17362306a36Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), 17462306a36Sopenharmony_ci .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), 17562306a36Sopenharmony_ci .address = VIN_VDD, 17662306a36Sopenharmony_ci }, 17762306a36Sopenharmony_ci [TEMP_INT] = { 17862306a36Sopenharmony_ci .type = IIO_TEMP, 17962306a36Sopenharmony_ci .indexed = 1, 18062306a36Sopenharmony_ci .channel = 0, 18162306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 18262306a36Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), 18362306a36Sopenharmony_ci .address = TEMP_INT, 18462306a36Sopenharmony_ci }, 18562306a36Sopenharmony_ci [TEMP_EXT] = { 18662306a36Sopenharmony_ci .type = IIO_TEMP, 18762306a36Sopenharmony_ci .indexed = 1, 18862306a36Sopenharmony_ci .channel = 1, 18962306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 19062306a36Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), 19162306a36Sopenharmony_ci .address = TEMP_EXT, 19262306a36Sopenharmony_ci }, 19362306a36Sopenharmony_ci [CIN1] = { 19462306a36Sopenharmony_ci .type = IIO_CAPACITANCE, 19562306a36Sopenharmony_ci .indexed = 1, 19662306a36Sopenharmony_ci .channel = 0, 19762306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 19862306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), 19962306a36Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | 20062306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), 20162306a36Sopenharmony_ci .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), 20262306a36Sopenharmony_ci .address = CIN1, 20362306a36Sopenharmony_ci }, 20462306a36Sopenharmony_ci [CIN1_DIFF] = { 20562306a36Sopenharmony_ci .type = IIO_CAPACITANCE, 20662306a36Sopenharmony_ci .differential = 1, 20762306a36Sopenharmony_ci .indexed = 1, 20862306a36Sopenharmony_ci .channel = 0, 20962306a36Sopenharmony_ci .channel2 = 2, 21062306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 21162306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_ZEROPOINT), 21262306a36Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | 21362306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), 21462306a36Sopenharmony_ci .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), 21562306a36Sopenharmony_ci .address = CIN1_DIFF, 21662306a36Sopenharmony_ci }, 21762306a36Sopenharmony_ci [CIN2] = { 21862306a36Sopenharmony_ci .type = IIO_CAPACITANCE, 21962306a36Sopenharmony_ci .indexed = 1, 22062306a36Sopenharmony_ci .channel = 1, 22162306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 22262306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), 22362306a36Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | 22462306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), 22562306a36Sopenharmony_ci .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), 22662306a36Sopenharmony_ci .address = CIN2, 22762306a36Sopenharmony_ci }, 22862306a36Sopenharmony_ci [CIN2_DIFF] = { 22962306a36Sopenharmony_ci .type = IIO_CAPACITANCE, 23062306a36Sopenharmony_ci .differential = 1, 23162306a36Sopenharmony_ci .indexed = 1, 23262306a36Sopenharmony_ci .channel = 1, 23362306a36Sopenharmony_ci .channel2 = 3, 23462306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 23562306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_ZEROPOINT), 23662306a36Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | 23762306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), 23862306a36Sopenharmony_ci .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), 23962306a36Sopenharmony_ci .address = CIN2_DIFF, 24062306a36Sopenharmony_ci } 24162306a36Sopenharmony_ci}; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci/* Values are Update Rate (Hz), Conversion Time (ms) + 1*/ 24462306a36Sopenharmony_cistatic const unsigned char ad7746_vt_filter_rate_table[][2] = { 24562306a36Sopenharmony_ci { 50, 20 + 1 }, { 31, 32 + 1 }, { 16, 62 + 1 }, { 8, 122 + 1 }, 24662306a36Sopenharmony_ci}; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistatic const unsigned char ad7746_cap_filter_rate_table[][2] = { 24962306a36Sopenharmony_ci { 91, 11 + 1 }, { 84, 12 + 1 }, { 50, 20 + 1 }, { 26, 38 + 1 }, 25062306a36Sopenharmony_ci { 16, 62 + 1 }, { 13, 77 + 1 }, { 11, 92 + 1 }, { 9, 110 + 1 }, 25162306a36Sopenharmony_ci}; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_cistatic int ad7746_set_capdac(struct ad7746_chip_info *chip, int channel) 25462306a36Sopenharmony_ci{ 25562306a36Sopenharmony_ci int ret = i2c_smbus_write_byte_data(chip->client, 25662306a36Sopenharmony_ci AD7746_REG_CAPDACA, 25762306a36Sopenharmony_ci chip->capdac[channel][0]); 25862306a36Sopenharmony_ci if (ret < 0) 25962306a36Sopenharmony_ci return ret; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci return i2c_smbus_write_byte_data(chip->client, 26262306a36Sopenharmony_ci AD7746_REG_CAPDACB, 26362306a36Sopenharmony_ci chip->capdac[channel][1]); 26462306a36Sopenharmony_ci} 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cistatic int ad7746_select_channel(struct iio_dev *indio_dev, 26762306a36Sopenharmony_ci struct iio_chan_spec const *chan) 26862306a36Sopenharmony_ci{ 26962306a36Sopenharmony_ci struct ad7746_chip_info *chip = iio_priv(indio_dev); 27062306a36Sopenharmony_ci u8 vt_setup, cap_setup; 27162306a36Sopenharmony_ci int ret, delay, idx; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci switch (chan->type) { 27462306a36Sopenharmony_ci case IIO_CAPACITANCE: 27562306a36Sopenharmony_ci cap_setup = FIELD_PREP(AD7746_CAPSETUP_CIN2, 27662306a36Sopenharmony_ci ad7746_chan_info[chan->address].cin2) | 27762306a36Sopenharmony_ci FIELD_PREP(AD7746_CAPSETUP_CAPDIFF, 27862306a36Sopenharmony_ci ad7746_chan_info[chan->address].capdiff) | 27962306a36Sopenharmony_ci FIELD_PREP(AD7746_CAPSETUP_CAPEN, 1); 28062306a36Sopenharmony_ci vt_setup = chip->vt_setup & ~AD7746_VTSETUP_VTEN; 28162306a36Sopenharmony_ci idx = FIELD_GET(AD7746_CONF_CAPFS_MASK, chip->config); 28262306a36Sopenharmony_ci delay = ad7746_cap_filter_rate_table[idx][1]; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci ret = ad7746_set_capdac(chip, chan->channel); 28562306a36Sopenharmony_ci if (ret < 0) 28662306a36Sopenharmony_ci return ret; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci chip->capdac_set = chan->channel; 28962306a36Sopenharmony_ci break; 29062306a36Sopenharmony_ci case IIO_VOLTAGE: 29162306a36Sopenharmony_ci case IIO_TEMP: 29262306a36Sopenharmony_ci vt_setup = FIELD_PREP(AD7746_VTSETUP_VTMD_MASK, 29362306a36Sopenharmony_ci ad7746_chan_info[chan->address].vtmd) | 29462306a36Sopenharmony_ci FIELD_PREP(AD7746_VTSETUP_VTEN, 1); 29562306a36Sopenharmony_ci cap_setup = chip->cap_setup & ~AD7746_CAPSETUP_CAPEN; 29662306a36Sopenharmony_ci idx = FIELD_GET(AD7746_CONF_VTFS_MASK, chip->config); 29762306a36Sopenharmony_ci delay = ad7746_cap_filter_rate_table[idx][1]; 29862306a36Sopenharmony_ci break; 29962306a36Sopenharmony_ci default: 30062306a36Sopenharmony_ci return -EINVAL; 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci if (chip->cap_setup != cap_setup) { 30462306a36Sopenharmony_ci ret = i2c_smbus_write_byte_data(chip->client, 30562306a36Sopenharmony_ci AD7746_REG_CAP_SETUP, 30662306a36Sopenharmony_ci cap_setup); 30762306a36Sopenharmony_ci if (ret < 0) 30862306a36Sopenharmony_ci return ret; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci chip->cap_setup = cap_setup; 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci if (chip->vt_setup != vt_setup) { 31462306a36Sopenharmony_ci ret = i2c_smbus_write_byte_data(chip->client, 31562306a36Sopenharmony_ci AD7746_REG_VT_SETUP, 31662306a36Sopenharmony_ci vt_setup); 31762306a36Sopenharmony_ci if (ret < 0) 31862306a36Sopenharmony_ci return ret; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci chip->vt_setup = vt_setup; 32162306a36Sopenharmony_ci } 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci return delay; 32462306a36Sopenharmony_ci} 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_cistatic inline ssize_t ad7746_start_calib(struct device *dev, 32762306a36Sopenharmony_ci struct device_attribute *attr, 32862306a36Sopenharmony_ci const char *buf, 32962306a36Sopenharmony_ci size_t len, 33062306a36Sopenharmony_ci u8 regval) 33162306a36Sopenharmony_ci{ 33262306a36Sopenharmony_ci struct iio_dev *indio_dev = dev_to_iio_dev(dev); 33362306a36Sopenharmony_ci struct ad7746_chip_info *chip = iio_priv(indio_dev); 33462306a36Sopenharmony_ci int ret, timeout = 10; 33562306a36Sopenharmony_ci bool doit; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci ret = kstrtobool(buf, &doit); 33862306a36Sopenharmony_ci if (ret < 0) 33962306a36Sopenharmony_ci return ret; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci if (!doit) 34262306a36Sopenharmony_ci return 0; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci mutex_lock(&chip->lock); 34562306a36Sopenharmony_ci regval |= chip->config; 34662306a36Sopenharmony_ci ret = i2c_smbus_write_byte_data(chip->client, AD7746_REG_CFG, regval); 34762306a36Sopenharmony_ci if (ret < 0) 34862306a36Sopenharmony_ci goto unlock; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci do { 35162306a36Sopenharmony_ci msleep(20); 35262306a36Sopenharmony_ci ret = i2c_smbus_read_byte_data(chip->client, AD7746_REG_CFG); 35362306a36Sopenharmony_ci if (ret < 0) 35462306a36Sopenharmony_ci goto unlock; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci } while ((ret == regval) && timeout--); 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci mutex_unlock(&chip->lock); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci return len; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ciunlock: 36362306a36Sopenharmony_ci mutex_unlock(&chip->lock); 36462306a36Sopenharmony_ci return ret; 36562306a36Sopenharmony_ci} 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cistatic ssize_t ad7746_start_offset_calib(struct device *dev, 36862306a36Sopenharmony_ci struct device_attribute *attr, 36962306a36Sopenharmony_ci const char *buf, 37062306a36Sopenharmony_ci size_t len) 37162306a36Sopenharmony_ci{ 37262306a36Sopenharmony_ci struct iio_dev *indio_dev = dev_to_iio_dev(dev); 37362306a36Sopenharmony_ci int ret = ad7746_select_channel(indio_dev, 37462306a36Sopenharmony_ci &ad7746_channels[to_iio_dev_attr(attr)->address]); 37562306a36Sopenharmony_ci if (ret < 0) 37662306a36Sopenharmony_ci return ret; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci return ad7746_start_calib(dev, attr, buf, len, 37962306a36Sopenharmony_ci FIELD_PREP(AD7746_CONF_MODE_MASK, 38062306a36Sopenharmony_ci AD7746_CONF_MODE_OFFS_CAL)); 38162306a36Sopenharmony_ci} 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_cistatic ssize_t ad7746_start_gain_calib(struct device *dev, 38462306a36Sopenharmony_ci struct device_attribute *attr, 38562306a36Sopenharmony_ci const char *buf, 38662306a36Sopenharmony_ci size_t len) 38762306a36Sopenharmony_ci{ 38862306a36Sopenharmony_ci struct iio_dev *indio_dev = dev_to_iio_dev(dev); 38962306a36Sopenharmony_ci int ret = ad7746_select_channel(indio_dev, 39062306a36Sopenharmony_ci &ad7746_channels[to_iio_dev_attr(attr)->address]); 39162306a36Sopenharmony_ci if (ret < 0) 39262306a36Sopenharmony_ci return ret; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci return ad7746_start_calib(dev, attr, buf, len, 39562306a36Sopenharmony_ci FIELD_PREP(AD7746_CONF_MODE_MASK, 39662306a36Sopenharmony_ci AD7746_CONF_MODE_GAIN_CAL)); 39762306a36Sopenharmony_ci} 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_cistatic IIO_DEVICE_ATTR(in_capacitance0_calibbias_calibration, 40062306a36Sopenharmony_ci 0200, NULL, ad7746_start_offset_calib, CIN1); 40162306a36Sopenharmony_cistatic IIO_DEVICE_ATTR(in_capacitance1_calibbias_calibration, 40262306a36Sopenharmony_ci 0200, NULL, ad7746_start_offset_calib, CIN2); 40362306a36Sopenharmony_cistatic IIO_DEVICE_ATTR(in_capacitance0_calibscale_calibration, 40462306a36Sopenharmony_ci 0200, NULL, ad7746_start_gain_calib, CIN1); 40562306a36Sopenharmony_cistatic IIO_DEVICE_ATTR(in_capacitance1_calibscale_calibration, 40662306a36Sopenharmony_ci 0200, NULL, ad7746_start_gain_calib, CIN2); 40762306a36Sopenharmony_cistatic IIO_DEVICE_ATTR(in_voltage0_calibscale_calibration, 40862306a36Sopenharmony_ci 0200, NULL, ad7746_start_gain_calib, VIN); 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_cistatic int ad7746_store_cap_filter_rate_setup(struct ad7746_chip_info *chip, 41162306a36Sopenharmony_ci int val) 41262306a36Sopenharmony_ci{ 41362306a36Sopenharmony_ci int i; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ad7746_cap_filter_rate_table); i++) 41662306a36Sopenharmony_ci if (val >= ad7746_cap_filter_rate_table[i][0]) 41762306a36Sopenharmony_ci break; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci if (i >= ARRAY_SIZE(ad7746_cap_filter_rate_table)) 42062306a36Sopenharmony_ci i = ARRAY_SIZE(ad7746_cap_filter_rate_table) - 1; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci chip->config &= ~AD7746_CONF_CAPFS_MASK; 42362306a36Sopenharmony_ci chip->config |= FIELD_PREP(AD7746_CONF_CAPFS_MASK, i); 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci return 0; 42662306a36Sopenharmony_ci} 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_cistatic int ad7746_store_vt_filter_rate_setup(struct ad7746_chip_info *chip, 42962306a36Sopenharmony_ci int val) 43062306a36Sopenharmony_ci{ 43162306a36Sopenharmony_ci int i; 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ad7746_vt_filter_rate_table); i++) 43462306a36Sopenharmony_ci if (val >= ad7746_vt_filter_rate_table[i][0]) 43562306a36Sopenharmony_ci break; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci if (i >= ARRAY_SIZE(ad7746_vt_filter_rate_table)) 43862306a36Sopenharmony_ci i = ARRAY_SIZE(ad7746_vt_filter_rate_table) - 1; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci chip->config &= ~AD7746_CONF_VTFS_MASK; 44162306a36Sopenharmony_ci chip->config |= FIELD_PREP(AD7746_CONF_VTFS_MASK, i); 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci return 0; 44462306a36Sopenharmony_ci} 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_cistatic struct attribute *ad7746_attributes[] = { 44762306a36Sopenharmony_ci &iio_dev_attr_in_capacitance0_calibbias_calibration.dev_attr.attr, 44862306a36Sopenharmony_ci &iio_dev_attr_in_capacitance0_calibscale_calibration.dev_attr.attr, 44962306a36Sopenharmony_ci &iio_dev_attr_in_capacitance1_calibscale_calibration.dev_attr.attr, 45062306a36Sopenharmony_ci &iio_dev_attr_in_capacitance1_calibbias_calibration.dev_attr.attr, 45162306a36Sopenharmony_ci &iio_dev_attr_in_voltage0_calibscale_calibration.dev_attr.attr, 45262306a36Sopenharmony_ci NULL, 45362306a36Sopenharmony_ci}; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_cistatic const struct attribute_group ad7746_attribute_group = { 45662306a36Sopenharmony_ci .attrs = ad7746_attributes, 45762306a36Sopenharmony_ci}; 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_cistatic int ad7746_write_raw(struct iio_dev *indio_dev, 46062306a36Sopenharmony_ci struct iio_chan_spec const *chan, 46162306a36Sopenharmony_ci int val, 46262306a36Sopenharmony_ci int val2, 46362306a36Sopenharmony_ci long mask) 46462306a36Sopenharmony_ci{ 46562306a36Sopenharmony_ci struct ad7746_chip_info *chip = iio_priv(indio_dev); 46662306a36Sopenharmony_ci int ret, reg; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci switch (mask) { 46962306a36Sopenharmony_ci case IIO_CHAN_INFO_CALIBSCALE: 47062306a36Sopenharmony_ci if (val != 1) 47162306a36Sopenharmony_ci return -EINVAL; 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci val = (val2 * 1024) / 15625; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci switch (chan->type) { 47662306a36Sopenharmony_ci case IIO_CAPACITANCE: 47762306a36Sopenharmony_ci reg = AD7746_REG_CAP_GAINH; 47862306a36Sopenharmony_ci break; 47962306a36Sopenharmony_ci case IIO_VOLTAGE: 48062306a36Sopenharmony_ci reg = AD7746_REG_VOLT_GAINH; 48162306a36Sopenharmony_ci break; 48262306a36Sopenharmony_ci default: 48362306a36Sopenharmony_ci return -EINVAL; 48462306a36Sopenharmony_ci } 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci mutex_lock(&chip->lock); 48762306a36Sopenharmony_ci ret = i2c_smbus_write_word_swapped(chip->client, reg, val); 48862306a36Sopenharmony_ci mutex_unlock(&chip->lock); 48962306a36Sopenharmony_ci if (ret < 0) 49062306a36Sopenharmony_ci return ret; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci return 0; 49362306a36Sopenharmony_ci case IIO_CHAN_INFO_CALIBBIAS: 49462306a36Sopenharmony_ci if (val < 0 || val > 0xFFFF) 49562306a36Sopenharmony_ci return -EINVAL; 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci mutex_lock(&chip->lock); 49862306a36Sopenharmony_ci ret = i2c_smbus_write_word_swapped(chip->client, 49962306a36Sopenharmony_ci AD7746_REG_CAP_OFFH, val); 50062306a36Sopenharmony_ci mutex_unlock(&chip->lock); 50162306a36Sopenharmony_ci if (ret < 0) 50262306a36Sopenharmony_ci return ret; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci return 0; 50562306a36Sopenharmony_ci case IIO_CHAN_INFO_OFFSET: 50662306a36Sopenharmony_ci case IIO_CHAN_INFO_ZEROPOINT: 50762306a36Sopenharmony_ci if (val < 0 || val > 43008000) /* 21pF */ 50862306a36Sopenharmony_ci return -EINVAL; 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci /* 51162306a36Sopenharmony_ci * CAPDAC Scale = 21pF_typ / 127 51262306a36Sopenharmony_ci * CIN Scale = 8.192pF / 2^24 51362306a36Sopenharmony_ci * Offset Scale = CAPDAC Scale / CIN Scale = 338646 51462306a36Sopenharmony_ci */ 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci val /= 338646; 51762306a36Sopenharmony_ci mutex_lock(&chip->lock); 51862306a36Sopenharmony_ci chip->capdac[chan->channel][chan->differential] = val > 0 ? 51962306a36Sopenharmony_ci FIELD_PREP(AD7746_CAPDAC_DACP_MASK, val) | AD7746_CAPDAC_DACEN : 0; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci ret = ad7746_set_capdac(chip, chan->channel); 52262306a36Sopenharmony_ci if (ret < 0) { 52362306a36Sopenharmony_ci mutex_unlock(&chip->lock); 52462306a36Sopenharmony_ci return ret; 52562306a36Sopenharmony_ci } 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci chip->capdac_set = chan->channel; 52862306a36Sopenharmony_ci mutex_unlock(&chip->lock); 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci return 0; 53162306a36Sopenharmony_ci case IIO_CHAN_INFO_SAMP_FREQ: 53262306a36Sopenharmony_ci if (val2) 53362306a36Sopenharmony_ci return -EINVAL; 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci switch (chan->type) { 53662306a36Sopenharmony_ci case IIO_CAPACITANCE: 53762306a36Sopenharmony_ci mutex_lock(&chip->lock); 53862306a36Sopenharmony_ci ret = ad7746_store_cap_filter_rate_setup(chip, val); 53962306a36Sopenharmony_ci mutex_unlock(&chip->lock); 54062306a36Sopenharmony_ci return ret; 54162306a36Sopenharmony_ci case IIO_VOLTAGE: 54262306a36Sopenharmony_ci mutex_lock(&chip->lock); 54362306a36Sopenharmony_ci ret = ad7746_store_vt_filter_rate_setup(chip, val); 54462306a36Sopenharmony_ci mutex_unlock(&chip->lock); 54562306a36Sopenharmony_ci return ret; 54662306a36Sopenharmony_ci default: 54762306a36Sopenharmony_ci return -EINVAL; 54862306a36Sopenharmony_ci } 54962306a36Sopenharmony_ci default: 55062306a36Sopenharmony_ci return -EINVAL; 55162306a36Sopenharmony_ci } 55262306a36Sopenharmony_ci} 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_cistatic const int ad7746_v_samp_freq[] = { 50, 31, 16, 8, }; 55562306a36Sopenharmony_cistatic const int ad7746_cap_samp_freq[] = { 91, 84, 50, 26, 16, 13, 11, 9, }; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_cistatic int ad7746_read_avail(struct iio_dev *indio_dev, 55862306a36Sopenharmony_ci struct iio_chan_spec const *chan, const int **vals, 55962306a36Sopenharmony_ci int *type, int *length, long mask) 56062306a36Sopenharmony_ci{ 56162306a36Sopenharmony_ci if (mask != IIO_CHAN_INFO_SAMP_FREQ) 56262306a36Sopenharmony_ci return -EINVAL; 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci switch (chan->type) { 56562306a36Sopenharmony_ci case IIO_VOLTAGE: 56662306a36Sopenharmony_ci *vals = ad7746_v_samp_freq; 56762306a36Sopenharmony_ci *length = ARRAY_SIZE(ad7746_v_samp_freq); 56862306a36Sopenharmony_ci break; 56962306a36Sopenharmony_ci case IIO_CAPACITANCE: 57062306a36Sopenharmony_ci *vals = ad7746_cap_samp_freq; 57162306a36Sopenharmony_ci *length = ARRAY_SIZE(ad7746_cap_samp_freq); 57262306a36Sopenharmony_ci break; 57362306a36Sopenharmony_ci default: 57462306a36Sopenharmony_ci return -EINVAL; 57562306a36Sopenharmony_ci } 57662306a36Sopenharmony_ci *type = IIO_VAL_INT; 57762306a36Sopenharmony_ci return IIO_AVAIL_LIST; 57862306a36Sopenharmony_ci} 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_cistatic int ad7746_read_channel(struct iio_dev *indio_dev, 58162306a36Sopenharmony_ci struct iio_chan_spec const *chan, 58262306a36Sopenharmony_ci int *val) 58362306a36Sopenharmony_ci{ 58462306a36Sopenharmony_ci struct ad7746_chip_info *chip = iio_priv(indio_dev); 58562306a36Sopenharmony_ci int ret, delay; 58662306a36Sopenharmony_ci u8 data[3]; 58762306a36Sopenharmony_ci u8 regval; 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci ret = ad7746_select_channel(indio_dev, chan); 59062306a36Sopenharmony_ci if (ret < 0) 59162306a36Sopenharmony_ci return ret; 59262306a36Sopenharmony_ci delay = ret; 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci regval = chip->config | FIELD_PREP(AD7746_CONF_MODE_MASK, 59562306a36Sopenharmony_ci AD7746_CONF_MODE_SINGLE_CONV); 59662306a36Sopenharmony_ci ret = i2c_smbus_write_byte_data(chip->client, AD7746_REG_CFG, regval); 59762306a36Sopenharmony_ci if (ret < 0) 59862306a36Sopenharmony_ci return ret; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci msleep(delay); 60162306a36Sopenharmony_ci /* Now read the actual register */ 60262306a36Sopenharmony_ci ret = i2c_smbus_read_i2c_block_data(chip->client, 60362306a36Sopenharmony_ci ad7746_chan_info[chan->address].addr, 60462306a36Sopenharmony_ci sizeof(data), data); 60562306a36Sopenharmony_ci if (ret < 0) 60662306a36Sopenharmony_ci return ret; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci /* 60962306a36Sopenharmony_ci * Offset applied internally becaue the _offset userspace interface is 61062306a36Sopenharmony_ci * needed for the CAP DACs which apply a controllable offset. 61162306a36Sopenharmony_ci */ 61262306a36Sopenharmony_ci *val = get_unaligned_be24(data) - 0x800000; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci return 0; 61562306a36Sopenharmony_ci} 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_cistatic int ad7746_read_raw(struct iio_dev *indio_dev, 61862306a36Sopenharmony_ci struct iio_chan_spec const *chan, 61962306a36Sopenharmony_ci int *val, int *val2, 62062306a36Sopenharmony_ci long mask) 62162306a36Sopenharmony_ci{ 62262306a36Sopenharmony_ci struct ad7746_chip_info *chip = iio_priv(indio_dev); 62362306a36Sopenharmony_ci int ret, idx; 62462306a36Sopenharmony_ci u8 reg; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci switch (mask) { 62762306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 62862306a36Sopenharmony_ci mutex_lock(&chip->lock); 62962306a36Sopenharmony_ci ret = ad7746_read_channel(indio_dev, chan, val); 63062306a36Sopenharmony_ci mutex_unlock(&chip->lock); 63162306a36Sopenharmony_ci if (ret < 0) 63262306a36Sopenharmony_ci return ret; 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci return IIO_VAL_INT; 63562306a36Sopenharmony_ci case IIO_CHAN_INFO_CALIBSCALE: 63662306a36Sopenharmony_ci switch (chan->type) { 63762306a36Sopenharmony_ci case IIO_CAPACITANCE: 63862306a36Sopenharmony_ci reg = AD7746_REG_CAP_GAINH; 63962306a36Sopenharmony_ci break; 64062306a36Sopenharmony_ci case IIO_VOLTAGE: 64162306a36Sopenharmony_ci reg = AD7746_REG_VOLT_GAINH; 64262306a36Sopenharmony_ci break; 64362306a36Sopenharmony_ci default: 64462306a36Sopenharmony_ci return -EINVAL; 64562306a36Sopenharmony_ci } 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci mutex_lock(&chip->lock); 64862306a36Sopenharmony_ci ret = i2c_smbus_read_word_swapped(chip->client, reg); 64962306a36Sopenharmony_ci mutex_unlock(&chip->lock); 65062306a36Sopenharmony_ci if (ret < 0) 65162306a36Sopenharmony_ci return ret; 65262306a36Sopenharmony_ci /* 1 + gain_val / 2^16 */ 65362306a36Sopenharmony_ci *val = 1; 65462306a36Sopenharmony_ci *val2 = (15625 * ret) / 1024; 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci return IIO_VAL_INT_PLUS_MICRO; 65762306a36Sopenharmony_ci case IIO_CHAN_INFO_CALIBBIAS: 65862306a36Sopenharmony_ci mutex_lock(&chip->lock); 65962306a36Sopenharmony_ci ret = i2c_smbus_read_word_swapped(chip->client, 66062306a36Sopenharmony_ci AD7746_REG_CAP_OFFH); 66162306a36Sopenharmony_ci mutex_unlock(&chip->lock); 66262306a36Sopenharmony_ci if (ret < 0) 66362306a36Sopenharmony_ci return ret; 66462306a36Sopenharmony_ci *val = ret; 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci return IIO_VAL_INT; 66762306a36Sopenharmony_ci case IIO_CHAN_INFO_OFFSET: 66862306a36Sopenharmony_ci case IIO_CHAN_INFO_ZEROPOINT: 66962306a36Sopenharmony_ci *val = FIELD_GET(AD7746_CAPDAC_DACP_MASK, 67062306a36Sopenharmony_ci chip->capdac[chan->channel][chan->differential]) * 338646; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci return IIO_VAL_INT; 67362306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 67462306a36Sopenharmony_ci switch (chan->type) { 67562306a36Sopenharmony_ci case IIO_CAPACITANCE: 67662306a36Sopenharmony_ci /* 8.192pf / 2^24 */ 67762306a36Sopenharmony_ci *val = 0; 67862306a36Sopenharmony_ci *val2 = 488; 67962306a36Sopenharmony_ci return IIO_VAL_INT_PLUS_NANO; 68062306a36Sopenharmony_ci case IIO_VOLTAGE: 68162306a36Sopenharmony_ci /* 1170mV / 2^23 */ 68262306a36Sopenharmony_ci *val = 1170; 68362306a36Sopenharmony_ci if (chan->channel == 1) 68462306a36Sopenharmony_ci *val *= 6; 68562306a36Sopenharmony_ci *val2 = 23; 68662306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL_LOG2; 68762306a36Sopenharmony_ci case IIO_TEMP: 68862306a36Sopenharmony_ci *val = 125; 68962306a36Sopenharmony_ci *val2 = 8; 69062306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL_LOG2; 69162306a36Sopenharmony_ci default: 69262306a36Sopenharmony_ci return -EINVAL; 69362306a36Sopenharmony_ci } 69462306a36Sopenharmony_ci case IIO_CHAN_INFO_SAMP_FREQ: 69562306a36Sopenharmony_ci switch (chan->type) { 69662306a36Sopenharmony_ci case IIO_CAPACITANCE: 69762306a36Sopenharmony_ci idx = FIELD_GET(AD7746_CONF_CAPFS_MASK, chip->config); 69862306a36Sopenharmony_ci *val = ad7746_cap_filter_rate_table[idx][0]; 69962306a36Sopenharmony_ci return IIO_VAL_INT; 70062306a36Sopenharmony_ci case IIO_VOLTAGE: 70162306a36Sopenharmony_ci idx = FIELD_GET(AD7746_CONF_VTFS_MASK, chip->config); 70262306a36Sopenharmony_ci *val = ad7746_vt_filter_rate_table[idx][0]; 70362306a36Sopenharmony_ci return IIO_VAL_INT; 70462306a36Sopenharmony_ci default: 70562306a36Sopenharmony_ci return -EINVAL; 70662306a36Sopenharmony_ci } 70762306a36Sopenharmony_ci default: 70862306a36Sopenharmony_ci return -EINVAL; 70962306a36Sopenharmony_ci } 71062306a36Sopenharmony_ci} 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_cistatic const struct iio_info ad7746_info = { 71362306a36Sopenharmony_ci .attrs = &ad7746_attribute_group, 71462306a36Sopenharmony_ci .read_raw = ad7746_read_raw, 71562306a36Sopenharmony_ci .read_avail = ad7746_read_avail, 71662306a36Sopenharmony_ci .write_raw = ad7746_write_raw, 71762306a36Sopenharmony_ci}; 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_cistatic int ad7746_probe(struct i2c_client *client) 72062306a36Sopenharmony_ci{ 72162306a36Sopenharmony_ci const struct i2c_device_id *id = i2c_client_get_device_id(client); 72262306a36Sopenharmony_ci struct device *dev = &client->dev; 72362306a36Sopenharmony_ci struct ad7746_chip_info *chip; 72462306a36Sopenharmony_ci struct iio_dev *indio_dev; 72562306a36Sopenharmony_ci unsigned char regval = 0; 72662306a36Sopenharmony_ci unsigned int vdd_permille; 72762306a36Sopenharmony_ci int ret; 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); 73062306a36Sopenharmony_ci if (!indio_dev) 73162306a36Sopenharmony_ci return -ENOMEM; 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci chip = iio_priv(indio_dev); 73462306a36Sopenharmony_ci mutex_init(&chip->lock); 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci chip->client = client; 73762306a36Sopenharmony_ci chip->capdac_set = -1; 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci indio_dev->name = id->name; 74062306a36Sopenharmony_ci indio_dev->info = &ad7746_info; 74162306a36Sopenharmony_ci indio_dev->channels = ad7746_channels; 74262306a36Sopenharmony_ci if (id->driver_data == 7746) 74362306a36Sopenharmony_ci indio_dev->num_channels = ARRAY_SIZE(ad7746_channels); 74462306a36Sopenharmony_ci else 74562306a36Sopenharmony_ci indio_dev->num_channels = ARRAY_SIZE(ad7746_channels) - 2; 74662306a36Sopenharmony_ci indio_dev->modes = INDIO_DIRECT_MODE; 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci if (device_property_read_bool(dev, "adi,exca-output-en")) { 74962306a36Sopenharmony_ci if (device_property_read_bool(dev, "adi,exca-output-invert")) 75062306a36Sopenharmony_ci regval |= AD7746_EXCSETUP_NEXCA; 75162306a36Sopenharmony_ci else 75262306a36Sopenharmony_ci regval |= AD7746_EXCSETUP_EXCA; 75362306a36Sopenharmony_ci } 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci if (device_property_read_bool(dev, "adi,excb-output-en")) { 75662306a36Sopenharmony_ci if (device_property_read_bool(dev, "adi,excb-output-invert")) 75762306a36Sopenharmony_ci regval |= AD7746_EXCSETUP_NEXCB; 75862306a36Sopenharmony_ci else 75962306a36Sopenharmony_ci regval |= AD7746_EXCSETUP_EXCB; 76062306a36Sopenharmony_ci } 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci ret = device_property_read_u32(dev, "adi,excitation-vdd-permille", 76362306a36Sopenharmony_ci &vdd_permille); 76462306a36Sopenharmony_ci if (!ret) { 76562306a36Sopenharmony_ci switch (vdd_permille) { 76662306a36Sopenharmony_ci case 125: 76762306a36Sopenharmony_ci regval |= FIELD_PREP(AD7746_EXCSETUP_EXCLVL_MASK, 0); 76862306a36Sopenharmony_ci break; 76962306a36Sopenharmony_ci case 250: 77062306a36Sopenharmony_ci regval |= FIELD_PREP(AD7746_EXCSETUP_EXCLVL_MASK, 1); 77162306a36Sopenharmony_ci break; 77262306a36Sopenharmony_ci case 375: 77362306a36Sopenharmony_ci regval |= FIELD_PREP(AD7746_EXCSETUP_EXCLVL_MASK, 2); 77462306a36Sopenharmony_ci break; 77562306a36Sopenharmony_ci case 500: 77662306a36Sopenharmony_ci regval |= FIELD_PREP(AD7746_EXCSETUP_EXCLVL_MASK, 3); 77762306a36Sopenharmony_ci break; 77862306a36Sopenharmony_ci default: 77962306a36Sopenharmony_ci break; 78062306a36Sopenharmony_ci } 78162306a36Sopenharmony_ci } 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci ret = i2c_smbus_write_byte_data(chip->client, AD7746_REG_EXC_SETUP, 78462306a36Sopenharmony_ci regval); 78562306a36Sopenharmony_ci if (ret < 0) 78662306a36Sopenharmony_ci return ret; 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci return devm_iio_device_register(indio_dev->dev.parent, indio_dev); 78962306a36Sopenharmony_ci} 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_cistatic const struct i2c_device_id ad7746_id[] = { 79262306a36Sopenharmony_ci { "ad7745", 7745 }, 79362306a36Sopenharmony_ci { "ad7746", 7746 }, 79462306a36Sopenharmony_ci { "ad7747", 7747 }, 79562306a36Sopenharmony_ci {} 79662306a36Sopenharmony_ci}; 79762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, ad7746_id); 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_cistatic const struct of_device_id ad7746_of_match[] = { 80062306a36Sopenharmony_ci { .compatible = "adi,ad7745" }, 80162306a36Sopenharmony_ci { .compatible = "adi,ad7746" }, 80262306a36Sopenharmony_ci { .compatible = "adi,ad7747" }, 80362306a36Sopenharmony_ci { }, 80462306a36Sopenharmony_ci}; 80562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, ad7746_of_match); 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_cistatic struct i2c_driver ad7746_driver = { 80862306a36Sopenharmony_ci .driver = { 80962306a36Sopenharmony_ci .name = KBUILD_MODNAME, 81062306a36Sopenharmony_ci .of_match_table = ad7746_of_match, 81162306a36Sopenharmony_ci }, 81262306a36Sopenharmony_ci .probe = ad7746_probe, 81362306a36Sopenharmony_ci .id_table = ad7746_id, 81462306a36Sopenharmony_ci}; 81562306a36Sopenharmony_cimodule_i2c_driver(ad7746_driver); 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ciMODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); 81862306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices AD7746/5/7 capacitive sensor driver"); 81962306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 820