162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2013 Oskar Andero <oskar.andero@gmail.com> 462306a36Sopenharmony_ci * Copyright (C) 2014 Rose Technology 562306a36Sopenharmony_ci * Allan Bendorff Jensen <abj@rosetechnology.dk> 662306a36Sopenharmony_ci * Soren Andersen <san@rosetechnology.dk> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Driver for following ADC chips from Microchip Technology's: 962306a36Sopenharmony_ci * 10 Bit converter 1062306a36Sopenharmony_ci * MCP3001 1162306a36Sopenharmony_ci * MCP3002 1262306a36Sopenharmony_ci * MCP3004 1362306a36Sopenharmony_ci * MCP3008 1462306a36Sopenharmony_ci * ------------ 1562306a36Sopenharmony_ci * 12 bit converter 1662306a36Sopenharmony_ci * MCP3201 1762306a36Sopenharmony_ci * MCP3202 1862306a36Sopenharmony_ci * MCP3204 1962306a36Sopenharmony_ci * MCP3208 2062306a36Sopenharmony_ci * ------------ 2162306a36Sopenharmony_ci * 13 bit converter 2262306a36Sopenharmony_ci * MCP3301 2362306a36Sopenharmony_ci * ------------ 2462306a36Sopenharmony_ci * 22 bit converter 2562306a36Sopenharmony_ci * MCP3550 2662306a36Sopenharmony_ci * MCP3551 2762306a36Sopenharmony_ci * MCP3553 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * Datasheet can be found here: 3062306a36Sopenharmony_ci * https://ww1.microchip.com/downloads/en/DeviceDoc/21293C.pdf mcp3001 3162306a36Sopenharmony_ci * https://ww1.microchip.com/downloads/en/DeviceDoc/21294E.pdf mcp3002 3262306a36Sopenharmony_ci * https://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf mcp3004/08 3362306a36Sopenharmony_ci * http://ww1.microchip.com/downloads/en/DeviceDoc/21290D.pdf mcp3201 3462306a36Sopenharmony_ci * http://ww1.microchip.com/downloads/en/DeviceDoc/21034D.pdf mcp3202 3562306a36Sopenharmony_ci * http://ww1.microchip.com/downloads/en/DeviceDoc/21298c.pdf mcp3204/08 3662306a36Sopenharmony_ci * https://ww1.microchip.com/downloads/en/DeviceDoc/21700E.pdf mcp3301 3762306a36Sopenharmony_ci * http://ww1.microchip.com/downloads/en/DeviceDoc/21950D.pdf mcp3550/1/3 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#include <linux/err.h> 4162306a36Sopenharmony_ci#include <linux/delay.h> 4262306a36Sopenharmony_ci#include <linux/spi/spi.h> 4362306a36Sopenharmony_ci#include <linux/module.h> 4462306a36Sopenharmony_ci#include <linux/mod_devicetable.h> 4562306a36Sopenharmony_ci#include <linux/iio/iio.h> 4662306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cienum { 4962306a36Sopenharmony_ci mcp3001, 5062306a36Sopenharmony_ci mcp3002, 5162306a36Sopenharmony_ci mcp3004, 5262306a36Sopenharmony_ci mcp3008, 5362306a36Sopenharmony_ci mcp3201, 5462306a36Sopenharmony_ci mcp3202, 5562306a36Sopenharmony_ci mcp3204, 5662306a36Sopenharmony_ci mcp3208, 5762306a36Sopenharmony_ci mcp3301, 5862306a36Sopenharmony_ci mcp3550_50, 5962306a36Sopenharmony_ci mcp3550_60, 6062306a36Sopenharmony_ci mcp3551, 6162306a36Sopenharmony_ci mcp3553, 6262306a36Sopenharmony_ci}; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistruct mcp320x_chip_info { 6562306a36Sopenharmony_ci const struct iio_chan_spec *channels; 6662306a36Sopenharmony_ci unsigned int num_channels; 6762306a36Sopenharmony_ci unsigned int resolution; 6862306a36Sopenharmony_ci unsigned int conv_time; /* usec */ 6962306a36Sopenharmony_ci}; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci/** 7262306a36Sopenharmony_ci * struct mcp320x - Microchip SPI ADC instance 7362306a36Sopenharmony_ci * @spi: SPI slave (parent of the IIO device) 7462306a36Sopenharmony_ci * @msg: SPI message to select a channel and receive a value from the ADC 7562306a36Sopenharmony_ci * @transfer: SPI transfers used by @msg 7662306a36Sopenharmony_ci * @start_conv_msg: SPI message to start a conversion by briefly asserting CS 7762306a36Sopenharmony_ci * @start_conv_transfer: SPI transfer used by @start_conv_msg 7862306a36Sopenharmony_ci * @reg: regulator generating Vref 7962306a36Sopenharmony_ci * @lock: protects read sequences 8062306a36Sopenharmony_ci * @chip_info: ADC properties 8162306a36Sopenharmony_ci * @tx_buf: buffer for @transfer[0] (not used on single-channel converters) 8262306a36Sopenharmony_ci * @rx_buf: buffer for @transfer[1] 8362306a36Sopenharmony_ci */ 8462306a36Sopenharmony_cistruct mcp320x { 8562306a36Sopenharmony_ci struct spi_device *spi; 8662306a36Sopenharmony_ci struct spi_message msg; 8762306a36Sopenharmony_ci struct spi_transfer transfer[2]; 8862306a36Sopenharmony_ci struct spi_message start_conv_msg; 8962306a36Sopenharmony_ci struct spi_transfer start_conv_transfer; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci struct regulator *reg; 9262306a36Sopenharmony_ci struct mutex lock; 9362306a36Sopenharmony_ci const struct mcp320x_chip_info *chip_info; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci u8 tx_buf __aligned(IIO_DMA_MINALIGN); 9662306a36Sopenharmony_ci u8 rx_buf[4]; 9762306a36Sopenharmony_ci}; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic int mcp320x_channel_to_tx_data(int device_index, 10062306a36Sopenharmony_ci const unsigned int channel, bool differential) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci int start_bit = 1; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci switch (device_index) { 10562306a36Sopenharmony_ci case mcp3002: 10662306a36Sopenharmony_ci case mcp3202: 10762306a36Sopenharmony_ci return ((start_bit << 4) | (!differential << 3) | 10862306a36Sopenharmony_ci (channel << 2)); 10962306a36Sopenharmony_ci case mcp3004: 11062306a36Sopenharmony_ci case mcp3204: 11162306a36Sopenharmony_ci case mcp3008: 11262306a36Sopenharmony_ci case mcp3208: 11362306a36Sopenharmony_ci return ((start_bit << 6) | (!differential << 5) | 11462306a36Sopenharmony_ci (channel << 2)); 11562306a36Sopenharmony_ci default: 11662306a36Sopenharmony_ci return -EINVAL; 11762306a36Sopenharmony_ci } 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel, 12162306a36Sopenharmony_ci bool differential, int device_index, int *val) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci int ret; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci if (adc->chip_info->conv_time) { 12662306a36Sopenharmony_ci ret = spi_sync(adc->spi, &adc->start_conv_msg); 12762306a36Sopenharmony_ci if (ret < 0) 12862306a36Sopenharmony_ci return ret; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci usleep_range(adc->chip_info->conv_time, 13162306a36Sopenharmony_ci adc->chip_info->conv_time + 100); 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci memset(&adc->rx_buf, 0, sizeof(adc->rx_buf)); 13562306a36Sopenharmony_ci if (adc->chip_info->num_channels > 1) 13662306a36Sopenharmony_ci adc->tx_buf = mcp320x_channel_to_tx_data(device_index, channel, 13762306a36Sopenharmony_ci differential); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci ret = spi_sync(adc->spi, &adc->msg); 14062306a36Sopenharmony_ci if (ret < 0) 14162306a36Sopenharmony_ci return ret; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci switch (device_index) { 14462306a36Sopenharmony_ci case mcp3001: 14562306a36Sopenharmony_ci *val = (adc->rx_buf[0] << 5 | adc->rx_buf[1] >> 3); 14662306a36Sopenharmony_ci return 0; 14762306a36Sopenharmony_ci case mcp3002: 14862306a36Sopenharmony_ci case mcp3004: 14962306a36Sopenharmony_ci case mcp3008: 15062306a36Sopenharmony_ci *val = (adc->rx_buf[0] << 2 | adc->rx_buf[1] >> 6); 15162306a36Sopenharmony_ci return 0; 15262306a36Sopenharmony_ci case mcp3201: 15362306a36Sopenharmony_ci *val = (adc->rx_buf[0] << 7 | adc->rx_buf[1] >> 1); 15462306a36Sopenharmony_ci return 0; 15562306a36Sopenharmony_ci case mcp3202: 15662306a36Sopenharmony_ci case mcp3204: 15762306a36Sopenharmony_ci case mcp3208: 15862306a36Sopenharmony_ci *val = (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4); 15962306a36Sopenharmony_ci return 0; 16062306a36Sopenharmony_ci case mcp3301: 16162306a36Sopenharmony_ci *val = sign_extend32((adc->rx_buf[0] & 0x1f) << 8 16262306a36Sopenharmony_ci | adc->rx_buf[1], 12); 16362306a36Sopenharmony_ci return 0; 16462306a36Sopenharmony_ci case mcp3550_50: 16562306a36Sopenharmony_ci case mcp3550_60: 16662306a36Sopenharmony_ci case mcp3551: 16762306a36Sopenharmony_ci case mcp3553: { 16862306a36Sopenharmony_ci u32 raw = be32_to_cpup((__be32 *)adc->rx_buf); 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci if (!(adc->spi->mode & SPI_CPOL)) 17162306a36Sopenharmony_ci raw <<= 1; /* strip Data Ready bit in SPI mode 0,0 */ 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci /* 17462306a36Sopenharmony_ci * If the input is within -vref and vref, bit 21 is the sign. 17562306a36Sopenharmony_ci * Up to 12% overrange or underrange are allowed, in which case 17662306a36Sopenharmony_ci * bit 23 is the sign and bit 0 to 21 is the value. 17762306a36Sopenharmony_ci */ 17862306a36Sopenharmony_ci raw >>= 8; 17962306a36Sopenharmony_ci if (raw & BIT(22) && raw & BIT(23)) 18062306a36Sopenharmony_ci return -EIO; /* cannot have overrange AND underrange */ 18162306a36Sopenharmony_ci else if (raw & BIT(22)) 18262306a36Sopenharmony_ci raw &= ~BIT(22); /* overrange */ 18362306a36Sopenharmony_ci else if (raw & BIT(23) || raw & BIT(21)) 18462306a36Sopenharmony_ci raw |= GENMASK(31, 22); /* underrange or negative */ 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci *val = (s32)raw; 18762306a36Sopenharmony_ci return 0; 18862306a36Sopenharmony_ci } 18962306a36Sopenharmony_ci default: 19062306a36Sopenharmony_ci return -EINVAL; 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ci} 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_cistatic int mcp320x_read_raw(struct iio_dev *indio_dev, 19562306a36Sopenharmony_ci struct iio_chan_spec const *channel, int *val, 19662306a36Sopenharmony_ci int *val2, long mask) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci struct mcp320x *adc = iio_priv(indio_dev); 19962306a36Sopenharmony_ci int ret = -EINVAL; 20062306a36Sopenharmony_ci int device_index = 0; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci mutex_lock(&adc->lock); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci device_index = spi_get_device_id(adc->spi)->driver_data; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci switch (mask) { 20762306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 20862306a36Sopenharmony_ci ret = mcp320x_adc_conversion(adc, channel->address, 20962306a36Sopenharmony_ci channel->differential, device_index, val); 21062306a36Sopenharmony_ci if (ret < 0) 21162306a36Sopenharmony_ci goto out; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci ret = IIO_VAL_INT; 21462306a36Sopenharmony_ci break; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 21762306a36Sopenharmony_ci ret = regulator_get_voltage(adc->reg); 21862306a36Sopenharmony_ci if (ret < 0) 21962306a36Sopenharmony_ci goto out; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci /* convert regulator output voltage to mV */ 22262306a36Sopenharmony_ci *val = ret / 1000; 22362306a36Sopenharmony_ci *val2 = adc->chip_info->resolution; 22462306a36Sopenharmony_ci ret = IIO_VAL_FRACTIONAL_LOG2; 22562306a36Sopenharmony_ci break; 22662306a36Sopenharmony_ci } 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ciout: 22962306a36Sopenharmony_ci mutex_unlock(&adc->lock); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci return ret; 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci#define MCP320X_VOLTAGE_CHANNEL(num) \ 23562306a36Sopenharmony_ci { \ 23662306a36Sopenharmony_ci .type = IIO_VOLTAGE, \ 23762306a36Sopenharmony_ci .indexed = 1, \ 23862306a36Sopenharmony_ci .channel = (num), \ 23962306a36Sopenharmony_ci .address = (num), \ 24062306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 24162306a36Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \ 24262306a36Sopenharmony_ci } 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci#define MCP320X_VOLTAGE_CHANNEL_DIFF(chan1, chan2) \ 24562306a36Sopenharmony_ci { \ 24662306a36Sopenharmony_ci .type = IIO_VOLTAGE, \ 24762306a36Sopenharmony_ci .indexed = 1, \ 24862306a36Sopenharmony_ci .channel = (chan1), \ 24962306a36Sopenharmony_ci .channel2 = (chan2), \ 25062306a36Sopenharmony_ci .address = (chan1), \ 25162306a36Sopenharmony_ci .differential = 1, \ 25262306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 25362306a36Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \ 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic const struct iio_chan_spec mcp3201_channels[] = { 25762306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1), 25862306a36Sopenharmony_ci}; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_cistatic const struct iio_chan_spec mcp3202_channels[] = { 26162306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL(0), 26262306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL(1), 26362306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1), 26462306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0), 26562306a36Sopenharmony_ci}; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_cistatic const struct iio_chan_spec mcp3204_channels[] = { 26862306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL(0), 26962306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL(1), 27062306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL(2), 27162306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL(3), 27262306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1), 27362306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0), 27462306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL_DIFF(2, 3), 27562306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL_DIFF(3, 2), 27662306a36Sopenharmony_ci}; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_cistatic const struct iio_chan_spec mcp3208_channels[] = { 27962306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL(0), 28062306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL(1), 28162306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL(2), 28262306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL(3), 28362306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL(4), 28462306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL(5), 28562306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL(6), 28662306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL(7), 28762306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1), 28862306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0), 28962306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL_DIFF(2, 3), 29062306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL_DIFF(3, 2), 29162306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL_DIFF(4, 5), 29262306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL_DIFF(5, 4), 29362306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL_DIFF(6, 7), 29462306a36Sopenharmony_ci MCP320X_VOLTAGE_CHANNEL_DIFF(7, 6), 29562306a36Sopenharmony_ci}; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cistatic const struct iio_info mcp320x_info = { 29862306a36Sopenharmony_ci .read_raw = mcp320x_read_raw, 29962306a36Sopenharmony_ci}; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_cistatic const struct mcp320x_chip_info mcp320x_chip_infos[] = { 30262306a36Sopenharmony_ci [mcp3001] = { 30362306a36Sopenharmony_ci .channels = mcp3201_channels, 30462306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(mcp3201_channels), 30562306a36Sopenharmony_ci .resolution = 10 30662306a36Sopenharmony_ci }, 30762306a36Sopenharmony_ci [mcp3002] = { 30862306a36Sopenharmony_ci .channels = mcp3202_channels, 30962306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(mcp3202_channels), 31062306a36Sopenharmony_ci .resolution = 10 31162306a36Sopenharmony_ci }, 31262306a36Sopenharmony_ci [mcp3004] = { 31362306a36Sopenharmony_ci .channels = mcp3204_channels, 31462306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(mcp3204_channels), 31562306a36Sopenharmony_ci .resolution = 10 31662306a36Sopenharmony_ci }, 31762306a36Sopenharmony_ci [mcp3008] = { 31862306a36Sopenharmony_ci .channels = mcp3208_channels, 31962306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(mcp3208_channels), 32062306a36Sopenharmony_ci .resolution = 10 32162306a36Sopenharmony_ci }, 32262306a36Sopenharmony_ci [mcp3201] = { 32362306a36Sopenharmony_ci .channels = mcp3201_channels, 32462306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(mcp3201_channels), 32562306a36Sopenharmony_ci .resolution = 12 32662306a36Sopenharmony_ci }, 32762306a36Sopenharmony_ci [mcp3202] = { 32862306a36Sopenharmony_ci .channels = mcp3202_channels, 32962306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(mcp3202_channels), 33062306a36Sopenharmony_ci .resolution = 12 33162306a36Sopenharmony_ci }, 33262306a36Sopenharmony_ci [mcp3204] = { 33362306a36Sopenharmony_ci .channels = mcp3204_channels, 33462306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(mcp3204_channels), 33562306a36Sopenharmony_ci .resolution = 12 33662306a36Sopenharmony_ci }, 33762306a36Sopenharmony_ci [mcp3208] = { 33862306a36Sopenharmony_ci .channels = mcp3208_channels, 33962306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(mcp3208_channels), 34062306a36Sopenharmony_ci .resolution = 12 34162306a36Sopenharmony_ci }, 34262306a36Sopenharmony_ci [mcp3301] = { 34362306a36Sopenharmony_ci .channels = mcp3201_channels, 34462306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(mcp3201_channels), 34562306a36Sopenharmony_ci .resolution = 13 34662306a36Sopenharmony_ci }, 34762306a36Sopenharmony_ci [mcp3550_50] = { 34862306a36Sopenharmony_ci .channels = mcp3201_channels, 34962306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(mcp3201_channels), 35062306a36Sopenharmony_ci .resolution = 21, 35162306a36Sopenharmony_ci /* 2% max deviation + 144 clock periods to exit shutdown */ 35262306a36Sopenharmony_ci .conv_time = 80000 * 1.02 + 144000 / 102.4, 35362306a36Sopenharmony_ci }, 35462306a36Sopenharmony_ci [mcp3550_60] = { 35562306a36Sopenharmony_ci .channels = mcp3201_channels, 35662306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(mcp3201_channels), 35762306a36Sopenharmony_ci .resolution = 21, 35862306a36Sopenharmony_ci .conv_time = 66670 * 1.02 + 144000 / 122.88, 35962306a36Sopenharmony_ci }, 36062306a36Sopenharmony_ci [mcp3551] = { 36162306a36Sopenharmony_ci .channels = mcp3201_channels, 36262306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(mcp3201_channels), 36362306a36Sopenharmony_ci .resolution = 21, 36462306a36Sopenharmony_ci .conv_time = 73100 * 1.02 + 144000 / 112.64, 36562306a36Sopenharmony_ci }, 36662306a36Sopenharmony_ci [mcp3553] = { 36762306a36Sopenharmony_ci .channels = mcp3201_channels, 36862306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(mcp3201_channels), 36962306a36Sopenharmony_ci .resolution = 21, 37062306a36Sopenharmony_ci .conv_time = 16670 * 1.02 + 144000 / 122.88, 37162306a36Sopenharmony_ci }, 37262306a36Sopenharmony_ci}; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_cistatic int mcp320x_probe(struct spi_device *spi) 37562306a36Sopenharmony_ci{ 37662306a36Sopenharmony_ci struct iio_dev *indio_dev; 37762306a36Sopenharmony_ci struct mcp320x *adc; 37862306a36Sopenharmony_ci const struct mcp320x_chip_info *chip_info; 37962306a36Sopenharmony_ci int ret, device_index; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc)); 38262306a36Sopenharmony_ci if (!indio_dev) 38362306a36Sopenharmony_ci return -ENOMEM; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci adc = iio_priv(indio_dev); 38662306a36Sopenharmony_ci adc->spi = spi; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci indio_dev->name = spi_get_device_id(spi)->name; 38962306a36Sopenharmony_ci indio_dev->modes = INDIO_DIRECT_MODE; 39062306a36Sopenharmony_ci indio_dev->info = &mcp320x_info; 39162306a36Sopenharmony_ci spi_set_drvdata(spi, indio_dev); 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci device_index = spi_get_device_id(spi)->driver_data; 39462306a36Sopenharmony_ci chip_info = &mcp320x_chip_infos[device_index]; 39562306a36Sopenharmony_ci indio_dev->channels = chip_info->channels; 39662306a36Sopenharmony_ci indio_dev->num_channels = chip_info->num_channels; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci adc->chip_info = chip_info; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci adc->transfer[0].tx_buf = &adc->tx_buf; 40162306a36Sopenharmony_ci adc->transfer[0].len = sizeof(adc->tx_buf); 40262306a36Sopenharmony_ci adc->transfer[1].rx_buf = adc->rx_buf; 40362306a36Sopenharmony_ci adc->transfer[1].len = DIV_ROUND_UP(chip_info->resolution, 8); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci if (chip_info->num_channels == 1) 40662306a36Sopenharmony_ci /* single-channel converters are rx only (no MOSI pin) */ 40762306a36Sopenharmony_ci spi_message_init_with_transfers(&adc->msg, 40862306a36Sopenharmony_ci &adc->transfer[1], 1); 40962306a36Sopenharmony_ci else 41062306a36Sopenharmony_ci spi_message_init_with_transfers(&adc->msg, adc->transfer, 41162306a36Sopenharmony_ci ARRAY_SIZE(adc->transfer)); 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci switch (device_index) { 41462306a36Sopenharmony_ci case mcp3550_50: 41562306a36Sopenharmony_ci case mcp3550_60: 41662306a36Sopenharmony_ci case mcp3551: 41762306a36Sopenharmony_ci case mcp3553: 41862306a36Sopenharmony_ci /* rx len increases from 24 to 25 bit in SPI mode 0,0 */ 41962306a36Sopenharmony_ci if (!(spi->mode & SPI_CPOL)) 42062306a36Sopenharmony_ci adc->transfer[1].len++; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci /* conversions are started by asserting CS pin for 8 usec */ 42362306a36Sopenharmony_ci adc->start_conv_transfer.delay.value = 8; 42462306a36Sopenharmony_ci adc->start_conv_transfer.delay.unit = SPI_DELAY_UNIT_USECS; 42562306a36Sopenharmony_ci spi_message_init_with_transfers(&adc->start_conv_msg, 42662306a36Sopenharmony_ci &adc->start_conv_transfer, 1); 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci /* 42962306a36Sopenharmony_ci * If CS was previously kept low (continuous conversion mode) 43062306a36Sopenharmony_ci * and then changed to high, the chip is in shutdown. 43162306a36Sopenharmony_ci * Sometimes it fails to wake from shutdown and clocks out 43262306a36Sopenharmony_ci * only 0xffffff. The magic sequence of performing two 43362306a36Sopenharmony_ci * conversions without delay between them resets the chip 43462306a36Sopenharmony_ci * and ensures all subsequent conversions succeed. 43562306a36Sopenharmony_ci */ 43662306a36Sopenharmony_ci mcp320x_adc_conversion(adc, 0, 1, device_index, &ret); 43762306a36Sopenharmony_ci mcp320x_adc_conversion(adc, 0, 1, device_index, &ret); 43862306a36Sopenharmony_ci } 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci adc->reg = devm_regulator_get(&spi->dev, "vref"); 44162306a36Sopenharmony_ci if (IS_ERR(adc->reg)) 44262306a36Sopenharmony_ci return PTR_ERR(adc->reg); 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci ret = regulator_enable(adc->reg); 44562306a36Sopenharmony_ci if (ret < 0) 44662306a36Sopenharmony_ci return ret; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci mutex_init(&adc->lock); 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci ret = iio_device_register(indio_dev); 45162306a36Sopenharmony_ci if (ret < 0) 45262306a36Sopenharmony_ci goto reg_disable; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci return 0; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_cireg_disable: 45762306a36Sopenharmony_ci regulator_disable(adc->reg); 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci return ret; 46062306a36Sopenharmony_ci} 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_cistatic void mcp320x_remove(struct spi_device *spi) 46362306a36Sopenharmony_ci{ 46462306a36Sopenharmony_ci struct iio_dev *indio_dev = spi_get_drvdata(spi); 46562306a36Sopenharmony_ci struct mcp320x *adc = iio_priv(indio_dev); 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci iio_device_unregister(indio_dev); 46862306a36Sopenharmony_ci regulator_disable(adc->reg); 46962306a36Sopenharmony_ci} 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_cistatic const struct of_device_id mcp320x_dt_ids[] = { 47262306a36Sopenharmony_ci /* NOTE: The use of compatibles with no vendor prefix is deprecated. */ 47362306a36Sopenharmony_ci { .compatible = "mcp3001" }, 47462306a36Sopenharmony_ci { .compatible = "mcp3002" }, 47562306a36Sopenharmony_ci { .compatible = "mcp3004" }, 47662306a36Sopenharmony_ci { .compatible = "mcp3008" }, 47762306a36Sopenharmony_ci { .compatible = "mcp3201" }, 47862306a36Sopenharmony_ci { .compatible = "mcp3202" }, 47962306a36Sopenharmony_ci { .compatible = "mcp3204" }, 48062306a36Sopenharmony_ci { .compatible = "mcp3208" }, 48162306a36Sopenharmony_ci { .compatible = "mcp3301" }, 48262306a36Sopenharmony_ci { .compatible = "microchip,mcp3001" }, 48362306a36Sopenharmony_ci { .compatible = "microchip,mcp3002" }, 48462306a36Sopenharmony_ci { .compatible = "microchip,mcp3004" }, 48562306a36Sopenharmony_ci { .compatible = "microchip,mcp3008" }, 48662306a36Sopenharmony_ci { .compatible = "microchip,mcp3201" }, 48762306a36Sopenharmony_ci { .compatible = "microchip,mcp3202" }, 48862306a36Sopenharmony_ci { .compatible = "microchip,mcp3204" }, 48962306a36Sopenharmony_ci { .compatible = "microchip,mcp3208" }, 49062306a36Sopenharmony_ci { .compatible = "microchip,mcp3301" }, 49162306a36Sopenharmony_ci { .compatible = "microchip,mcp3550-50" }, 49262306a36Sopenharmony_ci { .compatible = "microchip,mcp3550-60" }, 49362306a36Sopenharmony_ci { .compatible = "microchip,mcp3551" }, 49462306a36Sopenharmony_ci { .compatible = "microchip,mcp3553" }, 49562306a36Sopenharmony_ci { } 49662306a36Sopenharmony_ci}; 49762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, mcp320x_dt_ids); 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_cistatic const struct spi_device_id mcp320x_id[] = { 50062306a36Sopenharmony_ci { "mcp3001", mcp3001 }, 50162306a36Sopenharmony_ci { "mcp3002", mcp3002 }, 50262306a36Sopenharmony_ci { "mcp3004", mcp3004 }, 50362306a36Sopenharmony_ci { "mcp3008", mcp3008 }, 50462306a36Sopenharmony_ci { "mcp3201", mcp3201 }, 50562306a36Sopenharmony_ci { "mcp3202", mcp3202 }, 50662306a36Sopenharmony_ci { "mcp3204", mcp3204 }, 50762306a36Sopenharmony_ci { "mcp3208", mcp3208 }, 50862306a36Sopenharmony_ci { "mcp3301", mcp3301 }, 50962306a36Sopenharmony_ci { "mcp3550-50", mcp3550_50 }, 51062306a36Sopenharmony_ci { "mcp3550-60", mcp3550_60 }, 51162306a36Sopenharmony_ci { "mcp3551", mcp3551 }, 51262306a36Sopenharmony_ci { "mcp3553", mcp3553 }, 51362306a36Sopenharmony_ci { } 51462306a36Sopenharmony_ci}; 51562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, mcp320x_id); 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_cistatic struct spi_driver mcp320x_driver = { 51862306a36Sopenharmony_ci .driver = { 51962306a36Sopenharmony_ci .name = "mcp320x", 52062306a36Sopenharmony_ci .of_match_table = mcp320x_dt_ids, 52162306a36Sopenharmony_ci }, 52262306a36Sopenharmony_ci .probe = mcp320x_probe, 52362306a36Sopenharmony_ci .remove = mcp320x_remove, 52462306a36Sopenharmony_ci .id_table = mcp320x_id, 52562306a36Sopenharmony_ci}; 52662306a36Sopenharmony_cimodule_spi_driver(mcp320x_driver); 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ciMODULE_AUTHOR("Oskar Andero <oskar.andero@gmail.com>"); 52962306a36Sopenharmony_ciMODULE_DESCRIPTION("Microchip Technology MCP3x01/02/04/08 and MCP3550/1/3"); 53062306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 531