Lines Matching +full:adc +full:- +full:channels
1 // SPDX-License-Identifier: GPL-2.0+
3 * IIO driver for MCP356X/MCP356XR and MCP346X/MCP346XR series ADC chip family
5 * Copyright (C) 2022-2023 Microchip Technology Inc. and its subsidiaries
10 …s/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/MCP3561-2-4-Family-Data-Sheet-DS20006181…
12 …ds/aemDocuments/documents/APID/ProductDocuments/DataSheets/MCP3561_2_4R-Data-Sheet-DS200006391C.pdf
14 …ProductDocuments/DataSheets/MCP3461-2-4-Two-Four-Eight-Channel-153.6-ksps-Low-Noise-16-Bit-Delta-S…
16 …/aemDocuments/documents/APID/ProductDocuments/DataSheets/MCP3461-2-4R-Family-Data-Sheet-DS20006404…
64 * ADC Output Data Format 32-bit (25-bit right justified data + Channel ID):
65 * CHID[3:0] + SGN extension (4 bits) + 24-bit ADC data.
70 * ADC Output Data Format 32-bit (25-bit right justified data):
71 * SGN extension (8-bit) + 24-bit ADC data.
76 * ADC Output Data Format 32-bit (24-bit left justified data):
77 * 24-bit ADC data + 0x00 (8-bit).
78 * It does not allow overrange (ADC code locked to 0xFFFFFF or 0x800000).
82 * ADC Output Data Format 24-bit (default ADC coding):
83 * 24-bit ADC data.
84 * It does not allow overrange (ADC code locked to 0xFFFFFF or 0x800000).
92 * One-shot conversion or one-shot cycle in SCAN mode. It sets ADC_MODE[1:0] to ‘10’
97 * One-shot conversion or one-shot cycle in SCAN mode. It sets ADC_MODE[1:0] to ‘0x’ (ADC
276 * Current Source/Sink Selection Bits for Sensor Bias (source on VIN+/sink on VIN-)
286 * BOOST[1:0]: ADC Bias Current Selection
299 -8388608, /* min: -2^23 */
301 8388607 /* max: 2^23 - 1 */
307 * unsigned 24-bit register that holds the digital gain error
310 * The gain error calibration value range in equivalent voltage is [0; 2-2^(-23)]
315 16777215 /* max: 2 - 2^(-23) */
335 * struct mcp3564_chip_info - chip specific data
337 * @num_channels: number of channels
338 * @resolution: ADC resolution
349 * struct mcp3564_state - working data for a ADC device
355 * @oversampling: the index inside oversampling list of the ADC
356 * @hwgain: the index inside hardware gain list of the ADC
360 * @current_boost_mode: the index inside current boost list of the ADC
361 * @burnout_mode: the index inside current bias list of the ADC
362 * @auto_zeroing_mux: set if ADC auto-zeroing algorithm is enabled
363 * @auto_zeroing_ref: set if ADC auto-Zeroing Reference Buffer Setting is enabled
364 * @have_vref: does the ADC have an internal voltage reference?
365 * @labels: table with channels labels
400 static int mcp3564_read_8bits(struct mcp3564_state *adc, u8 reg, u8 *val) in mcp3564_read_8bits() argument
406 tx_buf = mcp3564_cmd_read(adc->dev_addr, reg); in mcp3564_read_8bits()
408 ret = spi_write_then_read(adc->spi, &tx_buf, sizeof(tx_buf), in mcp3564_read_8bits()
415 static int mcp3564_read_16bits(struct mcp3564_state *adc, u8 reg, u16 *val) in mcp3564_read_16bits() argument
421 tx_buf = mcp3564_cmd_read(adc->dev_addr, reg); in mcp3564_read_16bits()
423 ret = spi_write_then_read(adc->spi, &tx_buf, sizeof(tx_buf), in mcp3564_read_16bits()
430 static int mcp3564_read_32bits(struct mcp3564_state *adc, u8 reg, u32 *val) in mcp3564_read_32bits() argument
436 tx_buf = mcp3564_cmd_read(adc->dev_addr, reg); in mcp3564_read_32bits()
438 ret = spi_write_then_read(adc->spi, &tx_buf, sizeof(tx_buf), in mcp3564_read_32bits()
445 static int mcp3564_write_8bits(struct mcp3564_state *adc, u8 reg, u8 val) in mcp3564_write_8bits() argument
449 tx_buf[0] = mcp3564_cmd_write(adc->dev_addr, reg); in mcp3564_write_8bits()
452 return spi_write_then_read(adc->spi, tx_buf, sizeof(tx_buf), NULL, 0); in mcp3564_write_8bits()
455 static int mcp3564_write_24bits(struct mcp3564_state *adc, u8 reg, u32 val) in mcp3564_write_24bits() argument
459 val |= (mcp3564_cmd_write(adc->dev_addr, reg) << 24); in mcp3564_write_24bits()
462 return spi_write_then_read(adc->spi, &val_be, sizeof(val_be), NULL, 0); in mcp3564_write_24bits()
465 static int mcp3564_fast_cmd(struct mcp3564_state *adc, u8 fast_cmd) in mcp3564_fast_cmd() argument
469 val = FIELD_PREP(MCP3564_CMD_HW_ADDR_MASK, adc->dev_addr) | in mcp3564_fast_cmd()
472 return spi_write_then_read(adc->spi, &val, 1, NULL, 0); in mcp3564_fast_cmd()
475 static int mcp3564_update_8bits(struct mcp3564_state *adc, u8 reg, u32 mask, u8 val) in mcp3564_update_8bits() argument
482 ret = mcp3564_read_8bits(adc, reg, &tmp); in mcp3564_update_8bits()
489 return mcp3564_write_8bits(adc, reg, tmp); in mcp3564_update_8bits()
496 struct mcp3564_state *adc = iio_priv(indio_dev); in mcp3564_set_current_boost_mode() local
499 dev_dbg(&indio_dev->dev, "%s: %d\n", __func__, mode); in mcp3564_set_current_boost_mode()
501 mutex_lock(&adc->lock); in mcp3564_set_current_boost_mode()
502 ret = mcp3564_update_8bits(adc, MCP3564_CONFIG2_REG, MCP3564_CONFIG2_BOOST_CURRENT_MASK, in mcp3564_set_current_boost_mode()
506 dev_err(&indio_dev->dev, "Failed to configure CONFIG2 register\n"); in mcp3564_set_current_boost_mode()
508 adc->current_boost_mode = mode; in mcp3564_set_current_boost_mode()
510 mutex_unlock(&adc->lock); in mcp3564_set_current_boost_mode()
518 struct mcp3564_state *adc = iio_priv(indio_dev); in mcp3564_get_current_boost_mode() local
520 return adc->current_boost_mode; in mcp3564_get_current_boost_mode()
546 struct mcp3564_state *adc = iio_priv(indio_dev); in mcp3564_auto_zeroing_mux_show() local
548 return sysfs_emit(buf, "%d\n", adc->auto_zeroing_mux); in mcp3564_auto_zeroing_mux_show()
556 struct mcp3564_state *adc = iio_priv(indio_dev); in mcp3564_auto_zeroing_mux_store() local
564 mutex_lock(&adc->lock); in mcp3564_auto_zeroing_mux_store()
565 ret = mcp3564_update_8bits(adc, MCP3564_CONFIG2_REG, MCP3564_CONFIG2_AZ_MUX_MASK, in mcp3564_auto_zeroing_mux_store()
569 dev_err(&indio_dev->dev, "Failed to update CONFIG2 register\n"); in mcp3564_auto_zeroing_mux_store()
571 adc->auto_zeroing_mux = auto_zero; in mcp3564_auto_zeroing_mux_store()
573 mutex_unlock(&adc->lock); in mcp3564_auto_zeroing_mux_store()
583 struct mcp3564_state *adc = iio_priv(indio_dev); in mcp3564_auto_zeroing_ref_show() local
585 return sysfs_emit(buf, "%d\n", adc->auto_zeroing_ref); in mcp3564_auto_zeroing_ref_show()
593 struct mcp3564_state *adc = iio_priv(indio_dev); in mcp3564_auto_zeroing_ref_store() local
601 mutex_lock(&adc->lock); in mcp3564_auto_zeroing_ref_store()
602 ret = mcp3564_update_8bits(adc, MCP3564_CONFIG2_REG, MCP3564_CONFIG2_AZ_REF_MASK, in mcp3564_auto_zeroing_ref_store()
606 dev_err(&indio_dev->dev, "Failed to update CONFIG2 register\n"); in mcp3564_auto_zeroing_ref_store()
608 adc->auto_zeroing_ref = auto_zero; in mcp3564_auto_zeroing_ref_store()
610 mutex_unlock(&adc->lock); in mcp3564_auto_zeroing_ref_store()
655 * Number of channels could be calculated:
657 * Eg. for MCP3561 (only 2 channels available: CH0 and CH1)
658 * single_ended_input = (CH0 - GND), (CH1 - GND) = 2
659 * differential_input = (CH0 - CH1), (CH0 - CH0) = 2
662 * num_channels = P^R(Number_of_single_ended_channels, 2) + 2 (temperature + burnout channels)
745 struct mcp3564_state *adc = iio_priv(indio_dev); in mcp3564_read_single_value() local
750 ret = mcp3564_write_8bits(adc, MCP3564_MUX_REG, channel->address); in mcp3564_read_single_value()
754 /* Start ADC Conversion using fast command (overwrites ADC_MODE[1:0] = 11) */ in mcp3564_read_single_value()
755 ret = mcp3564_fast_cmd(adc, MCP3564_FASTCMD_START); in mcp3564_read_single_value()
766 adc, MCP3564_IRQ_REG, &tmp); in mcp3564_read_single_value()
777 return -EBUSY; in mcp3564_read_single_value()
779 return mcp3564_read_32bits(adc, MCP3564_ADCDATA_REG, val); in mcp3564_read_single_value()
787 struct mcp3564_state *adc = iio_priv(indio_dev); in mcp3564_read_avail() local
791 if (!channel->output) in mcp3564_read_avail()
792 return -EINVAL; in mcp3564_read_avail()
804 *vals = (int *)adc->scale_tbls; in mcp3564_read_avail()
805 *length = ARRAY_SIZE(adc->scale_tbls) * 2; in mcp3564_read_avail()
817 return -EINVAL; in mcp3564_read_avail()
825 struct mcp3564_state *adc = iio_priv(indio_dev); in mcp3564_read_raw() local
830 if (channel->output) { in mcp3564_read_raw()
831 mutex_lock(&adc->lock); in mcp3564_read_raw()
832 *val = mcp3564_burnout_avail[adc->burnout_mode][0]; in mcp3564_read_raw()
833 *val2 = mcp3564_burnout_avail[adc->burnout_mode][1]; in mcp3564_read_raw()
834 mutex_unlock(&adc->lock); in mcp3564_read_raw()
840 return -EINVAL; in mcp3564_read_raw()
843 mutex_lock(&adc->lock); in mcp3564_read_raw()
844 *val = adc->scale_tbls[adc->hwgain][0]; in mcp3564_read_raw()
845 *val2 = adc->scale_tbls[adc->hwgain][1]; in mcp3564_read_raw()
846 mutex_unlock(&adc->lock); in mcp3564_read_raw()
849 *val = mcp3564_oversampling_avail[adc->oversampling]; in mcp3564_read_raw()
852 *val = adc->calib_bias; in mcp3564_read_raw()
855 *val = adc->calib_scale; in mcp3564_read_raw()
858 return -EINVAL; in mcp3564_read_raw()
876 return -EINVAL; in mcp3564_write_raw_get_fmt()
884 struct mcp3564_state *adc = iio_priv(indio_dev); in mcp3564_write_raw() local
892 if (!channel->output) in mcp3564_write_raw()
893 return -EINVAL; in mcp3564_write_raw()
901 return -EINVAL; in mcp3564_write_raw()
903 if (burnout == adc->burnout_mode) in mcp3564_write_raw()
906 mutex_lock(&adc->lock); in mcp3564_write_raw()
907 ret = mcp3564_update_8bits(adc, MCP3564_CONFIG0_REG, in mcp3564_write_raw()
912 dev_err(&indio_dev->dev, "Failed to configure burnout current\n"); in mcp3564_write_raw()
914 adc->burnout_mode = burnout; in mcp3564_write_raw()
915 mutex_unlock(&adc->lock); in mcp3564_write_raw()
919 return -EINVAL; in mcp3564_write_raw()
921 mutex_lock(&adc->lock); in mcp3564_write_raw()
922 ret = mcp3564_write_24bits(adc, MCP3564_OFFSETCAL_REG, val); in mcp3564_write_raw()
924 adc->calib_bias = val; in mcp3564_write_raw()
925 mutex_unlock(&adc->lock); in mcp3564_write_raw()
929 return -EINVAL; in mcp3564_write_raw()
931 if (adc->calib_scale == val) in mcp3564_write_raw()
934 mutex_lock(&adc->lock); in mcp3564_write_raw()
935 ret = mcp3564_write_24bits(adc, MCP3564_GAINCAL_REG, val); in mcp3564_write_raw()
937 adc->calib_scale = val; in mcp3564_write_raw()
938 mutex_unlock(&adc->lock); in mcp3564_write_raw()
942 return -EINVAL; in mcp3564_write_raw()
947 if (adc->oversampling == tmp) in mcp3564_write_raw()
950 mutex_lock(&adc->lock); in mcp3564_write_raw()
951 ret = mcp3564_update_8bits(adc, MCP3564_CONFIG1_REG, in mcp3564_write_raw()
954 adc->oversampling)); in mcp3564_write_raw()
956 adc->oversampling = tmp; in mcp3564_write_raw()
957 mutex_unlock(&adc->lock); in mcp3564_write_raw()
961 if (val == adc->scale_tbls[hwgain][0] && in mcp3564_write_raw()
962 val2 == adc->scale_tbls[hwgain][1]) in mcp3564_write_raw()
966 return -EINVAL; in mcp3564_write_raw()
968 if (hwgain == adc->hwgain) in mcp3564_write_raw()
971 mutex_lock(&adc->lock); in mcp3564_write_raw()
972 ret = mcp3564_update_8bits(adc, MCP3564_CONFIG2_REG, in mcp3564_write_raw()
976 adc->hwgain = hwgain; in mcp3564_write_raw()
978 mutex_unlock(&adc->lock); in mcp3564_write_raw()
981 return -EINVAL; in mcp3564_write_raw()
988 struct mcp3564_state *adc = iio_priv(indio_dev); in mcp3564_read_label() local
990 return sprintf(label, "%s\n", adc->labels[chan->scan_index]); in mcp3564_read_label()
995 struct mcp3564_state *adc = iio_priv(indio_dev); in mcp3564_parse_fw_children() local
996 struct device *dev = &adc->spi->dev; in mcp3564_parse_fw_children()
997 struct iio_chan_spec *channels; in mcp3564_parse_fw_children() local
1010 return dev_err_probe(&indio_dev->dev, -ENODEV, in mcp3564_parse_fw_children()
1011 "FW has no channels defined\n"); in mcp3564_parse_fw_children()
1016 if (num_ch > adc->chip_info->num_channels) in mcp3564_parse_fw_children()
1017 return dev_err_probe(dev, -EINVAL, "Too many channels %d > %d\n", in mcp3564_parse_fw_children()
1018 num_ch, adc->chip_info->num_channels); in mcp3564_parse_fw_children()
1020 channels = devm_kcalloc(dev, num_ch, sizeof(*channels), GFP_KERNEL); in mcp3564_parse_fw_children()
1021 if (!channels) in mcp3564_parse_fw_children()
1022 return dev_err_probe(dev, -ENOMEM, "Can't allocate memory\n"); in mcp3564_parse_fw_children()
1027 if (fwnode_property_present(child, "diff-channels")) { in mcp3564_parse_fw_children()
1029 "diff-channels", in mcp3564_parse_fw_children()
1047 return dev_err_probe(&indio_dev->dev, -EINVAL, in mcp3564_parse_fw_children()
1059 adc->labels[chan_idx] = label; in mcp3564_parse_fw_children()
1062 channels[chan_idx] = chanspec; in mcp3564_parse_fw_children()
1068 channels[chan_idx] = burnout_chanspec; in mcp3564_parse_fw_children()
1069 adc->labels[chan_idx] = mcp3564_channel_labels[0]; in mcp3564_parse_fw_children()
1075 channels[chan_idx] = temp_chanspec; in mcp3564_parse_fw_children()
1076 adc->labels[chan_idx] = mcp3564_channel_labels[1]; in mcp3564_parse_fw_children()
1079 indio_dev->num_channels = chan_idx; in mcp3564_parse_fw_children()
1080 indio_dev->channels = channels; in mcp3564_parse_fw_children()
1085 static void mcp3564_fill_scale_tbls(struct mcp3564_state *adc) in mcp3564_fill_scale_tbls() argument
1087 unsigned int pow = adc->chip_info->resolution - 1; in mcp3564_fill_scale_tbls()
1094 ref = adc->vref_mv; in mcp3564_fill_scale_tbls()
1101 adc->scale_tbls[i][1] = tmp0; in mcp3564_fill_scale_tbls()
1107 struct mcp3564_state *adc = iio_priv(indio_dev); in mcp3564_config() local
1108 struct device *dev = &adc->spi->dev; in mcp3564_config()
1118 * The address is set on a per-device basis by fuses in the factory, in mcp3564_config()
1125 device_property_read_u32(dev, "microchip,hw-device-address", &tmp); in mcp3564_config()
1129 "invalid device address. Must be in range 0-3.\n"); in mcp3564_config()
1130 return -EINVAL; in mcp3564_config()
1133 adc->dev_addr = FIELD_GET(MCP3564_HW_ADDR_MASK, tmp); in mcp3564_config()
1135 dev_dbg(dev, "use HW device address %i\n", adc->dev_addr); in mcp3564_config()
1137 ret = mcp3564_read_8bits(adc, MCP3564_RESERVED_C_REG, &tmp_reg); in mcp3564_config()
1143 adc->have_vref = false; in mcp3564_config()
1146 adc->have_vref = true; in mcp3564_config()
1154 ret = mcp3564_read_16bits(adc, MCP3564_RESERVED_E_REG, &tmp_u16); in mcp3564_config()
1160 if (adc->have_vref) in mcp3564_config()
1166 if (adc->have_vref) in mcp3564_config()
1172 if (adc->have_vref) in mcp3564_config()
1178 if (adc->have_vref) in mcp3564_config()
1184 if (adc->have_vref) in mcp3564_config()
1190 if (adc->have_vref) in mcp3564_config()
1206 adc->chip_info = spi_get_device_match_data(adc->spi); in mcp3564_config()
1207 adc->have_vref = adc->chip_info->have_vref; in mcp3564_config()
1209 adc->chip_info = &mcp3564_chip_infos_tbl[ids]; in mcp3564_config()
1212 dev_dbg(dev, "Found %s chip\n", adc->chip_info->name); in mcp3564_config()
1215 if (ret < 0 && ret != -ENODEV) in mcp3564_config()
1218 internal_vref = ret == -ENODEV; in mcp3564_config()
1219 adc->vref_mv = internal_vref ? MCP3564R_INT_VREF_MV : ret / MILLI; in mcp3564_config()
1224 if (!adc->have_vref) in mcp3564_config()
1225 return dev_err_probe(dev, -ENODEV, "Unknown Vref\n"); in mcp3564_config()
1238 * in any cases of loss-of-power scenario (Full Chip Reset): in mcp3564_config()
1239 * - Write LOCK register to 0xA5 in mcp3564_config()
1240 * - Write IRQ register to 0x03 in mcp3564_config()
1241 * - Send "Device Full Reset" fast command in mcp3564_config()
1242 * - Wait 1ms for "Full Reset" to complete in mcp3564_config()
1244 ret = mcp3564_write_8bits(adc, MCP3564_LOCK_REG, MCP3564_LOCK_WRITE_ACCESS_PASSWORD); in mcp3564_config()
1248 ret = mcp3564_write_8bits(adc, MCP3564_IRQ_REG, 0x03); in mcp3564_config()
1252 ret = mcp3564_fast_cmd(adc, MCP3564_FASTCMD_RESET); in mcp3564_config()
1265 ret = mcp3564_write_24bits(adc, MCP3564_GAINCAL_REG, MCP3564_DEFAULT_GAINCAL); in mcp3564_config()
1269 adc->calib_scale = MCP3564_DEFAULT_GAINCAL; in mcp3564_config()
1271 ret = mcp3564_write_24bits(adc, MCP3564_OFFSETCAL_REG, MCP3564_DEFAULT_OFFSETCAL); in mcp3564_config()
1275 ret = mcp3564_write_24bits(adc, MCP3564_TIMER_REG, MCP3564_TIMER_DEFAULT_VALUE); in mcp3564_config()
1279 ret = mcp3564_write_24bits(adc, MCP3564_SCAN_REG, in mcp3564_config()
1285 ret = mcp3564_write_8bits(adc, MCP3564_MUX_REG, MCP3564_MUX_SET(MCP3564_CH0, MCP3564_CH1)); in mcp3564_config()
1289 ret = mcp3564_write_8bits(adc, MCP3564_IRQ_REG, in mcp3564_config()
1302 ret = mcp3564_write_8bits(adc, MCP3564_CONFIG3_REG, tmp_reg); in mcp3564_config()
1310 ret = mcp3564_write_8bits(adc, MCP3564_CONFIG2_REG, tmp_reg); in mcp3564_config()
1314 adc->hwgain = 0x01; in mcp3564_config()
1315 adc->auto_zeroing_mux = true; in mcp3564_config()
1316 adc->auto_zeroing_ref = false; in mcp3564_config()
1317 adc->current_boost_mode = MCP3564_BOOST_CURRENT_x1_00; in mcp3564_config()
1321 ret = mcp3564_write_8bits(adc, MCP3564_CONFIG1_REG, tmp_reg); in mcp3564_config()
1325 adc->oversampling = MCP3564_OVERSAMPLING_RATIO_98304; in mcp3564_config()
1335 ret = mcp3564_write_8bits(adc, MCP3564_CONFIG0_REG, tmp_reg); in mcp3564_config()
1337 adc->burnout_mode = MCP3564_CONFIG0_CS_SEL_0_0_uA; in mcp3564_config()
1391 struct mcp3564_state *adc; in mcp3564_probe() local
1394 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc)); in mcp3564_probe()
1396 return -ENOMEM; in mcp3564_probe()
1398 adc = iio_priv(indio_dev); in mcp3564_probe()
1399 adc->spi = spi; in mcp3564_probe()
1401 dev_dbg(&spi->dev, "%s: probe(spi = 0x%p)\n", __func__, spi); in mcp3564_probe()
1406 * enable/disable certain channels in mcp3564_probe()
1411 return dev_err_probe(&spi->dev, ret, in mcp3564_probe()
1414 dev_dbg(&spi->dev, "%s: Vref (mV): %d\n", __func__, adc->vref_mv); in mcp3564_probe()
1416 mcp3564_fill_scale_tbls(adc); in mcp3564_probe()
1418 indio_dev->name = adc->chip_info->name; in mcp3564_probe()
1419 indio_dev->modes = INDIO_DIRECT_MODE; in mcp3564_probe()
1422 indio_dev->info = &mcp3564r_info; in mcp3564_probe()
1424 indio_dev->info = &mcp3564_info; in mcp3564_probe()
1426 mutex_init(&adc->lock); in mcp3564_probe()
1428 ret = devm_iio_device_register(&spi->dev, indio_dev); in mcp3564_probe()
1430 return dev_err_probe(&spi->dev, ret, in mcp3564_probe()