// SPDX-License-Identifier: GPL-2.0+
/*
* IIO driver for MCP356X/MCP356XR and MCP346X/MCP346XR series ADC chip family
*
* Copyright (C) 2022-2023 Microchip Technology Inc. and its subsidiaries
*
* Author: Marius Cristea <marius.cristea@microchip.com>
*
* Datasheet for MCP3561, MCP3562, MCP3564 can be found here:
* https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/MCP3561-2-4-Family-Data-Sheet-DS20006181C.pdf
* Datasheet for MCP3561R, MCP3562R, MCP3564R can be found here:
* https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/MCP3561_2_4R-Data-Sheet-DS200006391C.pdf
* Datasheet for MCP3461, MCP3462, MCP3464 can be found here:
* https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/MCP3461-2-4-Two-Four-Eight-Channel-153.6-ksps-Low-Noise-16-Bit-Delta-Sigma-ADC-Data-Sheet-20006180D.pdf
* Datasheet for MCP3461R, MCP3462R, MCP3464R can be found here:
* https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/MCP3461-2-4R-Family-Data-Sheet-DS20006404C.pdf
*/
#include <linux/bitfield.h>
#include <linux/iopoll.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
#include <linux/units.h>
#include <linux/util_macros.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#define MCP3564_ADCDATA_REG 0x00
#define MCP3564_CONFIG0_REG 0x01
#define MCP3564_CONFIG0_ADC_MODE_MASK GENMASK(1, 0)
/* Current Source/Sink Selection Bits for Sensor Bias */
#define MCP3564_CONFIG0_CS_SEL_MASK GENMASK(3, 2)
/* Internal clock is selected and AMCLK is present on the analog master clock output pin */
#define MCP3564_CONFIG0_USE_INT_CLK_OUTPUT_EN 0x03
/* Internal clock is selected and no clock output is present on the CLK pin */
#define MCP3564_CONFIG0_USE_INT_CLK 0x02
/* External digital clock */
#define MCP3564_CONFIG0_USE_EXT_CLK 0x01
/* External digital clock (default) */
#define MCP3564_CONFIG0_USE_EXT_CLK_DEFAULT 0x00
#define MCP3564_CONFIG0_CLK_SEL_MASK GENMASK(5, 4)
#define MCP3456_CONFIG0_BIT6_DEFAULT BIT(6)
#define MCP3456_CONFIG0_VREF_MASK BIT(7)
#define MCP3564_CONFIG1_REG 0x02
#define MCP3564_CONFIG1_OVERSPL_RATIO_MASK GENMASK(5, 2)
#define MCP3564_CONFIG2_REG 0x03
#define MCP3564_CONFIG2_AZ_REF_MASK BIT(1)
#define MCP3564_CONFIG2_AZ_MUX_MASK BIT(2)
#define MCP3564_CONFIG2_HARDWARE_GAIN_MASK GENMASK(5, 3)
#define MCP3564_DEFAULT_HARDWARE_GAIN 0x01
#define MCP3564_CONFIG2_BOOST_CURRENT_MASK GENMASK(7, 6)
#define MCP3564_CONFIG3_REG 0x04
#define MCP3464_CONFIG3_EN_GAINCAL_MASK BIT(0)
#define MCP3464_CONFIG3_EN_OFFCAL_MASK BIT(1)
#define MCP3464_CONFIG3_EN_CRCCOM_MASK BIT(2)
#define MCP3464_CONFIG3_CRC_FORMAT_MASK BIT(3)
/*
* ADC Output Data Format 32-bit (25-bit right justified data + Channel ID):
* CHID[3:0] + SGN extension (4 bits) + 24-bit ADC data.
* It allows overrange with the SGN extension.
*/
#define MCP3464_CONFIG3_DATA_FMT_32B_WITH_CH_ID 3
/*
* ADC Output Data Format 32-bit (25-bit right justified data):
* SGN extension (8-bit) + 24-bit ADC data.
* It allows overrange with the SGN extension.
*/
#define MCP3464_CONFIG3_DATA_FMT_32B_SGN_EXT 2
/*
* ADC Output Data Format 32-bit (24-bit left justified data):
* 24-bit ADC data + 0x00 (8-bit).
* It does not allow overrange (ADC code locked to 0xFFFFFF or 0x800000).
*/
#define MCP3464_CONFIG3_DATA_FMT_32B_LEFT_JUSTIFIED 1
/*
* ADC Output Data Format 24-bit (default ADC coding):
* 24-bit ADC data.
* It does not allow overrange (ADC code locked to 0xFFFFFF or 0x800000).
*/
#define MCP3464_CONFIG3_DATA_FMT_24B 0
#define MCP3464_CONFIG3_DATA_FORMAT_MASK GENMASK(5, 4)
/* Continuous Conversion mode or continuous conversion cycle in SCAN mode. */
#define MCP3464_CONFIG3_CONV_MODE_CONTINUOUS 3
/*
* One-shot conversion or one-shot cycle in SCAN mode. It sets ADC_MODE[1:0] to ‘10’
* (standby) at the end of the conversion or at the end of the conversion cycle in SCAN mode.
*/
#define MCP3464_CONFIG3_CONV_MODE_ONE_SHOT_STANDBY 2
/*
* One-shot conversion or one-shot cycle in SCAN mode. It sets ADC_MODE[1:0] to ‘0x’ (ADC
* Shutdown) at the end of the conversion or at the end of the conversion cycle in SCAN
* mode (default).
*/
#define MCP3464_CONFIG3_CONV_MODE_ONE_SHOT_SHUTDOWN 0
#define MCP3464_CONFIG3_CONV_MODE_MASK GENMASK(7, 6)
#define MCP3564_IRQ_REG 0x05
#define MCP3464_EN_STP_MASK BIT(0)
#define MCP3464_EN_FASTCMD_MASK BIT(1)
#define MCP3464_IRQ_MODE_0_MASK BIT(2)
#define MCP3464_IRQ_MODE_1_MASK BIT(3)
#define MCP3564_POR_STATUS_MASK BIT(4)
#define MCP3564_CRCCFG_STATUS_MASK BIT(5)
#define MCP3564_DATA_READY_MASK BIT(6)
#define MCP3564_MUX_REG 0x06
#define MCP3564_MUX_VIN_P_MASK GENMASK(7, 4)
#define MCP3564_MUX_VIN_N_MASK GENMASK(3, 0)
#define MCP3564_MUX_SET(x, y) (FIELD_PREP(MCP3564_MUX_VIN_P_MASK, (x)) | \
FIELD_PREP(MCP3564_MUX_VIN_N_MASK, (y)))
#define MCP3564_SCAN_REG 0x07
#define MCP3564_SCAN_CH_SEL_MASK GENMASK(15, 0)
#define MCP3564_SCAN_CH_SEL_SET(x) FIELD_PREP(MCP3564_SCAN_CH_SEL_MASK, (x))
#define MCP3564_SCAN_DELAY_TIME_MASK GENMASK(23, 21)
#define MCP3564_SCAN_DELAY_TIME_SET(x) FIELD_PREP(MCP3564_SCAN_DELAY_TIME_MASK, (x))
#define MCP3564_SCAN_DEFAULT_VALUE 0
#define MCP3564_TIMER_REG 0x08
#define MCP3564_TIMER_DEFAULT_VALUE 0
#define MCP3564_OFFSETCAL_REG 0x09
#define MCP3564_DEFAULT_OFFSETCAL 0
#define MCP3564_GAINCAL_REG 0x0A
#define MCP3564_DEFAULT_GAINCAL 0x00800000
#define MCP3564_RESERVED_B_REG 0x0B
#define MCP3564_RESERVED_C_REG 0x0C
#define MCP3564_C_REG_DEFAULT 0x50
#define MCP3564R_C_REG_DEFAULT 0x30
#define MCP3564_LOCK_REG 0x0D
#define MCP3564_LOCK_WRITE_ACCESS_PASSWORD 0xA5
#define MCP3564_RESERVED_E_REG 0x0E
#define MCP3564_CRCCFG_REG 0x0F
#define MCP3564_CMD_HW_ADDR_MASK GENMASK(7, 6)
#define MCP3564_CMD_ADDR_MASK GENMASK(5, 2)
#define MCP3564_HW_ADDR_MASK GENMASK(1, 0)
#define MCP3564_FASTCMD_START 0x0A
#define MCP3564_FASTCMD_RESET 0x0E
#define MCP3461_HW_ID 0x0008
#define MCP3462_HW_ID 0x0009
#define MCP3464_HW_ID 0x000B
#define MCP3561_HW_ID 0x000C
#define MCP3562_HW_ID 0x000D
#define MCP3564_HW_ID 0x000F
#define MCP3564_HW_ID_MASK GENMASK(3, 0)
#define MCP3564R_INT_VREF_MV 2400
#define MCP3564_DATA_READY_TIMEOUT_MS 2000
#define MCP3564_MAX_PGA 8
#define MCP3564_MAX_BURNOUT_IDX 4
#define MCP3564_MAX_CHANNELS 66
enum mcp3564_ids {
mcp3461,
mcp3462,
mcp3464,
mcp3561,
mcp3562,
mcp3564,
mcp3461r,
mcp3462r,
mcp3464r,
mcp3561r,
mcp3562r,
mcp3564r,
};
enum mcp3564_delay_time {
MCP3564_NO_DELAY,
MCP3564_DELAY_8_DMCLK,
MCP3564_DELAY_16_DMCLK,
MCP3564_DELAY_32_DMCLK,
MCP3564_DELAY_64_DMCLK,
MCP3564_DELAY_128_DMCLK,
MCP3564_DELAY_256_DMCLK,
MCP3564_DELAY_512_DMCLK
};
enum mcp3564_adc_conversion_mode {
MCP3564_ADC_MODE_DEFAULT,
MCP3564_ADC_MODE_SHUTDOWN,
MCP3564_ADC_MODE_STANDBY,
MCP3564_ADC_MODE_CONVERSION
};
enum mcp3564_adc_bias_current {
MCP3564_BOOST_CURRENT_x0_50,
MCP3564_BOOST_CURRENT_x0_66,
MCP3564_BOOST_CURRENT_x1_00,
MCP3564_BOOST_CURRENT_x2_00
};
enum mcp3564_burnout {
MCP3564_CONFIG0_CS_SEL_0_0_uA,
MCP3564_CONFIG0_CS_SEL_0_9_uA,
MCP3564_CONFIG0_CS_SEL_3_7_uA,
MCP3564_CONFIG0_CS_SEL_15_uA
};
enum mcp3564_channel_names {
MCP3564_CH0,
MCP3564_CH1,
MCP3564_CH2,
MCP3564_CH3,
MCP3564_CH4,
MCP3564_CH5,
MCP3564_CH6,
MCP3564_CH7,
MCP3564_AGND,
MCP3564_AVDD,
MCP3564_RESERVED, /* do not use */
MCP3564_REFIN_POZ,
MCP3564_REFIN_NEG,
MCP3564_TEMP_DIODE_P,
MCP3564_TEMP_DIODE_M,
MCP3564_INTERNAL_VCM,
};
enum mcp3564_oversampling {
MCP3564_OVERSAMPLING_RATIO_32,
MCP3564_OVERSAMPLING_RATIO_64,
MCP3564_OVERSAMPLING_RATIO_128,
MCP3564_OVERSAMPLING_RATIO_256,
MCP3564_OVERSAMPLING_RATIO_512,
MCP3564_OVERSAMPLING_RATIO_1024,
MCP3564_OVERSAMPLING_RATIO_2048,
MCP3564_OVERSAMPLING_RATIO_4096,
MCP3564_OVERSAMPLING_RATIO_8192,
MCP3564_OVERSAMPLING_RATIO_16384,
MCP3564_OVERSAMPLING_RATIO_20480,
MCP3564_OVERSAMPLING_RATIO_
|