// SPDX-License-Identifier: GPL-2.0-only /* * Analog Devices AD3552R * Digital to Analog converter driver, High Speed version * * Copyright 2024 Analog Devices Inc. */ #include #include #include #include #include #include #include #include #include #include "ad3552r.h" #include "ad3552r-hs.h" /* * Important notes for register map access: * ======================================== * * Register address space is divided in 2 regions, primary (config) and * secondary (DAC). Primary region can only be accessed in simple SPI mode, * with exception for ad355x models where setting QSPI pin high allows QSPI * access to both the regions. * * Due to the fact that ad3541/2r do not implement QSPI, for proper device * detection, HDL keeps "QSPI" pin level low at boot (see ad3552r manual, rev B * table 7, pin 31, digital input). For this reason, actually the working mode * between SPI, DSPI and QSPI must be set via software, configuring the target * DAC appropriately, together with the backend API to configure the bus mode * accordingly. * * Also, important to note that none of the three modes allow to read in DDR. * * In non-buffering operations, mode is set to simple SPI SDR for all primary * and secondary region r/w accesses, to avoid to switch the mode each time DAC * register is accessed (raw accesses, r/w), and to be able to dump registers * content (possible as non DDR only). * In buffering mode, driver sets best possible mode, D/QSPI and DDR. */ struct ad3552r_hs_state { const struct ad3552r_model_data *model_data; struct gpio_desc *reset_gpio; struct device *dev; struct iio_backend *back; bool single_channel; struct ad3552r_ch_data ch_data[AD3552R_MAX_CH]; struct ad3552r_hs_platform_data *data; /* INTERFACE_CONFIG_D register cache, in DDR we cannot read values. */ u32 config_d; }; static int ad3552r_hs_reg_read(struct ad3552r_hs_state *st, u32 reg, u32 *val, size_t xfer_size) { /* No chip in the family supports DDR read. Informing of this. */ WARN_ON_ONCE(st->config_d & AD3552R_MASK_SPI_CONFIG_DDR); return st->data->bus_reg_read(st->back, reg, val, xfer_size); } static int ad3552r_hs_update_reg_bits(struct ad3552r_hs_state *st, u32 reg, u32 mask, u32 val, size_t xfer_size) { u32 rval; int ret; ret = ad3552r_hs_reg_read(st, reg, &rval, xfer_size); if (ret) return ret; rval = (rval & ~mask) | val; return st->data->bus_reg_write(st->back, reg, rval, xfer_size); } static int ad3552r_hs_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { struct ad3552r_hs_state *st = iio_priv(indio_dev); int ret; int ch = chan->channel; switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: /* * Using a "num_spi_data_lanes" variable since ad3541/2 have * only DSPI interface, while ad355x is QSPI. Then using 2 as * DDR mode is considered always on (considering buffering * mode always). */ *val = DIV_ROUND_CLOSEST(st->data->bus_sample_data_clock_hz * st->model_data->num_spi_data_lanes * 2, chan->scan_type.realbits); return IIO_VAL_INT; case IIO_CHAN_INFO_RAW: /* For RAW accesses, stay always in simple-spi. */ ret = ad3552r_hs_reg_read(st, AD3552R_REG_ADDR_CH_DAC_16B(chan->channel), val, 2); if (ret) return ret; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: *val = st->ch_data[ch].scale_int; *val2 = st->ch_data[ch].scale_dec; return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_OFFSET: *val = st->ch_data[ch].offset_int; *val2 = st->ch_data[ch].offset_dec; return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } } static int ad3552r_hs_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { struct ad3552r_hs_state *st = iio_priv(indio_dev); int ret; switch (mask) { case IIO_CHAN_INFO_RAW: if (!iio_device_claim_direct(indio_dev)) return -EBUSY; /* For RAW accesses, stay always in simple-spi. */ ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_CH_DAC_16B(chan->channel), val, 2); iio_device_release_direct(indio_dev); return ret; default: return -EINVAL; } } static int ad3552r_hs_set_bus_io_mode_hs(struct ad3552r_hs_state *st) { int bus_mode; if (st->model_data->num_spi_data_lanes == 4) bus_mode = AD3552R_IO_MODE_QSPI; else bus_mode = AD3552R_IO_MODE_DSPI; return st->data->bus_set_io_mode(st->back, bus_mode); } static int ad3552r_hs_set_target_io_mode_hs(struct ad3552r_hs_state *st) { u32 mode_target; /* * Best access for secondary reg area, QSPI where possible, * else as DSPI. */ if (st->model_data->num_spi_data_lanes == 4) mode_target = AD3552R_QUAD_SPI; else mode_target = AD3552R_DUAL_SPI; /* * Better to not use update here, since generally it is already * set as DDR mode, and it's not possible to read in DDR mode. */ return st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_TRANSFER_REGISTER, FIELD_PREP(AD3552R_MASK_MULTI_IO_MODE, mode_target) | AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE, 1); } static int ad3552r_hs_buffer_postenable(struct iio_dev *indio_dev) { struct ad3552r_hs_state *st = iio_priv(indio_dev); struct iio_backend_data_fmt fmt = { .type = IIO_BACKEND_DATA_UNSIGNED }; int loop_len, val, ret; switch (*indio_dev->active_scan_mask) { case AD3552R_CH0_ACTIVE: st->single_channel = true; loop_len = 2; val = AD3552R_REG_ADDR_CH_DAC_16B(0); break; case AD3552R_CH1_ACTIVE: st->single_channel = true; loop_len = 2; val = AD3552R_REG_ADDR_CH_DAC_16B(1); break; case AD3552R_CH0_ACTIVE | AD3552R_CH1_ACTIVE: st->single_channel = false; loop_len = 4; val = AD3552R_REG_ADDR_CH_DAC_16B(1); break; default: return -EINVAL; } /* * With ad3541/2r support, QSPI pin is held low at reset from HDL, * streaming start sequence must respect strictly the order below. */ /* Primary region access, set streaming mode (now in SPI + SDR). */ ret = ad3552r_hs_update_reg_bits(st, AD3552R_REG_ADDR_INTERFACE_CONFIG_B, AD3552R_MASK_SINGLE_INST, 0, 1); if (ret) return ret; /* * Set target loop len, keeping the value: streaming writes at address * 0x2c or 0x2a, in descending loop (2 or 4 bytes), keeping loop len * value so that it's not cleared hereafter when _CS is deasserted. */ ret = ad3552r_hs_update_reg_bits(st, AD3552R_REG_ADDR_TRANSFER_REGISTER, AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE, AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE, 1); if (ret) goto exit_err_streaming; ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_STREAM_MODE, loop_len, 1); if (ret) goto exit_err_streaming; st->config_d |= AD3552R_MASK_SPI_CONFIG_DDR; ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_INTERFACE_CONFIG_D, st->config_d, 1); if (ret) goto exit_err_streaming; ret = iio_backend_ddr_enable(st->back); if (ret) goto exit_err_ddr_mode_target; /* * From here onward mode is DDR, so reading any register is not possible * anymore, including calling "ad3552r_hs_update_reg_bits" function. */ /* Set target to best high speed mode (D or QSPI). */ ret = ad3552r_hs_set_target_io_mode_hs(st); if (ret) goto exit_err_ddr_mode; /* Set bus to best high speed mode (D or QSPI). */ ret = ad3552r_hs_set_bus_io_mode_hs(st); if (ret) goto exit_err_bus_mode_target; /* * Backend setup must be done now only, or related register values will * be disrupted by previous bus accesses. */ ret = iio_backend_data_transfer_addr(st->back, val); if (ret) goto exit_err_bus_mode_target; ret = iio_backend_data_format_set(st->back, 0, &fmt); if (ret) goto exit_err_bus_mode_target; ret = iio_backend_data_stream_enable(st->back); if (ret) goto exit_err_bus_mode_target; return 0; exit_err_bus_mode_target: /* Back to simple SPI, not using update to avoid read. */ st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_TRANSFER_REGISTER, FIELD_PREP(AD3552R_MASK_MULTI_IO_MODE, AD3552R_SPI) | AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE, 1); /* * Back bus to simple SPI, this must be executed together with above * target mode unwind, and can be done only after it. */ st->data->bus_set_io_mode(st->back, AD3552R_IO_MODE_SPI); exit_err_ddr_mode: iio_backend_ddr_disable(st->back); exit_err_ddr_mode_target: /* * Back to SDR. In DDR we cannot read, whatever the mode is, so not * using update. */ st->config_d &= ~AD3552R_MASK_SPI_CONFIG_DDR; st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_INTERFACE_CONFIG_D, st->config_d, 1); exit_err_streaming: /* Back to single instruction mode, disabling loop. */ st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_INTERFACE_CONFIG_B, AD3552R_MASK_SINGLE_INST | AD3552R_MASK_SHORT_INSTRUCTION, 1); return ret; } static int ad3552r_hs_buffer_predisable(struct iio_dev *indio_dev) { struct ad3552r_hs_state *st = iio_priv(indio_dev); int ret; ret = iio_backend_data_stream_disable(st->back); if (ret) return ret; /* * Set us to simple SPI, even if still in ddr, so to be able to write * in primary region. */ ret = st->data->bus_set_io_mode(st->back, AD3552R_IO_MODE_SPI); if (ret) return ret; /* * Back to SDR (in DDR we cannot read, whatever the mode is, so not * using update). */ st->config_d &= ~AD3552R_MASK_SPI_CONFIG_DDR; ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_INTERFACE_CONFIG_D, st->config_d, 1); if (ret) return ret; ret = iio_backend_ddr_disable(st->back); if (ret) return ret; /* * Back to simple SPI for secondary region too now, so to be able to * dump/read registers there too if needed. */ ret = ad3552r_hs_update_reg_bits(st, AD3552R_REG_ADDR_TRANSFER_REGISTER, AD3552R_MASK_MULTI_IO_MODE, AD3552R_SPI, 1); if (ret) return ret; /* Back to single instruction mode, disabling loop. */ ret = ad3552r_hs_update_reg_bits(st, AD3552R_REG_ADDR_INTERFACE_CONFIG_B, AD3552R_MASK_SINGLE_INST, AD3552R_MASK_SINGLE_INST, 1); if (ret) return ret; return 0; } static inline int ad3552r_hs_set_output_range(struct ad3552r_hs_state *st, int ch, unsigned int mode) { int val; if (ch == 0) val = FIELD_PREP(AD3552R_MASK_CH0_RANGE, mode); else val = FIELD_PREP(AD3552R_MASK_CH1_RANGE, mode); return ad3552r_hs_update_reg_bits(st, AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE, AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch), val, 1); } static int ad3552r_hs_reset(struct ad3552r_hs_state *st) { int ret; st->reset_gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(st->reset_gpio)) return PTR_ERR(st->reset_gpio); if (st->reset_gpio) { fsleep(10); gpiod_set_value_cansleep(st->reset_gpio, 0); } else { ret = ad3552r_hs_update_reg_bits(st, AD3552R_REG_ADDR_INTERFACE_CONFIG_A, AD3552R_MASK_SOFTWARE_RESET, AD3552R_MASK_SOFTWARE_RESET, 1); if (ret) return ret; } msleep(100); return 0; } static int ad3552r_hs_scratch_pad_test(struct ad3552r_hs_state *st) { int ret, val; ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_SCRATCH_PAD, AD3552R_SCRATCH_PAD_TEST_VAL1, 1); if (ret) return ret; ret = st->data->bus_reg_read(st->back, AD3552R_REG_ADDR_SCRATCH_PAD, &val, 1); if (ret) return ret; if (val != AD3552R_SCRATCH_PAD_TEST_VAL1) return dev_err_probe(st->dev, -EIO, "SCRATCH_PAD_TEST mismatch. Expected 0x%x, Read 0x%x\n", AD3552R_SCRATCH_PAD_TEST_VAL1, val); ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_SCRATCH_PAD, AD3552R_SCRATCH_PAD_TEST_VAL2, 1); if (ret) return ret; ret = st->data->bus_reg_read(st->back, AD3552R_REG_ADDR_SCRATCH_PAD, &val, 1); if (ret) return ret; if (val != AD3552R_SCRATCH_PAD_TEST_VAL2) return dev_err_probe(st->dev, -EIO, "SCRATCH_PAD_TEST mismatch. Expected 0x%x, Read 0x%x\n", AD3552R_SCRATCH_PAD_TEST_VAL2, val); return 0; } static int ad3552r_hs_setup_custom_gain(struct ad3552r_hs_state *st, int ch, u16 gain, u16 offset) { int ret; ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_CH_OFFSET(ch), offset, 1); if (ret) return ret; return st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_CH_GAIN(ch), gain, 1); } static int ad3552r_hs_setup(struct ad3552r_hs_state *st) { u16 id; u16 gain = 0, offset = 0; u32 ch, val, range; int ret; ret = ad3552r_hs_reset(st); if (ret) return ret; /* HDL starts with DDR enabled, disabling it. */ ret = iio_backend_ddr_disable(st->back); if (ret) return ret; ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_INTERFACE_CONFIG_B, AD3552R_MASK_SINGLE_INST | AD3552R_MASK_SHORT_INSTRUCTION, 1); if (ret) return ret; ret = ad3552r_hs_scratch_pad_test(st); if (ret) return ret; /* * Caching config_d, needed to restore it after streaming, * and also, to detect possible DDR read, that's not allowed. */ ret = st->data->bus_reg_read(st->back, AD3552R_REG_ADDR_INTERFACE_CONFIG_D, &st->config_d, 1); if (ret) return ret; ret = ad3552r_hs_reg_read(st, AD3552R_REG_ADDR_PRODUCT_ID_L, &val, 1); if (ret) return ret; id = val; ret = ad3552r_hs_reg_read(st, AD3552R_REG_ADDR_PRODUCT_ID_H, &val, 1); if (ret) return ret; id |= val << 8; if (id != st->model_data->chip_id) dev_warn(st->dev, "chip ID mismatch, detected 0x%x but expected 0x%x\n", id, st->model_data->chip_id); dev_dbg(st->dev, "chip id %s detected", st->model_data->model_name); /* Clear reset error flag, see ad3552r manual, rev B table 38. */ ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_ERR_STATUS, AD3552R_MASK_RESET_STATUS, 1); if (ret) return ret; ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_SH_REFERENCE_CONFIG, 0, 1); if (ret) return ret; ret = iio_backend_data_source_set(st->back, 0, IIO_BACKEND_EXTERNAL); if (ret) return ret; ret = iio_backend_data_source_set(st->back, 1, IIO_BACKEND_EXTERNAL); if (ret) return ret; ret = ad3552r_get_ref_voltage(st->dev, &val); if (ret < 0) return ret; val = ret; ret = ad3552r_hs_update_reg_bits(st, AD3552R_REG_ADDR_SH_REFERENCE_CONFIG, AD3552R_MASK_REFERENCE_VOLTAGE_SEL, val, 1); if (ret) return ret; ret = ad3552r_get_drive_strength(st->dev, &val); if (!ret) { st->config_d |= FIELD_PREP(AD3552R_MASK_SDO_DRIVE_STRENGTH, val); ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_INTERFACE_CONFIG_D, st->config_d, 1); if (ret) return ret; } device_for_each_child_node_scoped(st->dev, child) { ret = fwnode_property_read_u32(child, "reg", &ch); if (ret) return dev_err_probe(st->dev, ret, "reg property missing\n"); ret = ad3552r_get_output_range(st->dev, st->model_data, child, &range); if (ret && ret != -ENOENT) return ret; if (ret == -ENOENT) { ret = ad3552r_get_custom_gain(st->dev, child, &st->ch_data[ch].p, &st->ch_data[ch].n, &st->ch_data[ch].rfb, &st->ch_data[ch].gain_offset); if (ret) return ret; gain = ad3552r_calc_custom_gain(st->ch_data[ch].p, st->ch_data[ch].n, st->ch_data[ch].gain_offset); offset = abs(st->ch_data[ch].gain_offset); st->ch_data[ch].range_override = 1; ret = ad3552r_hs_setup_custom_gain(st, ch, gain, offset); if (ret) return ret; } else { st->ch_data[ch].range = range; ret = ad3552r_hs_set_output_range(st, ch, range); if (ret) return ret; } ad3552r_calc_gain_and_offset(&st->ch_data[ch], st->model_data); } return 0; } static const struct iio_buffer_setup_ops ad3552r_hs_buffer_setup_ops = { .postenable = ad3552r_hs_buffer_postenable, .predisable = ad3552r_hs_buffer_predisable, }; #define AD3552R_CHANNEL(ch) { \ .type = IIO_VOLTAGE, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_OFFSET), \ .output = 1, \ .indexed = 1, \ .channel = (ch), \ .scan_index = (ch), \ .scan_type = { \ .sign = 'u', \ .realbits = 16, \ .storagebits = 16, \ .endianness = IIO_BE, \ } \ } static const struct iio_chan_spec ad3552r_hs_channels[] = { AD3552R_CHANNEL(0), AD3552R_CHANNEL(1), }; static const struct iio_info ad3552r_hs_info = { .read_raw = &ad3552r_hs_read_raw, .write_raw = &ad3552r_hs_write_raw, }; static int ad3552r_hs_probe(struct platform_device *pdev) { struct ad3552r_hs_state *st; struct iio_dev *indio_dev; int ret; indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; st = iio_priv(indio_dev); st->dev = &pdev->dev; st->data = dev_get_platdata(st->dev); if (!st->data) return dev_err_probe(st->dev, -ENODEV, "No platform data !"); st->back = devm_iio_backend_get(&pdev->dev, NULL); if (IS_ERR(st->back)) return PTR_ERR(st->back); ret = devm_iio_backend_enable(&pdev->dev, st->back); if (ret) return ret; st->model_data = device_get_match_data(&pdev->dev); if (!st->model_data) return -ENODEV; indio_dev->name = "ad3552r"; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->setup_ops = &ad3552r_hs_buffer_setup_ops; indio_dev->channels = ad3552r_hs_channels; indio_dev->num_channels = ARRAY_SIZE(ad3552r_hs_channels); indio_dev->info = &ad3552r_hs_info; ret = devm_iio_backend_request_buffer(&pdev->dev, st->back, indio_dev); if (ret) return ret; ret = ad3552r_hs_setup(st); if (ret) return ret; return devm_iio_device_register(&pdev->dev, indio_dev); } static const struct of_device_id ad3552r_hs_of_id[] = { { .compatible = "adi,ad3541r", .data = &ad3541r_model_data }, { .compatible = "adi,ad3542r", .data = &ad3542r_model_data }, { .compatible = "adi,ad3551r", .data = &ad3551r_model_data }, { .compatible = "adi,ad3552r", .data = &ad3552r_model_data }, { } }; MODULE_DEVICE_TABLE(of, ad3552r_hs_of_id); static struct platform_driver ad3552r_hs_driver = { .driver = { .name = "ad3552r-hs", .of_match_table = ad3552r_hs_of_id, }, .probe = ad3552r_hs_probe, }; module_platform_driver(ad3552r_hs_driver); MODULE_AUTHOR("Dragos Bogdan "); MODULE_AUTHOR("Angelo Dureghello "); MODULE_DESCRIPTION("AD3552R Driver - High Speed version"); MODULE_LICENSE("GPL"); MODULE_IMPORT_NS("IIO_BACKEND"); MODULE_IMPORT_NS("IIO_AD3552R");