162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Analog Devices AD3552R 462306a36Sopenharmony_ci * Digital to Analog converter driver 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright 2021 Analog Devices Inc. 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci#include <asm/unaligned.h> 962306a36Sopenharmony_ci#include <linux/device.h> 1062306a36Sopenharmony_ci#include <linux/iio/triggered_buffer.h> 1162306a36Sopenharmony_ci#include <linux/iio/trigger_consumer.h> 1262306a36Sopenharmony_ci#include <linux/iopoll.h> 1362306a36Sopenharmony_ci#include <linux/kernel.h> 1462306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 1562306a36Sopenharmony_ci#include <linux/spi/spi.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/* Register addresses */ 1862306a36Sopenharmony_ci/* Primary address space */ 1962306a36Sopenharmony_ci#define AD3552R_REG_ADDR_INTERFACE_CONFIG_A 0x00 2062306a36Sopenharmony_ci#define AD3552R_MASK_SOFTWARE_RESET (BIT(7) | BIT(0)) 2162306a36Sopenharmony_ci#define AD3552R_MASK_ADDR_ASCENSION BIT(5) 2262306a36Sopenharmony_ci#define AD3552R_MASK_SDO_ACTIVE BIT(4) 2362306a36Sopenharmony_ci#define AD3552R_REG_ADDR_INTERFACE_CONFIG_B 0x01 2462306a36Sopenharmony_ci#define AD3552R_MASK_SINGLE_INST BIT(7) 2562306a36Sopenharmony_ci#define AD3552R_MASK_SHORT_INSTRUCTION BIT(3) 2662306a36Sopenharmony_ci#define AD3552R_REG_ADDR_DEVICE_CONFIG 0x02 2762306a36Sopenharmony_ci#define AD3552R_MASK_DEVICE_STATUS(n) BIT(4 + (n)) 2862306a36Sopenharmony_ci#define AD3552R_MASK_CUSTOM_MODES GENMASK(3, 2) 2962306a36Sopenharmony_ci#define AD3552R_MASK_OPERATING_MODES GENMASK(1, 0) 3062306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CHIP_TYPE 0x03 3162306a36Sopenharmony_ci#define AD3552R_MASK_CLASS GENMASK(7, 0) 3262306a36Sopenharmony_ci#define AD3552R_REG_ADDR_PRODUCT_ID_L 0x04 3362306a36Sopenharmony_ci#define AD3552R_REG_ADDR_PRODUCT_ID_H 0x05 3462306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CHIP_GRADE 0x06 3562306a36Sopenharmony_ci#define AD3552R_MASK_GRADE GENMASK(7, 4) 3662306a36Sopenharmony_ci#define AD3552R_MASK_DEVICE_REVISION GENMASK(3, 0) 3762306a36Sopenharmony_ci#define AD3552R_REG_ADDR_SCRATCH_PAD 0x0A 3862306a36Sopenharmony_ci#define AD3552R_REG_ADDR_SPI_REVISION 0x0B 3962306a36Sopenharmony_ci#define AD3552R_REG_ADDR_VENDOR_L 0x0C 4062306a36Sopenharmony_ci#define AD3552R_REG_ADDR_VENDOR_H 0x0D 4162306a36Sopenharmony_ci#define AD3552R_REG_ADDR_STREAM_MODE 0x0E 4262306a36Sopenharmony_ci#define AD3552R_MASK_LENGTH GENMASK(7, 0) 4362306a36Sopenharmony_ci#define AD3552R_REG_ADDR_TRANSFER_REGISTER 0x0F 4462306a36Sopenharmony_ci#define AD3552R_MASK_MULTI_IO_MODE GENMASK(7, 6) 4562306a36Sopenharmony_ci#define AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE BIT(2) 4662306a36Sopenharmony_ci#define AD3552R_REG_ADDR_INTERFACE_CONFIG_C 0x10 4762306a36Sopenharmony_ci#define AD3552R_MASK_CRC_ENABLE (GENMASK(7, 6) |\ 4862306a36Sopenharmony_ci GENMASK(1, 0)) 4962306a36Sopenharmony_ci#define AD3552R_MASK_STRICT_REGISTER_ACCESS BIT(5) 5062306a36Sopenharmony_ci#define AD3552R_REG_ADDR_INTERFACE_STATUS_A 0x11 5162306a36Sopenharmony_ci#define AD3552R_MASK_INTERFACE_NOT_READY BIT(7) 5262306a36Sopenharmony_ci#define AD3552R_MASK_CLOCK_COUNTING_ERROR BIT(5) 5362306a36Sopenharmony_ci#define AD3552R_MASK_INVALID_OR_NO_CRC BIT(3) 5462306a36Sopenharmony_ci#define AD3552R_MASK_WRITE_TO_READ_ONLY_REGISTER BIT(2) 5562306a36Sopenharmony_ci#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS BIT(1) 5662306a36Sopenharmony_ci#define AD3552R_MASK_REGISTER_ADDRESS_INVALID BIT(0) 5762306a36Sopenharmony_ci#define AD3552R_REG_ADDR_INTERFACE_CONFIG_D 0x14 5862306a36Sopenharmony_ci#define AD3552R_MASK_ALERT_ENABLE_PULLUP BIT(6) 5962306a36Sopenharmony_ci#define AD3552R_MASK_MEM_CRC_EN BIT(4) 6062306a36Sopenharmony_ci#define AD3552R_MASK_SDO_DRIVE_STRENGTH GENMASK(3, 2) 6162306a36Sopenharmony_ci#define AD3552R_MASK_DUAL_SPI_SYNCHROUNOUS_EN BIT(1) 6262306a36Sopenharmony_ci#define AD3552R_MASK_SPI_CONFIG_DDR BIT(0) 6362306a36Sopenharmony_ci#define AD3552R_REG_ADDR_SH_REFERENCE_CONFIG 0x15 6462306a36Sopenharmony_ci#define AD3552R_MASK_IDUMP_FAST_MODE BIT(6) 6562306a36Sopenharmony_ci#define AD3552R_MASK_SAMPLE_HOLD_DIFFERENTIAL_USER_EN BIT(5) 6662306a36Sopenharmony_ci#define AD3552R_MASK_SAMPLE_HOLD_USER_TRIM GENMASK(4, 3) 6762306a36Sopenharmony_ci#define AD3552R_MASK_SAMPLE_HOLD_USER_ENABLE BIT(2) 6862306a36Sopenharmony_ci#define AD3552R_MASK_REFERENCE_VOLTAGE_SEL GENMASK(1, 0) 6962306a36Sopenharmony_ci#define AD3552R_REG_ADDR_ERR_ALARM_MASK 0x16 7062306a36Sopenharmony_ci#define AD3552R_MASK_REF_RANGE_ALARM BIT(6) 7162306a36Sopenharmony_ci#define AD3552R_MASK_CLOCK_COUNT_ERR_ALARM BIT(5) 7262306a36Sopenharmony_ci#define AD3552R_MASK_MEM_CRC_ERR_ALARM BIT(4) 7362306a36Sopenharmony_ci#define AD3552R_MASK_SPI_CRC_ERR_ALARM BIT(3) 7462306a36Sopenharmony_ci#define AD3552R_MASK_WRITE_TO_READ_ONLY_ALARM BIT(2) 7562306a36Sopenharmony_ci#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS_ALARM BIT(1) 7662306a36Sopenharmony_ci#define AD3552R_MASK_REGISTER_ADDRESS_INVALID_ALARM BIT(0) 7762306a36Sopenharmony_ci#define AD3552R_REG_ADDR_ERR_STATUS 0x17 7862306a36Sopenharmony_ci#define AD3552R_MASK_REF_RANGE_ERR_STATUS BIT(6) 7962306a36Sopenharmony_ci#define AD3552R_MASK_DUAL_SPI_STREAM_EXCEEDS_DAC_ERR_STATUS BIT(5) 8062306a36Sopenharmony_ci#define AD3552R_MASK_MEM_CRC_ERR_STATUS BIT(4) 8162306a36Sopenharmony_ci#define AD3552R_MASK_RESET_STATUS BIT(0) 8262306a36Sopenharmony_ci#define AD3552R_REG_ADDR_POWERDOWN_CONFIG 0x18 8362306a36Sopenharmony_ci#define AD3552R_MASK_CH_DAC_POWERDOWN(ch) BIT(4 + (ch)) 8462306a36Sopenharmony_ci#define AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(ch) BIT(ch) 8562306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE 0x19 8662306a36Sopenharmony_ci#define AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch) ((ch) ? GENMASK(7, 4) :\ 8762306a36Sopenharmony_ci GENMASK(3, 0)) 8862306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CH_OFFSET(ch) (0x1B + (ch) * 2) 8962306a36Sopenharmony_ci#define AD3552R_MASK_CH_OFFSET_BITS_0_7 GENMASK(7, 0) 9062306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CH_GAIN(ch) (0x1C + (ch) * 2) 9162306a36Sopenharmony_ci#define AD3552R_MASK_CH_RANGE_OVERRIDE BIT(7) 9262306a36Sopenharmony_ci#define AD3552R_MASK_CH_GAIN_SCALING_N GENMASK(6, 5) 9362306a36Sopenharmony_ci#define AD3552R_MASK_CH_GAIN_SCALING_P GENMASK(4, 3) 9462306a36Sopenharmony_ci#define AD3552R_MASK_CH_OFFSET_POLARITY BIT(2) 9562306a36Sopenharmony_ci#define AD3552R_MASK_CH_OFFSET_BIT_8 BIT(0) 9662306a36Sopenharmony_ci/* 9762306a36Sopenharmony_ci * Secondary region 9862306a36Sopenharmony_ci * For multibyte registers specify the highest address because the access is 9962306a36Sopenharmony_ci * done in descending order 10062306a36Sopenharmony_ci */ 10162306a36Sopenharmony_ci#define AD3552R_SECONDARY_REGION_START 0x28 10262306a36Sopenharmony_ci#define AD3552R_REG_ADDR_HW_LDAC_16B 0x28 10362306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CH_DAC_16B(ch) (0x2C - (1 - ch) * 2) 10462306a36Sopenharmony_ci#define AD3552R_REG_ADDR_DAC_PAGE_MASK_16B 0x2E 10562306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CH_SELECT_16B 0x2F 10662306a36Sopenharmony_ci#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_16B 0x31 10762306a36Sopenharmony_ci#define AD3552R_REG_ADDR_SW_LDAC_16B 0x32 10862306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CH_INPUT_16B(ch) (0x36 - (1 - ch) * 2) 10962306a36Sopenharmony_ci/* 3 bytes registers */ 11062306a36Sopenharmony_ci#define AD3552R_REG_START_24B 0x37 11162306a36Sopenharmony_ci#define AD3552R_REG_ADDR_HW_LDAC_24B 0x37 11262306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CH_DAC_24B(ch) (0x3D - (1 - ch) * 3) 11362306a36Sopenharmony_ci#define AD3552R_REG_ADDR_DAC_PAGE_MASK_24B 0x40 11462306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CH_SELECT_24B 0x41 11562306a36Sopenharmony_ci#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_24B 0x44 11662306a36Sopenharmony_ci#define AD3552R_REG_ADDR_SW_LDAC_24B 0x45 11762306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CH_INPUT_24B(ch) (0x4B - (1 - ch) * 3) 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci/* Useful defines */ 12062306a36Sopenharmony_ci#define AD3552R_NUM_CH 2 12162306a36Sopenharmony_ci#define AD3552R_MASK_CH(ch) BIT(ch) 12262306a36Sopenharmony_ci#define AD3552R_MASK_ALL_CH GENMASK(1, 0) 12362306a36Sopenharmony_ci#define AD3552R_MAX_REG_SIZE 3 12462306a36Sopenharmony_ci#define AD3552R_READ_BIT BIT(7) 12562306a36Sopenharmony_ci#define AD3552R_ADDR_MASK GENMASK(6, 0) 12662306a36Sopenharmony_ci#define AD3552R_MASK_DAC_12B 0xFFF0 12762306a36Sopenharmony_ci#define AD3552R_DEFAULT_CONFIG_B_VALUE 0x8 12862306a36Sopenharmony_ci#define AD3552R_SCRATCH_PAD_TEST_VAL1 0x34 12962306a36Sopenharmony_ci#define AD3552R_SCRATCH_PAD_TEST_VAL2 0xB2 13062306a36Sopenharmony_ci#define AD3552R_GAIN_SCALE 1000 13162306a36Sopenharmony_ci#define AD3552R_LDAC_PULSE_US 100 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cienum ad3552r_ch_vref_select { 13462306a36Sopenharmony_ci /* Internal source with Vref I/O floating */ 13562306a36Sopenharmony_ci AD3552R_INTERNAL_VREF_PIN_FLOATING, 13662306a36Sopenharmony_ci /* Internal source with Vref I/O at 2.5V */ 13762306a36Sopenharmony_ci AD3552R_INTERNAL_VREF_PIN_2P5V, 13862306a36Sopenharmony_ci /* External source with Vref I/O as input */ 13962306a36Sopenharmony_ci AD3552R_EXTERNAL_VREF_PIN_INPUT 14062306a36Sopenharmony_ci}; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cienum ad3542r_id { 14362306a36Sopenharmony_ci AD3542R_ID = 0x4009, 14462306a36Sopenharmony_ci AD3552R_ID = 0x4008, 14562306a36Sopenharmony_ci}; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cienum ad3552r_ch_output_range { 14862306a36Sopenharmony_ci /* Range from 0 V to 2.5 V. Requires Rfb1x connection */ 14962306a36Sopenharmony_ci AD3552R_CH_OUTPUT_RANGE_0__2P5V, 15062306a36Sopenharmony_ci /* Range from 0 V to 5 V. Requires Rfb1x connection */ 15162306a36Sopenharmony_ci AD3552R_CH_OUTPUT_RANGE_0__5V, 15262306a36Sopenharmony_ci /* Range from 0 V to 10 V. Requires Rfb2x connection */ 15362306a36Sopenharmony_ci AD3552R_CH_OUTPUT_RANGE_0__10V, 15462306a36Sopenharmony_ci /* Range from -5 V to 5 V. Requires Rfb2x connection */ 15562306a36Sopenharmony_ci AD3552R_CH_OUTPUT_RANGE_NEG_5__5V, 15662306a36Sopenharmony_ci /* Range from -10 V to 10 V. Requires Rfb4x connection */ 15762306a36Sopenharmony_ci AD3552R_CH_OUTPUT_RANGE_NEG_10__10V, 15862306a36Sopenharmony_ci}; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic const s32 ad3552r_ch_ranges[][2] = { 16162306a36Sopenharmony_ci [AD3552R_CH_OUTPUT_RANGE_0__2P5V] = {0, 2500}, 16262306a36Sopenharmony_ci [AD3552R_CH_OUTPUT_RANGE_0__5V] = {0, 5000}, 16362306a36Sopenharmony_ci [AD3552R_CH_OUTPUT_RANGE_0__10V] = {0, 10000}, 16462306a36Sopenharmony_ci [AD3552R_CH_OUTPUT_RANGE_NEG_5__5V] = {-5000, 5000}, 16562306a36Sopenharmony_ci [AD3552R_CH_OUTPUT_RANGE_NEG_10__10V] = {-10000, 10000} 16662306a36Sopenharmony_ci}; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cienum ad3542r_ch_output_range { 16962306a36Sopenharmony_ci /* Range from 0 V to 2.5 V. Requires Rfb1x connection */ 17062306a36Sopenharmony_ci AD3542R_CH_OUTPUT_RANGE_0__2P5V, 17162306a36Sopenharmony_ci /* Range from 0 V to 3 V. Requires Rfb1x connection */ 17262306a36Sopenharmony_ci AD3542R_CH_OUTPUT_RANGE_0__3V, 17362306a36Sopenharmony_ci /* Range from 0 V to 5 V. Requires Rfb1x connection */ 17462306a36Sopenharmony_ci AD3542R_CH_OUTPUT_RANGE_0__5V, 17562306a36Sopenharmony_ci /* Range from 0 V to 10 V. Requires Rfb2x connection */ 17662306a36Sopenharmony_ci AD3542R_CH_OUTPUT_RANGE_0__10V, 17762306a36Sopenharmony_ci /* Range from -2.5 V to 7.5 V. Requires Rfb2x connection */ 17862306a36Sopenharmony_ci AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V, 17962306a36Sopenharmony_ci /* Range from -5 V to 5 V. Requires Rfb2x connection */ 18062306a36Sopenharmony_ci AD3542R_CH_OUTPUT_RANGE_NEG_5__5V, 18162306a36Sopenharmony_ci}; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic const s32 ad3542r_ch_ranges[][2] = { 18462306a36Sopenharmony_ci [AD3542R_CH_OUTPUT_RANGE_0__2P5V] = {0, 2500}, 18562306a36Sopenharmony_ci [AD3542R_CH_OUTPUT_RANGE_0__3V] = {0, 3000}, 18662306a36Sopenharmony_ci [AD3542R_CH_OUTPUT_RANGE_0__5V] = {0, 5000}, 18762306a36Sopenharmony_ci [AD3542R_CH_OUTPUT_RANGE_0__10V] = {0, 10000}, 18862306a36Sopenharmony_ci [AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V] = {-2500, 7500}, 18962306a36Sopenharmony_ci [AD3542R_CH_OUTPUT_RANGE_NEG_5__5V] = {-5000, 5000} 19062306a36Sopenharmony_ci}; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cienum ad3552r_ch_gain_scaling { 19362306a36Sopenharmony_ci /* Gain scaling of 1 */ 19462306a36Sopenharmony_ci AD3552R_CH_GAIN_SCALING_1, 19562306a36Sopenharmony_ci /* Gain scaling of 0.5 */ 19662306a36Sopenharmony_ci AD3552R_CH_GAIN_SCALING_0_5, 19762306a36Sopenharmony_ci /* Gain scaling of 0.25 */ 19862306a36Sopenharmony_ci AD3552R_CH_GAIN_SCALING_0_25, 19962306a36Sopenharmony_ci /* Gain scaling of 0.125 */ 20062306a36Sopenharmony_ci AD3552R_CH_GAIN_SCALING_0_125, 20162306a36Sopenharmony_ci}; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci/* Gain * AD3552R_GAIN_SCALE */ 20462306a36Sopenharmony_cistatic const s32 gains_scaling_table[] = { 20562306a36Sopenharmony_ci [AD3552R_CH_GAIN_SCALING_1] = 1000, 20662306a36Sopenharmony_ci [AD3552R_CH_GAIN_SCALING_0_5] = 500, 20762306a36Sopenharmony_ci [AD3552R_CH_GAIN_SCALING_0_25] = 250, 20862306a36Sopenharmony_ci [AD3552R_CH_GAIN_SCALING_0_125] = 125 20962306a36Sopenharmony_ci}; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cienum ad3552r_dev_attributes { 21262306a36Sopenharmony_ci /* - Direct register values */ 21362306a36Sopenharmony_ci /* From 0-3 */ 21462306a36Sopenharmony_ci AD3552R_SDO_DRIVE_STRENGTH, 21562306a36Sopenharmony_ci /* 21662306a36Sopenharmony_ci * 0 -> Internal Vref, vref_io pin floating (default) 21762306a36Sopenharmony_ci * 1 -> Internal Vref, vref_io driven by internal vref 21862306a36Sopenharmony_ci * 2 or 3 -> External Vref 21962306a36Sopenharmony_ci */ 22062306a36Sopenharmony_ci AD3552R_VREF_SELECT, 22162306a36Sopenharmony_ci /* Read registers in ascending order if set. Else descending */ 22262306a36Sopenharmony_ci AD3552R_ADDR_ASCENSION, 22362306a36Sopenharmony_ci}; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cienum ad3552r_ch_attributes { 22662306a36Sopenharmony_ci /* DAC powerdown */ 22762306a36Sopenharmony_ci AD3552R_CH_DAC_POWERDOWN, 22862306a36Sopenharmony_ci /* DAC amplifier powerdown */ 22962306a36Sopenharmony_ci AD3552R_CH_AMPLIFIER_POWERDOWN, 23062306a36Sopenharmony_ci /* Select the output range. Select from enum ad3552r_ch_output_range */ 23162306a36Sopenharmony_ci AD3552R_CH_OUTPUT_RANGE_SEL, 23262306a36Sopenharmony_ci /* 23362306a36Sopenharmony_ci * Over-rider the range selector in order to manually set the output 23462306a36Sopenharmony_ci * voltage range 23562306a36Sopenharmony_ci */ 23662306a36Sopenharmony_ci AD3552R_CH_RANGE_OVERRIDE, 23762306a36Sopenharmony_ci /* Manually set the offset voltage */ 23862306a36Sopenharmony_ci AD3552R_CH_GAIN_OFFSET, 23962306a36Sopenharmony_ci /* Sets the polarity of the offset. */ 24062306a36Sopenharmony_ci AD3552R_CH_GAIN_OFFSET_POLARITY, 24162306a36Sopenharmony_ci /* PDAC gain scaling */ 24262306a36Sopenharmony_ci AD3552R_CH_GAIN_SCALING_P, 24362306a36Sopenharmony_ci /* NDAC gain scaling */ 24462306a36Sopenharmony_ci AD3552R_CH_GAIN_SCALING_N, 24562306a36Sopenharmony_ci /* Rfb value */ 24662306a36Sopenharmony_ci AD3552R_CH_RFB, 24762306a36Sopenharmony_ci /* Channel select. When set allow Input -> DAC and Mask -> DAC */ 24862306a36Sopenharmony_ci AD3552R_CH_SELECT, 24962306a36Sopenharmony_ci}; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistruct ad3552r_ch_data { 25262306a36Sopenharmony_ci s32 scale_int; 25362306a36Sopenharmony_ci s32 scale_dec; 25462306a36Sopenharmony_ci s32 offset_int; 25562306a36Sopenharmony_ci s32 offset_dec; 25662306a36Sopenharmony_ci s16 gain_offset; 25762306a36Sopenharmony_ci u16 rfb; 25862306a36Sopenharmony_ci u8 n; 25962306a36Sopenharmony_ci u8 p; 26062306a36Sopenharmony_ci u8 range; 26162306a36Sopenharmony_ci bool range_override; 26262306a36Sopenharmony_ci}; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistruct ad3552r_desc { 26562306a36Sopenharmony_ci /* Used to look the spi bus for atomic operations where needed */ 26662306a36Sopenharmony_ci struct mutex lock; 26762306a36Sopenharmony_ci struct gpio_desc *gpio_reset; 26862306a36Sopenharmony_ci struct gpio_desc *gpio_ldac; 26962306a36Sopenharmony_ci struct spi_device *spi; 27062306a36Sopenharmony_ci struct ad3552r_ch_data ch_data[AD3552R_NUM_CH]; 27162306a36Sopenharmony_ci struct iio_chan_spec channels[AD3552R_NUM_CH + 1]; 27262306a36Sopenharmony_ci unsigned long enabled_ch; 27362306a36Sopenharmony_ci unsigned int num_ch; 27462306a36Sopenharmony_ci enum ad3542r_id chip_id; 27562306a36Sopenharmony_ci}; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_cistatic const u16 addr_mask_map[][2] = { 27862306a36Sopenharmony_ci [AD3552R_ADDR_ASCENSION] = { 27962306a36Sopenharmony_ci AD3552R_REG_ADDR_INTERFACE_CONFIG_A, 28062306a36Sopenharmony_ci AD3552R_MASK_ADDR_ASCENSION 28162306a36Sopenharmony_ci }, 28262306a36Sopenharmony_ci [AD3552R_SDO_DRIVE_STRENGTH] = { 28362306a36Sopenharmony_ci AD3552R_REG_ADDR_INTERFACE_CONFIG_D, 28462306a36Sopenharmony_ci AD3552R_MASK_SDO_DRIVE_STRENGTH 28562306a36Sopenharmony_ci }, 28662306a36Sopenharmony_ci [AD3552R_VREF_SELECT] = { 28762306a36Sopenharmony_ci AD3552R_REG_ADDR_SH_REFERENCE_CONFIG, 28862306a36Sopenharmony_ci AD3552R_MASK_REFERENCE_VOLTAGE_SEL 28962306a36Sopenharmony_ci }, 29062306a36Sopenharmony_ci}; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci/* 0 -> reg addr, 1->ch0 mask, 2->ch1 mask */ 29362306a36Sopenharmony_cistatic const u16 addr_mask_map_ch[][3] = { 29462306a36Sopenharmony_ci [AD3552R_CH_DAC_POWERDOWN] = { 29562306a36Sopenharmony_ci AD3552R_REG_ADDR_POWERDOWN_CONFIG, 29662306a36Sopenharmony_ci AD3552R_MASK_CH_DAC_POWERDOWN(0), 29762306a36Sopenharmony_ci AD3552R_MASK_CH_DAC_POWERDOWN(1) 29862306a36Sopenharmony_ci }, 29962306a36Sopenharmony_ci [AD3552R_CH_AMPLIFIER_POWERDOWN] = { 30062306a36Sopenharmony_ci AD3552R_REG_ADDR_POWERDOWN_CONFIG, 30162306a36Sopenharmony_ci AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(0), 30262306a36Sopenharmony_ci AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(1) 30362306a36Sopenharmony_ci }, 30462306a36Sopenharmony_ci [AD3552R_CH_OUTPUT_RANGE_SEL] = { 30562306a36Sopenharmony_ci AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE, 30662306a36Sopenharmony_ci AD3552R_MASK_CH_OUTPUT_RANGE_SEL(0), 30762306a36Sopenharmony_ci AD3552R_MASK_CH_OUTPUT_RANGE_SEL(1) 30862306a36Sopenharmony_ci }, 30962306a36Sopenharmony_ci [AD3552R_CH_SELECT] = { 31062306a36Sopenharmony_ci AD3552R_REG_ADDR_CH_SELECT_16B, 31162306a36Sopenharmony_ci AD3552R_MASK_CH(0), 31262306a36Sopenharmony_ci AD3552R_MASK_CH(1) 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci}; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_cistatic u8 _ad3552r_reg_len(u8 addr) 31762306a36Sopenharmony_ci{ 31862306a36Sopenharmony_ci switch (addr) { 31962306a36Sopenharmony_ci case AD3552R_REG_ADDR_HW_LDAC_16B: 32062306a36Sopenharmony_ci case AD3552R_REG_ADDR_CH_SELECT_16B: 32162306a36Sopenharmony_ci case AD3552R_REG_ADDR_SW_LDAC_16B: 32262306a36Sopenharmony_ci case AD3552R_REG_ADDR_HW_LDAC_24B: 32362306a36Sopenharmony_ci case AD3552R_REG_ADDR_CH_SELECT_24B: 32462306a36Sopenharmony_ci case AD3552R_REG_ADDR_SW_LDAC_24B: 32562306a36Sopenharmony_ci return 1; 32662306a36Sopenharmony_ci default: 32762306a36Sopenharmony_ci break; 32862306a36Sopenharmony_ci } 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci if (addr > AD3552R_REG_ADDR_HW_LDAC_24B) 33162306a36Sopenharmony_ci return 3; 33262306a36Sopenharmony_ci if (addr > AD3552R_REG_ADDR_HW_LDAC_16B) 33362306a36Sopenharmony_ci return 2; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci return 1; 33662306a36Sopenharmony_ci} 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci/* SPI transfer to device */ 33962306a36Sopenharmony_cistatic int ad3552r_transfer(struct ad3552r_desc *dac, u8 addr, u32 len, 34062306a36Sopenharmony_ci u8 *data, bool is_read) 34162306a36Sopenharmony_ci{ 34262306a36Sopenharmony_ci /* Maximum transfer: Addr (1B) + 2 * (Data Reg (3B)) + SW LDAC(1B) */ 34362306a36Sopenharmony_ci u8 buf[8]; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci buf[0] = addr & AD3552R_ADDR_MASK; 34662306a36Sopenharmony_ci buf[0] |= is_read ? AD3552R_READ_BIT : 0; 34762306a36Sopenharmony_ci if (is_read) 34862306a36Sopenharmony_ci return spi_write_then_read(dac->spi, buf, 1, data, len); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci memcpy(buf + 1, data, len); 35162306a36Sopenharmony_ci return spi_write_then_read(dac->spi, buf, len + 1, NULL, 0); 35262306a36Sopenharmony_ci} 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_cistatic int ad3552r_write_reg(struct ad3552r_desc *dac, u8 addr, u16 val) 35562306a36Sopenharmony_ci{ 35662306a36Sopenharmony_ci u8 reg_len; 35762306a36Sopenharmony_ci u8 buf[AD3552R_MAX_REG_SIZE] = { 0 }; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci reg_len = _ad3552r_reg_len(addr); 36062306a36Sopenharmony_ci if (reg_len == 2) 36162306a36Sopenharmony_ci /* Only DAC register are 2 bytes wide */ 36262306a36Sopenharmony_ci val &= AD3552R_MASK_DAC_12B; 36362306a36Sopenharmony_ci if (reg_len == 1) 36462306a36Sopenharmony_ci buf[0] = val & 0xFF; 36562306a36Sopenharmony_ci else 36662306a36Sopenharmony_ci /* reg_len can be 2 or 3, but 3rd bytes needs to be set to 0 */ 36762306a36Sopenharmony_ci put_unaligned_be16(val, buf); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci return ad3552r_transfer(dac, addr, reg_len, buf, false); 37062306a36Sopenharmony_ci} 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_cistatic int ad3552r_read_reg(struct ad3552r_desc *dac, u8 addr, u16 *val) 37362306a36Sopenharmony_ci{ 37462306a36Sopenharmony_ci int err; 37562306a36Sopenharmony_ci u8 reg_len, buf[AD3552R_MAX_REG_SIZE] = { 0 }; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci reg_len = _ad3552r_reg_len(addr); 37862306a36Sopenharmony_ci err = ad3552r_transfer(dac, addr, reg_len, buf, true); 37962306a36Sopenharmony_ci if (err) 38062306a36Sopenharmony_ci return err; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci if (reg_len == 1) 38362306a36Sopenharmony_ci *val = buf[0]; 38462306a36Sopenharmony_ci else 38562306a36Sopenharmony_ci /* reg_len can be 2 or 3, but only first 2 bytes are relevant */ 38662306a36Sopenharmony_ci *val = get_unaligned_be16(buf); 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci return 0; 38962306a36Sopenharmony_ci} 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_cistatic u16 ad3552r_field_prep(u16 val, u16 mask) 39262306a36Sopenharmony_ci{ 39362306a36Sopenharmony_ci return (val << __ffs(mask)) & mask; 39462306a36Sopenharmony_ci} 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci/* Update field of a register, shift val if needed */ 39762306a36Sopenharmony_cistatic int ad3552r_update_reg_field(struct ad3552r_desc *dac, u8 addr, u16 mask, 39862306a36Sopenharmony_ci u16 val) 39962306a36Sopenharmony_ci{ 40062306a36Sopenharmony_ci int ret; 40162306a36Sopenharmony_ci u16 reg; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci ret = ad3552r_read_reg(dac, addr, ®); 40462306a36Sopenharmony_ci if (ret < 0) 40562306a36Sopenharmony_ci return ret; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci reg &= ~mask; 40862306a36Sopenharmony_ci reg |= ad3552r_field_prep(val, mask); 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci return ad3552r_write_reg(dac, addr, reg); 41162306a36Sopenharmony_ci} 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_cistatic int ad3552r_set_ch_value(struct ad3552r_desc *dac, 41462306a36Sopenharmony_ci enum ad3552r_ch_attributes attr, 41562306a36Sopenharmony_ci u8 ch, 41662306a36Sopenharmony_ci u16 val) 41762306a36Sopenharmony_ci{ 41862306a36Sopenharmony_ci /* Update register related to attributes in chip */ 41962306a36Sopenharmony_ci return ad3552r_update_reg_field(dac, addr_mask_map_ch[attr][0], 42062306a36Sopenharmony_ci addr_mask_map_ch[attr][ch + 1], val); 42162306a36Sopenharmony_ci} 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci#define AD3552R_CH_DAC(_idx) ((struct iio_chan_spec) { \ 42462306a36Sopenharmony_ci .type = IIO_VOLTAGE, \ 42562306a36Sopenharmony_ci .output = true, \ 42662306a36Sopenharmony_ci .indexed = true, \ 42762306a36Sopenharmony_ci .channel = _idx, \ 42862306a36Sopenharmony_ci .scan_index = _idx, \ 42962306a36Sopenharmony_ci .scan_type = { \ 43062306a36Sopenharmony_ci .sign = 'u', \ 43162306a36Sopenharmony_ci .realbits = 16, \ 43262306a36Sopenharmony_ci .storagebits = 16, \ 43362306a36Sopenharmony_ci .endianness = IIO_BE, \ 43462306a36Sopenharmony_ci }, \ 43562306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 43662306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE) | \ 43762306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_ENABLE) | \ 43862306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_OFFSET), \ 43962306a36Sopenharmony_ci}) 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_cistatic int ad3552r_read_raw(struct iio_dev *indio_dev, 44262306a36Sopenharmony_ci struct iio_chan_spec const *chan, 44362306a36Sopenharmony_ci int *val, 44462306a36Sopenharmony_ci int *val2, 44562306a36Sopenharmony_ci long mask) 44662306a36Sopenharmony_ci{ 44762306a36Sopenharmony_ci struct ad3552r_desc *dac = iio_priv(indio_dev); 44862306a36Sopenharmony_ci u16 tmp_val; 44962306a36Sopenharmony_ci int err; 45062306a36Sopenharmony_ci u8 ch = chan->channel; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci switch (mask) { 45362306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 45462306a36Sopenharmony_ci mutex_lock(&dac->lock); 45562306a36Sopenharmony_ci err = ad3552r_read_reg(dac, AD3552R_REG_ADDR_CH_DAC_24B(ch), 45662306a36Sopenharmony_ci &tmp_val); 45762306a36Sopenharmony_ci mutex_unlock(&dac->lock); 45862306a36Sopenharmony_ci if (err < 0) 45962306a36Sopenharmony_ci return err; 46062306a36Sopenharmony_ci *val = tmp_val; 46162306a36Sopenharmony_ci return IIO_VAL_INT; 46262306a36Sopenharmony_ci case IIO_CHAN_INFO_ENABLE: 46362306a36Sopenharmony_ci mutex_lock(&dac->lock); 46462306a36Sopenharmony_ci err = ad3552r_read_reg(dac, AD3552R_REG_ADDR_POWERDOWN_CONFIG, 46562306a36Sopenharmony_ci &tmp_val); 46662306a36Sopenharmony_ci mutex_unlock(&dac->lock); 46762306a36Sopenharmony_ci if (err < 0) 46862306a36Sopenharmony_ci return err; 46962306a36Sopenharmony_ci *val = !((tmp_val & AD3552R_MASK_CH_DAC_POWERDOWN(ch)) >> 47062306a36Sopenharmony_ci __ffs(AD3552R_MASK_CH_DAC_POWERDOWN(ch))); 47162306a36Sopenharmony_ci return IIO_VAL_INT; 47262306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 47362306a36Sopenharmony_ci *val = dac->ch_data[ch].scale_int; 47462306a36Sopenharmony_ci *val2 = dac->ch_data[ch].scale_dec; 47562306a36Sopenharmony_ci return IIO_VAL_INT_PLUS_MICRO; 47662306a36Sopenharmony_ci case IIO_CHAN_INFO_OFFSET: 47762306a36Sopenharmony_ci *val = dac->ch_data[ch].offset_int; 47862306a36Sopenharmony_ci *val2 = dac->ch_data[ch].offset_dec; 47962306a36Sopenharmony_ci return IIO_VAL_INT_PLUS_MICRO; 48062306a36Sopenharmony_ci default: 48162306a36Sopenharmony_ci return -EINVAL; 48262306a36Sopenharmony_ci } 48362306a36Sopenharmony_ci} 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_cistatic int ad3552r_write_raw(struct iio_dev *indio_dev, 48662306a36Sopenharmony_ci struct iio_chan_spec const *chan, 48762306a36Sopenharmony_ci int val, 48862306a36Sopenharmony_ci int val2, 48962306a36Sopenharmony_ci long mask) 49062306a36Sopenharmony_ci{ 49162306a36Sopenharmony_ci struct ad3552r_desc *dac = iio_priv(indio_dev); 49262306a36Sopenharmony_ci int err; 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci mutex_lock(&dac->lock); 49562306a36Sopenharmony_ci switch (mask) { 49662306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 49762306a36Sopenharmony_ci err = ad3552r_write_reg(dac, 49862306a36Sopenharmony_ci AD3552R_REG_ADDR_CH_DAC_24B(chan->channel), 49962306a36Sopenharmony_ci val); 50062306a36Sopenharmony_ci break; 50162306a36Sopenharmony_ci case IIO_CHAN_INFO_ENABLE: 50262306a36Sopenharmony_ci err = ad3552r_set_ch_value(dac, AD3552R_CH_DAC_POWERDOWN, 50362306a36Sopenharmony_ci chan->channel, !val); 50462306a36Sopenharmony_ci break; 50562306a36Sopenharmony_ci default: 50662306a36Sopenharmony_ci err = -EINVAL; 50762306a36Sopenharmony_ci break; 50862306a36Sopenharmony_ci } 50962306a36Sopenharmony_ci mutex_unlock(&dac->lock); 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci return err; 51262306a36Sopenharmony_ci} 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_cistatic const struct iio_info ad3552r_iio_info = { 51562306a36Sopenharmony_ci .read_raw = ad3552r_read_raw, 51662306a36Sopenharmony_ci .write_raw = ad3552r_write_raw 51762306a36Sopenharmony_ci}; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_cistatic int32_t ad3552r_trigger_hw_ldac(struct gpio_desc *ldac) 52062306a36Sopenharmony_ci{ 52162306a36Sopenharmony_ci gpiod_set_value_cansleep(ldac, 0); 52262306a36Sopenharmony_ci usleep_range(AD3552R_LDAC_PULSE_US, AD3552R_LDAC_PULSE_US + 10); 52362306a36Sopenharmony_ci gpiod_set_value_cansleep(ldac, 1); 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci return 0; 52662306a36Sopenharmony_ci} 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_cistatic int ad3552r_write_all_channels(struct ad3552r_desc *dac, u8 *data) 52962306a36Sopenharmony_ci{ 53062306a36Sopenharmony_ci int err, len; 53162306a36Sopenharmony_ci u8 addr, buff[AD3552R_NUM_CH * AD3552R_MAX_REG_SIZE + 1]; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci addr = AD3552R_REG_ADDR_CH_INPUT_24B(1); 53462306a36Sopenharmony_ci /* CH1 */ 53562306a36Sopenharmony_ci memcpy(buff, data + 2, 2); 53662306a36Sopenharmony_ci buff[2] = 0; 53762306a36Sopenharmony_ci /* CH0 */ 53862306a36Sopenharmony_ci memcpy(buff + 3, data, 2); 53962306a36Sopenharmony_ci buff[5] = 0; 54062306a36Sopenharmony_ci len = 6; 54162306a36Sopenharmony_ci if (!dac->gpio_ldac) { 54262306a36Sopenharmony_ci /* Software LDAC */ 54362306a36Sopenharmony_ci buff[6] = AD3552R_MASK_ALL_CH; 54462306a36Sopenharmony_ci ++len; 54562306a36Sopenharmony_ci } 54662306a36Sopenharmony_ci err = ad3552r_transfer(dac, addr, len, buff, false); 54762306a36Sopenharmony_ci if (err) 54862306a36Sopenharmony_ci return err; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci if (dac->gpio_ldac) 55162306a36Sopenharmony_ci return ad3552r_trigger_hw_ldac(dac->gpio_ldac); 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci return 0; 55462306a36Sopenharmony_ci} 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_cistatic int ad3552r_write_codes(struct ad3552r_desc *dac, u32 mask, u8 *data) 55762306a36Sopenharmony_ci{ 55862306a36Sopenharmony_ci int err; 55962306a36Sopenharmony_ci u8 addr, buff[AD3552R_MAX_REG_SIZE]; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci if (mask == AD3552R_MASK_ALL_CH) { 56262306a36Sopenharmony_ci if (memcmp(data, data + 2, 2) != 0) 56362306a36Sopenharmony_ci return ad3552r_write_all_channels(dac, data); 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci addr = AD3552R_REG_ADDR_INPUT_PAGE_MASK_24B; 56662306a36Sopenharmony_ci } else { 56762306a36Sopenharmony_ci addr = AD3552R_REG_ADDR_CH_INPUT_24B(__ffs(mask)); 56862306a36Sopenharmony_ci } 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci memcpy(buff, data, 2); 57162306a36Sopenharmony_ci buff[2] = 0; 57262306a36Sopenharmony_ci err = ad3552r_transfer(dac, addr, 3, data, false); 57362306a36Sopenharmony_ci if (err) 57462306a36Sopenharmony_ci return err; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci if (dac->gpio_ldac) 57762306a36Sopenharmony_ci return ad3552r_trigger_hw_ldac(dac->gpio_ldac); 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci return ad3552r_write_reg(dac, AD3552R_REG_ADDR_SW_LDAC_24B, mask); 58062306a36Sopenharmony_ci} 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_cistatic irqreturn_t ad3552r_trigger_handler(int irq, void *p) 58362306a36Sopenharmony_ci{ 58462306a36Sopenharmony_ci struct iio_poll_func *pf = p; 58562306a36Sopenharmony_ci struct iio_dev *indio_dev = pf->indio_dev; 58662306a36Sopenharmony_ci struct iio_buffer *buf = indio_dev->buffer; 58762306a36Sopenharmony_ci struct ad3552r_desc *dac = iio_priv(indio_dev); 58862306a36Sopenharmony_ci /* Maximum size of a scan */ 58962306a36Sopenharmony_ci u8 buff[AD3552R_NUM_CH * AD3552R_MAX_REG_SIZE]; 59062306a36Sopenharmony_ci int err; 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci memset(buff, 0, sizeof(buff)); 59362306a36Sopenharmony_ci err = iio_pop_from_buffer(buf, buff); 59462306a36Sopenharmony_ci if (err) 59562306a36Sopenharmony_ci goto end; 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci mutex_lock(&dac->lock); 59862306a36Sopenharmony_ci ad3552r_write_codes(dac, *indio_dev->active_scan_mask, buff); 59962306a36Sopenharmony_ci mutex_unlock(&dac->lock); 60062306a36Sopenharmony_ciend: 60162306a36Sopenharmony_ci iio_trigger_notify_done(indio_dev->trig); 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci return IRQ_HANDLED; 60462306a36Sopenharmony_ci} 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_cistatic int ad3552r_check_scratch_pad(struct ad3552r_desc *dac) 60762306a36Sopenharmony_ci{ 60862306a36Sopenharmony_ci const u16 val1 = AD3552R_SCRATCH_PAD_TEST_VAL1; 60962306a36Sopenharmony_ci const u16 val2 = AD3552R_SCRATCH_PAD_TEST_VAL2; 61062306a36Sopenharmony_ci u16 val; 61162306a36Sopenharmony_ci int err; 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci err = ad3552r_write_reg(dac, AD3552R_REG_ADDR_SCRATCH_PAD, val1); 61462306a36Sopenharmony_ci if (err < 0) 61562306a36Sopenharmony_ci return err; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci err = ad3552r_read_reg(dac, AD3552R_REG_ADDR_SCRATCH_PAD, &val); 61862306a36Sopenharmony_ci if (err < 0) 61962306a36Sopenharmony_ci return err; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci if (val1 != val) 62262306a36Sopenharmony_ci return -ENODEV; 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci err = ad3552r_write_reg(dac, AD3552R_REG_ADDR_SCRATCH_PAD, val2); 62562306a36Sopenharmony_ci if (err < 0) 62662306a36Sopenharmony_ci return err; 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci err = ad3552r_read_reg(dac, AD3552R_REG_ADDR_SCRATCH_PAD, &val); 62962306a36Sopenharmony_ci if (err < 0) 63062306a36Sopenharmony_ci return err; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci if (val2 != val) 63362306a36Sopenharmony_ci return -ENODEV; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci return 0; 63662306a36Sopenharmony_ci} 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_cistruct reg_addr_pool { 63962306a36Sopenharmony_ci struct ad3552r_desc *dac; 64062306a36Sopenharmony_ci u8 addr; 64162306a36Sopenharmony_ci}; 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_cistatic int ad3552r_read_reg_wrapper(struct reg_addr_pool *addr) 64462306a36Sopenharmony_ci{ 64562306a36Sopenharmony_ci int err; 64662306a36Sopenharmony_ci u16 val; 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci err = ad3552r_read_reg(addr->dac, addr->addr, &val); 64962306a36Sopenharmony_ci if (err) 65062306a36Sopenharmony_ci return err; 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci return val; 65362306a36Sopenharmony_ci} 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_cistatic int ad3552r_reset(struct ad3552r_desc *dac) 65662306a36Sopenharmony_ci{ 65762306a36Sopenharmony_ci struct reg_addr_pool addr; 65862306a36Sopenharmony_ci int ret; 65962306a36Sopenharmony_ci int val; 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci dac->gpio_reset = devm_gpiod_get_optional(&dac->spi->dev, "reset", 66262306a36Sopenharmony_ci GPIOD_OUT_LOW); 66362306a36Sopenharmony_ci if (IS_ERR(dac->gpio_reset)) 66462306a36Sopenharmony_ci return dev_err_probe(&dac->spi->dev, PTR_ERR(dac->gpio_reset), 66562306a36Sopenharmony_ci "Error while getting gpio reset"); 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci if (dac->gpio_reset) { 66862306a36Sopenharmony_ci /* Perform hardware reset */ 66962306a36Sopenharmony_ci usleep_range(10, 20); 67062306a36Sopenharmony_ci gpiod_set_value_cansleep(dac->gpio_reset, 1); 67162306a36Sopenharmony_ci } else { 67262306a36Sopenharmony_ci /* Perform software reset if no GPIO provided */ 67362306a36Sopenharmony_ci ret = ad3552r_update_reg_field(dac, 67462306a36Sopenharmony_ci AD3552R_REG_ADDR_INTERFACE_CONFIG_A, 67562306a36Sopenharmony_ci AD3552R_MASK_SOFTWARE_RESET, 67662306a36Sopenharmony_ci AD3552R_MASK_SOFTWARE_RESET); 67762306a36Sopenharmony_ci if (ret < 0) 67862306a36Sopenharmony_ci return ret; 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci } 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci addr.dac = dac; 68362306a36Sopenharmony_ci addr.addr = AD3552R_REG_ADDR_INTERFACE_CONFIG_B; 68462306a36Sopenharmony_ci ret = readx_poll_timeout(ad3552r_read_reg_wrapper, &addr, val, 68562306a36Sopenharmony_ci val == AD3552R_DEFAULT_CONFIG_B_VALUE || 68662306a36Sopenharmony_ci val < 0, 68762306a36Sopenharmony_ci 5000, 50000); 68862306a36Sopenharmony_ci if (val < 0) 68962306a36Sopenharmony_ci ret = val; 69062306a36Sopenharmony_ci if (ret) { 69162306a36Sopenharmony_ci dev_err(&dac->spi->dev, "Error while resetting"); 69262306a36Sopenharmony_ci return ret; 69362306a36Sopenharmony_ci } 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci ret = readx_poll_timeout(ad3552r_read_reg_wrapper, &addr, val, 69662306a36Sopenharmony_ci !(val & AD3552R_MASK_INTERFACE_NOT_READY) || 69762306a36Sopenharmony_ci val < 0, 69862306a36Sopenharmony_ci 5000, 50000); 69962306a36Sopenharmony_ci if (val < 0) 70062306a36Sopenharmony_ci ret = val; 70162306a36Sopenharmony_ci if (ret) { 70262306a36Sopenharmony_ci dev_err(&dac->spi->dev, "Error while resetting"); 70362306a36Sopenharmony_ci return ret; 70462306a36Sopenharmony_ci } 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci return ad3552r_update_reg_field(dac, 70762306a36Sopenharmony_ci addr_mask_map[AD3552R_ADDR_ASCENSION][0], 70862306a36Sopenharmony_ci addr_mask_map[AD3552R_ADDR_ASCENSION][1], 70962306a36Sopenharmony_ci val); 71062306a36Sopenharmony_ci} 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_cistatic void ad3552r_get_custom_range(struct ad3552r_desc *dac, s32 i, s32 *v_min, 71362306a36Sopenharmony_ci s32 *v_max) 71462306a36Sopenharmony_ci{ 71562306a36Sopenharmony_ci s64 vref, tmp, common, offset, gn, gp; 71662306a36Sopenharmony_ci /* 71762306a36Sopenharmony_ci * From datasheet formula (In Volts): 71862306a36Sopenharmony_ci * Vmin = 2.5 + [(GainN + Offset / 1024) * 2.5 * Rfb * 1.03] 71962306a36Sopenharmony_ci * Vmax = 2.5 - [(GainP + Offset / 1024) * 2.5 * Rfb * 1.03] 72062306a36Sopenharmony_ci * Calculus are converted to milivolts 72162306a36Sopenharmony_ci */ 72262306a36Sopenharmony_ci vref = 2500; 72362306a36Sopenharmony_ci /* 2.5 * 1.03 * 1000 (To mV) */ 72462306a36Sopenharmony_ci common = 2575 * dac->ch_data[i].rfb; 72562306a36Sopenharmony_ci offset = dac->ch_data[i].gain_offset; 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci gn = gains_scaling_table[dac->ch_data[i].n]; 72862306a36Sopenharmony_ci tmp = (1024 * gn + AD3552R_GAIN_SCALE * offset) * common; 72962306a36Sopenharmony_ci tmp = div_s64(tmp, 1024 * AD3552R_GAIN_SCALE); 73062306a36Sopenharmony_ci *v_max = vref + tmp; 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci gp = gains_scaling_table[dac->ch_data[i].p]; 73362306a36Sopenharmony_ci tmp = (1024 * gp - AD3552R_GAIN_SCALE * offset) * common; 73462306a36Sopenharmony_ci tmp = div_s64(tmp, 1024 * AD3552R_GAIN_SCALE); 73562306a36Sopenharmony_ci *v_min = vref - tmp; 73662306a36Sopenharmony_ci} 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_cistatic void ad3552r_calc_gain_and_offset(struct ad3552r_desc *dac, s32 ch) 73962306a36Sopenharmony_ci{ 74062306a36Sopenharmony_ci s32 idx, v_max, v_min, span, rem; 74162306a36Sopenharmony_ci s64 tmp; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci if (dac->ch_data[ch].range_override) { 74462306a36Sopenharmony_ci ad3552r_get_custom_range(dac, ch, &v_min, &v_max); 74562306a36Sopenharmony_ci } else { 74662306a36Sopenharmony_ci /* Normal range */ 74762306a36Sopenharmony_ci idx = dac->ch_data[ch].range; 74862306a36Sopenharmony_ci if (dac->chip_id == AD3542R_ID) { 74962306a36Sopenharmony_ci v_min = ad3542r_ch_ranges[idx][0]; 75062306a36Sopenharmony_ci v_max = ad3542r_ch_ranges[idx][1]; 75162306a36Sopenharmony_ci } else { 75262306a36Sopenharmony_ci v_min = ad3552r_ch_ranges[idx][0]; 75362306a36Sopenharmony_ci v_max = ad3552r_ch_ranges[idx][1]; 75462306a36Sopenharmony_ci } 75562306a36Sopenharmony_ci } 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci /* 75862306a36Sopenharmony_ci * From datasheet formula: 75962306a36Sopenharmony_ci * Vout = Span * (D / 65536) + Vmin 76062306a36Sopenharmony_ci * Converted to scale and offset: 76162306a36Sopenharmony_ci * Scale = Span / 65536 76262306a36Sopenharmony_ci * Offset = 65536 * Vmin / Span 76362306a36Sopenharmony_ci * 76462306a36Sopenharmony_ci * Reminders are in micros in order to be printed as 76562306a36Sopenharmony_ci * IIO_VAL_INT_PLUS_MICRO 76662306a36Sopenharmony_ci */ 76762306a36Sopenharmony_ci span = v_max - v_min; 76862306a36Sopenharmony_ci dac->ch_data[ch].scale_int = div_s64_rem(span, 65536, &rem); 76962306a36Sopenharmony_ci /* Do operations in microvolts */ 77062306a36Sopenharmony_ci dac->ch_data[ch].scale_dec = DIV_ROUND_CLOSEST((s64)rem * 1000000, 77162306a36Sopenharmony_ci 65536); 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci dac->ch_data[ch].offset_int = div_s64_rem(v_min * 65536, span, &rem); 77462306a36Sopenharmony_ci tmp = (s64)rem * 1000000; 77562306a36Sopenharmony_ci dac->ch_data[ch].offset_dec = div_s64(tmp, span); 77662306a36Sopenharmony_ci} 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_cistatic int ad3552r_find_range(u16 id, s32 *vals) 77962306a36Sopenharmony_ci{ 78062306a36Sopenharmony_ci int i, len; 78162306a36Sopenharmony_ci const s32 (*ranges)[2]; 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci if (id == AD3542R_ID) { 78462306a36Sopenharmony_ci len = ARRAY_SIZE(ad3542r_ch_ranges); 78562306a36Sopenharmony_ci ranges = ad3542r_ch_ranges; 78662306a36Sopenharmony_ci } else { 78762306a36Sopenharmony_ci len = ARRAY_SIZE(ad3552r_ch_ranges); 78862306a36Sopenharmony_ci ranges = ad3552r_ch_ranges; 78962306a36Sopenharmony_ci } 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci for (i = 0; i < len; i++) 79262306a36Sopenharmony_ci if (vals[0] == ranges[i][0] * 1000 && 79362306a36Sopenharmony_ci vals[1] == ranges[i][1] * 1000) 79462306a36Sopenharmony_ci return i; 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci return -EINVAL; 79762306a36Sopenharmony_ci} 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_cistatic int ad3552r_configure_custom_gain(struct ad3552r_desc *dac, 80062306a36Sopenharmony_ci struct fwnode_handle *child, 80162306a36Sopenharmony_ci u32 ch) 80262306a36Sopenharmony_ci{ 80362306a36Sopenharmony_ci struct device *dev = &dac->spi->dev; 80462306a36Sopenharmony_ci struct fwnode_handle *gain_child; 80562306a36Sopenharmony_ci u32 val; 80662306a36Sopenharmony_ci int err; 80762306a36Sopenharmony_ci u8 addr; 80862306a36Sopenharmony_ci u16 reg = 0, offset; 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci gain_child = fwnode_get_named_child_node(child, 81162306a36Sopenharmony_ci "custom-output-range-config"); 81262306a36Sopenharmony_ci if (!gain_child) { 81362306a36Sopenharmony_ci dev_err(dev, 81462306a36Sopenharmony_ci "mandatory custom-output-range-config property missing\n"); 81562306a36Sopenharmony_ci return -EINVAL; 81662306a36Sopenharmony_ci } 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci dac->ch_data[ch].range_override = 1; 81962306a36Sopenharmony_ci reg |= ad3552r_field_prep(1, AD3552R_MASK_CH_RANGE_OVERRIDE); 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-p", &val); 82262306a36Sopenharmony_ci if (err) { 82362306a36Sopenharmony_ci dev_err(dev, "mandatory adi,gain-scaling-p property missing\n"); 82462306a36Sopenharmony_ci goto put_child; 82562306a36Sopenharmony_ci } 82662306a36Sopenharmony_ci reg |= ad3552r_field_prep(val, AD3552R_MASK_CH_GAIN_SCALING_P); 82762306a36Sopenharmony_ci dac->ch_data[ch].p = val; 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-n", &val); 83062306a36Sopenharmony_ci if (err) { 83162306a36Sopenharmony_ci dev_err(dev, "mandatory adi,gain-scaling-n property missing\n"); 83262306a36Sopenharmony_ci goto put_child; 83362306a36Sopenharmony_ci } 83462306a36Sopenharmony_ci reg |= ad3552r_field_prep(val, AD3552R_MASK_CH_GAIN_SCALING_N); 83562306a36Sopenharmony_ci dac->ch_data[ch].n = val; 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci err = fwnode_property_read_u32(gain_child, "adi,rfb-ohms", &val); 83862306a36Sopenharmony_ci if (err) { 83962306a36Sopenharmony_ci dev_err(dev, "mandatory adi,rfb-ohms property missing\n"); 84062306a36Sopenharmony_ci goto put_child; 84162306a36Sopenharmony_ci } 84262306a36Sopenharmony_ci dac->ch_data[ch].rfb = val; 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci err = fwnode_property_read_u32(gain_child, "adi,gain-offset", &val); 84562306a36Sopenharmony_ci if (err) { 84662306a36Sopenharmony_ci dev_err(dev, "mandatory adi,gain-offset property missing\n"); 84762306a36Sopenharmony_ci goto put_child; 84862306a36Sopenharmony_ci } 84962306a36Sopenharmony_ci dac->ch_data[ch].gain_offset = val; 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci offset = abs((s32)val); 85262306a36Sopenharmony_ci reg |= ad3552r_field_prep((offset >> 8), AD3552R_MASK_CH_OFFSET_BIT_8); 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci reg |= ad3552r_field_prep((s32)val < 0, AD3552R_MASK_CH_OFFSET_POLARITY); 85562306a36Sopenharmony_ci addr = AD3552R_REG_ADDR_CH_GAIN(ch); 85662306a36Sopenharmony_ci err = ad3552r_write_reg(dac, addr, 85762306a36Sopenharmony_ci offset & AD3552R_MASK_CH_OFFSET_BITS_0_7); 85862306a36Sopenharmony_ci if (err) { 85962306a36Sopenharmony_ci dev_err(dev, "Error writing register\n"); 86062306a36Sopenharmony_ci goto put_child; 86162306a36Sopenharmony_ci } 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci err = ad3552r_write_reg(dac, addr, reg); 86462306a36Sopenharmony_ci if (err) { 86562306a36Sopenharmony_ci dev_err(dev, "Error writing register\n"); 86662306a36Sopenharmony_ci goto put_child; 86762306a36Sopenharmony_ci } 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ciput_child: 87062306a36Sopenharmony_ci fwnode_handle_put(gain_child); 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci return err; 87362306a36Sopenharmony_ci} 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_cistatic void ad3552r_reg_disable(void *reg) 87662306a36Sopenharmony_ci{ 87762306a36Sopenharmony_ci regulator_disable(reg); 87862306a36Sopenharmony_ci} 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_cistatic int ad3552r_configure_device(struct ad3552r_desc *dac) 88162306a36Sopenharmony_ci{ 88262306a36Sopenharmony_ci struct device *dev = &dac->spi->dev; 88362306a36Sopenharmony_ci struct fwnode_handle *child; 88462306a36Sopenharmony_ci struct regulator *vref; 88562306a36Sopenharmony_ci int err, cnt = 0, voltage, delta = 100000; 88662306a36Sopenharmony_ci u32 vals[2], val, ch; 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci dac->gpio_ldac = devm_gpiod_get_optional(dev, "ldac", GPIOD_OUT_HIGH); 88962306a36Sopenharmony_ci if (IS_ERR(dac->gpio_ldac)) 89062306a36Sopenharmony_ci return dev_err_probe(dev, PTR_ERR(dac->gpio_ldac), 89162306a36Sopenharmony_ci "Error getting gpio ldac"); 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci vref = devm_regulator_get_optional(dev, "vref"); 89462306a36Sopenharmony_ci if (IS_ERR(vref)) { 89562306a36Sopenharmony_ci if (PTR_ERR(vref) != -ENODEV) 89662306a36Sopenharmony_ci return dev_err_probe(dev, PTR_ERR(vref), 89762306a36Sopenharmony_ci "Error getting vref"); 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci if (device_property_read_bool(dev, "adi,vref-out-en")) 90062306a36Sopenharmony_ci val = AD3552R_INTERNAL_VREF_PIN_2P5V; 90162306a36Sopenharmony_ci else 90262306a36Sopenharmony_ci val = AD3552R_INTERNAL_VREF_PIN_FLOATING; 90362306a36Sopenharmony_ci } else { 90462306a36Sopenharmony_ci err = regulator_enable(vref); 90562306a36Sopenharmony_ci if (err) { 90662306a36Sopenharmony_ci dev_err(dev, "Failed to enable external vref supply\n"); 90762306a36Sopenharmony_ci return err; 90862306a36Sopenharmony_ci } 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci err = devm_add_action_or_reset(dev, ad3552r_reg_disable, vref); 91162306a36Sopenharmony_ci if (err) { 91262306a36Sopenharmony_ci regulator_disable(vref); 91362306a36Sopenharmony_ci return err; 91462306a36Sopenharmony_ci } 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci voltage = regulator_get_voltage(vref); 91762306a36Sopenharmony_ci if (voltage > 2500000 + delta || voltage < 2500000 - delta) { 91862306a36Sopenharmony_ci dev_warn(dev, "vref-supply must be 2.5V"); 91962306a36Sopenharmony_ci return -EINVAL; 92062306a36Sopenharmony_ci } 92162306a36Sopenharmony_ci val = AD3552R_EXTERNAL_VREF_PIN_INPUT; 92262306a36Sopenharmony_ci } 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci err = ad3552r_update_reg_field(dac, 92562306a36Sopenharmony_ci addr_mask_map[AD3552R_VREF_SELECT][0], 92662306a36Sopenharmony_ci addr_mask_map[AD3552R_VREF_SELECT][1], 92762306a36Sopenharmony_ci val); 92862306a36Sopenharmony_ci if (err) 92962306a36Sopenharmony_ci return err; 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci err = device_property_read_u32(dev, "adi,sdo-drive-strength", &val); 93262306a36Sopenharmony_ci if (!err) { 93362306a36Sopenharmony_ci if (val > 3) { 93462306a36Sopenharmony_ci dev_err(dev, "adi,sdo-drive-strength must be less than 4\n"); 93562306a36Sopenharmony_ci return -EINVAL; 93662306a36Sopenharmony_ci } 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_ci err = ad3552r_update_reg_field(dac, 93962306a36Sopenharmony_ci addr_mask_map[AD3552R_SDO_DRIVE_STRENGTH][0], 94062306a36Sopenharmony_ci addr_mask_map[AD3552R_SDO_DRIVE_STRENGTH][1], 94162306a36Sopenharmony_ci val); 94262306a36Sopenharmony_ci if (err) 94362306a36Sopenharmony_ci return err; 94462306a36Sopenharmony_ci } 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci dac->num_ch = device_get_child_node_count(dev); 94762306a36Sopenharmony_ci if (!dac->num_ch) { 94862306a36Sopenharmony_ci dev_err(dev, "No channels defined\n"); 94962306a36Sopenharmony_ci return -ENODEV; 95062306a36Sopenharmony_ci } 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci device_for_each_child_node(dev, child) { 95362306a36Sopenharmony_ci err = fwnode_property_read_u32(child, "reg", &ch); 95462306a36Sopenharmony_ci if (err) { 95562306a36Sopenharmony_ci dev_err(dev, "mandatory reg property missing\n"); 95662306a36Sopenharmony_ci goto put_child; 95762306a36Sopenharmony_ci } 95862306a36Sopenharmony_ci if (ch >= AD3552R_NUM_CH) { 95962306a36Sopenharmony_ci dev_err(dev, "reg must be less than %d\n", 96062306a36Sopenharmony_ci AD3552R_NUM_CH); 96162306a36Sopenharmony_ci err = -EINVAL; 96262306a36Sopenharmony_ci goto put_child; 96362306a36Sopenharmony_ci } 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci if (fwnode_property_present(child, "adi,output-range-microvolt")) { 96662306a36Sopenharmony_ci err = fwnode_property_read_u32_array(child, 96762306a36Sopenharmony_ci "adi,output-range-microvolt", 96862306a36Sopenharmony_ci vals, 96962306a36Sopenharmony_ci 2); 97062306a36Sopenharmony_ci if (err) { 97162306a36Sopenharmony_ci dev_err(dev, 97262306a36Sopenharmony_ci "adi,output-range-microvolt property could not be parsed\n"); 97362306a36Sopenharmony_ci goto put_child; 97462306a36Sopenharmony_ci } 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci err = ad3552r_find_range(dac->chip_id, vals); 97762306a36Sopenharmony_ci if (err < 0) { 97862306a36Sopenharmony_ci dev_err(dev, 97962306a36Sopenharmony_ci "Invalid adi,output-range-microvolt value\n"); 98062306a36Sopenharmony_ci goto put_child; 98162306a36Sopenharmony_ci } 98262306a36Sopenharmony_ci val = err; 98362306a36Sopenharmony_ci err = ad3552r_set_ch_value(dac, 98462306a36Sopenharmony_ci AD3552R_CH_OUTPUT_RANGE_SEL, 98562306a36Sopenharmony_ci ch, val); 98662306a36Sopenharmony_ci if (err) 98762306a36Sopenharmony_ci goto put_child; 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_ci dac->ch_data[ch].range = val; 99062306a36Sopenharmony_ci } else if (dac->chip_id == AD3542R_ID) { 99162306a36Sopenharmony_ci dev_err(dev, 99262306a36Sopenharmony_ci "adi,output-range-microvolt is required for ad3542r\n"); 99362306a36Sopenharmony_ci err = -EINVAL; 99462306a36Sopenharmony_ci goto put_child; 99562306a36Sopenharmony_ci } else { 99662306a36Sopenharmony_ci err = ad3552r_configure_custom_gain(dac, child, ch); 99762306a36Sopenharmony_ci if (err) 99862306a36Sopenharmony_ci goto put_child; 99962306a36Sopenharmony_ci } 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci ad3552r_calc_gain_and_offset(dac, ch); 100262306a36Sopenharmony_ci dac->enabled_ch |= BIT(ch); 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci err = ad3552r_set_ch_value(dac, AD3552R_CH_SELECT, ch, 1); 100562306a36Sopenharmony_ci if (err < 0) 100662306a36Sopenharmony_ci goto put_child; 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_ci dac->channels[cnt] = AD3552R_CH_DAC(ch); 100962306a36Sopenharmony_ci ++cnt; 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci } 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci /* Disable unused channels */ 101462306a36Sopenharmony_ci for_each_clear_bit(ch, &dac->enabled_ch, AD3552R_NUM_CH) { 101562306a36Sopenharmony_ci err = ad3552r_set_ch_value(dac, AD3552R_CH_AMPLIFIER_POWERDOWN, 101662306a36Sopenharmony_ci ch, 1); 101762306a36Sopenharmony_ci if (err) 101862306a36Sopenharmony_ci return err; 101962306a36Sopenharmony_ci } 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci dac->num_ch = cnt; 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci return 0; 102462306a36Sopenharmony_ciput_child: 102562306a36Sopenharmony_ci fwnode_handle_put(child); 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci return err; 102862306a36Sopenharmony_ci} 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_cistatic int ad3552r_init(struct ad3552r_desc *dac) 103162306a36Sopenharmony_ci{ 103262306a36Sopenharmony_ci int err; 103362306a36Sopenharmony_ci u16 val, id; 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci err = ad3552r_reset(dac); 103662306a36Sopenharmony_ci if (err) { 103762306a36Sopenharmony_ci dev_err(&dac->spi->dev, "Reset failed\n"); 103862306a36Sopenharmony_ci return err; 103962306a36Sopenharmony_ci } 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_ci err = ad3552r_check_scratch_pad(dac); 104262306a36Sopenharmony_ci if (err) { 104362306a36Sopenharmony_ci dev_err(&dac->spi->dev, "Scratch pad test failed\n"); 104462306a36Sopenharmony_ci return err; 104562306a36Sopenharmony_ci } 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci err = ad3552r_read_reg(dac, AD3552R_REG_ADDR_PRODUCT_ID_L, &val); 104862306a36Sopenharmony_ci if (err) { 104962306a36Sopenharmony_ci dev_err(&dac->spi->dev, "Fail read PRODUCT_ID_L\n"); 105062306a36Sopenharmony_ci return err; 105162306a36Sopenharmony_ci } 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci id = val; 105462306a36Sopenharmony_ci err = ad3552r_read_reg(dac, AD3552R_REG_ADDR_PRODUCT_ID_H, &val); 105562306a36Sopenharmony_ci if (err) { 105662306a36Sopenharmony_ci dev_err(&dac->spi->dev, "Fail read PRODUCT_ID_H\n"); 105762306a36Sopenharmony_ci return err; 105862306a36Sopenharmony_ci } 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci id |= val << 8; 106162306a36Sopenharmony_ci if (id != dac->chip_id) { 106262306a36Sopenharmony_ci dev_err(&dac->spi->dev, "Product id not matching\n"); 106362306a36Sopenharmony_ci return -ENODEV; 106462306a36Sopenharmony_ci } 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci return ad3552r_configure_device(dac); 106762306a36Sopenharmony_ci} 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_cistatic int ad3552r_probe(struct spi_device *spi) 107062306a36Sopenharmony_ci{ 107162306a36Sopenharmony_ci const struct spi_device_id *id = spi_get_device_id(spi); 107262306a36Sopenharmony_ci struct ad3552r_desc *dac; 107362306a36Sopenharmony_ci struct iio_dev *indio_dev; 107462306a36Sopenharmony_ci int err; 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*dac)); 107762306a36Sopenharmony_ci if (!indio_dev) 107862306a36Sopenharmony_ci return -ENOMEM; 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci dac = iio_priv(indio_dev); 108162306a36Sopenharmony_ci dac->spi = spi; 108262306a36Sopenharmony_ci dac->chip_id = id->driver_data; 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci mutex_init(&dac->lock); 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci err = ad3552r_init(dac); 108762306a36Sopenharmony_ci if (err) 108862306a36Sopenharmony_ci return err; 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci /* Config triggered buffer device */ 109162306a36Sopenharmony_ci if (dac->chip_id == AD3552R_ID) 109262306a36Sopenharmony_ci indio_dev->name = "ad3552r"; 109362306a36Sopenharmony_ci else 109462306a36Sopenharmony_ci indio_dev->name = "ad3542r"; 109562306a36Sopenharmony_ci indio_dev->dev.parent = &spi->dev; 109662306a36Sopenharmony_ci indio_dev->info = &ad3552r_iio_info; 109762306a36Sopenharmony_ci indio_dev->num_channels = dac->num_ch; 109862306a36Sopenharmony_ci indio_dev->channels = dac->channels; 109962306a36Sopenharmony_ci indio_dev->modes = INDIO_DIRECT_MODE; 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci err = devm_iio_triggered_buffer_setup_ext(&indio_dev->dev, indio_dev, NULL, 110262306a36Sopenharmony_ci &ad3552r_trigger_handler, 110362306a36Sopenharmony_ci IIO_BUFFER_DIRECTION_OUT, 110462306a36Sopenharmony_ci NULL, 110562306a36Sopenharmony_ci NULL); 110662306a36Sopenharmony_ci if (err) 110762306a36Sopenharmony_ci return err; 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_ci return devm_iio_device_register(&spi->dev, indio_dev); 111062306a36Sopenharmony_ci} 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_cistatic const struct spi_device_id ad3552r_id[] = { 111362306a36Sopenharmony_ci { "ad3542r", AD3542R_ID }, 111462306a36Sopenharmony_ci { "ad3552r", AD3552R_ID }, 111562306a36Sopenharmony_ci { } 111662306a36Sopenharmony_ci}; 111762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, ad3552r_id); 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_cistatic const struct of_device_id ad3552r_of_match[] = { 112062306a36Sopenharmony_ci { .compatible = "adi,ad3542r"}, 112162306a36Sopenharmony_ci { .compatible = "adi,ad3552r"}, 112262306a36Sopenharmony_ci { } 112362306a36Sopenharmony_ci}; 112462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, ad3552r_of_match); 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_cistatic struct spi_driver ad3552r_driver = { 112762306a36Sopenharmony_ci .driver = { 112862306a36Sopenharmony_ci .name = "ad3552r", 112962306a36Sopenharmony_ci .of_match_table = ad3552r_of_match, 113062306a36Sopenharmony_ci }, 113162306a36Sopenharmony_ci .probe = ad3552r_probe, 113262306a36Sopenharmony_ci .id_table = ad3552r_id 113362306a36Sopenharmony_ci}; 113462306a36Sopenharmony_cimodule_spi_driver(ad3552r_driver); 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_ciMODULE_AUTHOR("Mihail Chindris <mihail.chindris@analog.com>"); 113762306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Device AD3552R DAC"); 113862306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 1139