linux/drivers/iio/dac/ad5758.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * AD5758 Digital to analog converters driver
   4 *
   5 * Copyright 2018 Analog Devices Inc.
   6 *
   7 * TODO: Currently CRC is not supported in this driver
   8 */
   9#include <linux/bsearch.h>
  10#include <linux/delay.h>
  11#include <linux/kernel.h>
  12#include <linux/module.h>
  13#include <linux/property.h>
  14#include <linux/of.h>
  15#include <linux/of_device.h>
  16#include <linux/spi/spi.h>
  17#include <linux/gpio/consumer.h>
  18
  19#include <linux/iio/iio.h>
  20#include <linux/iio/sysfs.h>
  21
  22/* AD5758 registers definition */
  23#define AD5758_NOP                              0x00
  24#define AD5758_DAC_INPUT                        0x01
  25#define AD5758_DAC_OUTPUT                       0x02
  26#define AD5758_CLEAR_CODE                       0x03
  27#define AD5758_USER_GAIN                        0x04
  28#define AD5758_USER_OFFSET                      0x05
  29#define AD5758_DAC_CONFIG                       0x06
  30#define AD5758_SW_LDAC                          0x07
  31#define AD5758_KEY                              0x08
  32#define AD5758_GP_CONFIG1                       0x09
  33#define AD5758_GP_CONFIG2                       0x0A
  34#define AD5758_DCDC_CONFIG1                     0x0B
  35#define AD5758_DCDC_CONFIG2                     0x0C
  36#define AD5758_WDT_CONFIG                       0x0F
  37#define AD5758_DIGITAL_DIAG_CONFIG              0x10
  38#define AD5758_ADC_CONFIG                       0x11
  39#define AD5758_FAULT_PIN_CONFIG                 0x12
  40#define AD5758_TWO_STAGE_READBACK_SELECT        0x13
  41#define AD5758_DIGITAL_DIAG_RESULTS             0x14
  42#define AD5758_ANALOG_DIAG_RESULTS              0x15
  43#define AD5758_STATUS                           0x16
  44#define AD5758_CHIP_ID                          0x17
  45#define AD5758_FREQ_MONITOR                     0x18
  46#define AD5758_DEVICE_ID_0                      0x19
  47#define AD5758_DEVICE_ID_1                      0x1A
  48#define AD5758_DEVICE_ID_2                      0x1B
  49#define AD5758_DEVICE_ID_3                      0x1C
  50
  51/* AD5758_DAC_CONFIG */
  52#define AD5758_DAC_CONFIG_RANGE_MSK             GENMASK(3, 0)
  53#define AD5758_DAC_CONFIG_RANGE_MODE(x)         (((x) & 0xF) << 0)
  54#define AD5758_DAC_CONFIG_INT_EN_MSK            BIT(5)
  55#define AD5758_DAC_CONFIG_INT_EN_MODE(x)        (((x) & 0x1) << 5)
  56#define AD5758_DAC_CONFIG_OUT_EN_MSK            BIT(6)
  57#define AD5758_DAC_CONFIG_OUT_EN_MODE(x)        (((x) & 0x1) << 6)
  58#define AD5758_DAC_CONFIG_SR_EN_MSK             BIT(8)
  59#define AD5758_DAC_CONFIG_SR_EN_MODE(x)         (((x) & 0x1) << 8)
  60#define AD5758_DAC_CONFIG_SR_CLOCK_MSK          GENMASK(12, 9)
  61#define AD5758_DAC_CONFIG_SR_CLOCK_MODE(x)      (((x) & 0xF) << 9)
  62#define AD5758_DAC_CONFIG_SR_STEP_MSK           GENMASK(15, 13)
  63#define AD5758_DAC_CONFIG_SR_STEP_MODE(x)       (((x) & 0x7) << 13)
  64
  65/* AD5758_KEY */
  66#define AD5758_KEY_CODE_RESET_1                 0x15FA
  67#define AD5758_KEY_CODE_RESET_2                 0xAF51
  68#define AD5758_KEY_CODE_SINGLE_ADC_CONV         0x1ADC
  69#define AD5758_KEY_CODE_RESET_WDT               0x0D06
  70#define AD5758_KEY_CODE_CALIB_MEM_REFRESH       0xFCBA
  71
  72/* AD5758_DCDC_CONFIG1 */
  73#define AD5758_DCDC_CONFIG1_DCDC_VPROG_MSK      GENMASK(4, 0)
  74#define AD5758_DCDC_CONFIG1_DCDC_VPROG_MODE(x)  (((x) & 0x1F) << 0)
  75#define AD5758_DCDC_CONFIG1_DCDC_MODE_MSK       GENMASK(6, 5)
  76#define AD5758_DCDC_CONFIG1_DCDC_MODE_MODE(x)   (((x) & 0x3) << 5)
  77
  78/* AD5758_DCDC_CONFIG2 */
  79#define AD5758_DCDC_CONFIG2_ILIMIT_MSK          GENMASK(3, 1)
  80#define AD5758_DCDC_CONFIG2_ILIMIT_MODE(x)      (((x) & 0x7) << 1)
  81#define AD5758_DCDC_CONFIG2_INTR_SAT_3WI_MSK    BIT(11)
  82#define AD5758_DCDC_CONFIG2_BUSY_3WI_MSK        BIT(12)
  83
  84/* AD5758_DIGITAL_DIAG_RESULTS */
  85#define AD5758_CAL_MEM_UNREFRESHED_MSK          BIT(15)
  86
  87/* AD5758_ADC_CONFIG */
  88#define AD5758_ADC_CONFIG_PPC_BUF_EN(x)         (((x) & 0x1) << 11)
  89#define AD5758_ADC_CONFIG_PPC_BUF_MSK           BIT(11)
  90
  91#define AD5758_WR_FLAG_MSK(x)           (0x80 | ((x) & 0x1F))
  92
  93#define AD5758_FULL_SCALE_MICRO 65535000000ULL
  94
  95struct ad5758_range {
  96        int reg;
  97        int min;
  98        int max;
  99};
 100
 101/**
 102 * struct ad5758_state - driver instance specific data
 103 * @spi:        spi_device
 104 * @lock:       mutex lock
 105 * @gpio_reset: gpio descriptor for the reset line
 106 * @out_range:  struct which stores the output range
 107 * @dc_dc_mode: variable which stores the mode of operation
 108 * @dc_dc_ilim: variable which stores the dc-to-dc converter current limit
 109 * @slew_time:  variable which stores the target slew time
 110 * @pwr_down:   variable which contains whether a channel is powered down or not
 111 * @d32:        spi transfer buffers
 112 */
 113struct ad5758_state {
 114        struct spi_device *spi;
 115        struct mutex lock;
 116        struct gpio_desc *gpio_reset;
 117        struct ad5758_range out_range;
 118        unsigned int dc_dc_mode;
 119        unsigned int dc_dc_ilim;
 120        unsigned int slew_time;
 121        bool pwr_down;
 122        __be32 d32[3];
 123};
 124
 125/*
 126 * Output ranges corresponding to bits [3:0] from DAC_CONFIG register
 127 * 0000: 0 V to 5 V voltage range
 128 * 0001: 0 V to 10 V voltage range
 129 * 0010: ±5 V voltage range
 130 * 0011: ±10 V voltage range
 131 * 1000: 0 mA to 20 mA current range
 132 * 1001: 0 mA to 24 mA current range
 133 * 1010: 4 mA to 20 mA current range
 134 * 1011: ±20 mA current range
 135 * 1100: ±24 mA current range
 136 * 1101: -1 mA to +22 mA current range
 137 */
 138enum ad5758_output_range {
 139        AD5758_RANGE_0V_5V,
 140        AD5758_RANGE_0V_10V,
 141        AD5758_RANGE_PLUSMINUS_5V,
 142        AD5758_RANGE_PLUSMINUS_10V,
 143        AD5758_RANGE_0mA_20mA = 8,
 144        AD5758_RANGE_0mA_24mA,
 145        AD5758_RANGE_4mA_24mA,
 146        AD5758_RANGE_PLUSMINUS_20mA,
 147        AD5758_RANGE_PLUSMINUS_24mA,
 148        AD5758_RANGE_MINUS_1mA_PLUS_22mA,
 149};
 150
 151enum ad5758_dc_dc_mode {
 152        AD5758_DCDC_MODE_POWER_OFF,
 153        AD5758_DCDC_MODE_DPC_CURRENT,
 154        AD5758_DCDC_MODE_DPC_VOLTAGE,
 155        AD5758_DCDC_MODE_PPC_CURRENT,
 156};
 157
 158static const struct ad5758_range ad5758_voltage_range[] = {
 159        { AD5758_RANGE_0V_5V, 0, 5000000 },
 160        { AD5758_RANGE_0V_10V, 0, 10000000 },
 161        { AD5758_RANGE_PLUSMINUS_5V, -5000000, 5000000 },
 162        { AD5758_RANGE_PLUSMINUS_10V, -10000000, 10000000 }
 163};
 164
 165static const struct ad5758_range ad5758_current_range[] = {
 166        { AD5758_RANGE_0mA_20mA, 0, 20000},
 167        { AD5758_RANGE_0mA_24mA, 0, 24000 },
 168        { AD5758_RANGE_4mA_24mA, 4, 24000 },
 169        { AD5758_RANGE_PLUSMINUS_20mA, -20000, 20000 },
 170        { AD5758_RANGE_PLUSMINUS_24mA, -24000, 24000 },
 171        { AD5758_RANGE_MINUS_1mA_PLUS_22mA, -1000, 22000 },
 172};
 173
 174static const int ad5758_sr_clk[16] = {
 175        240000, 200000, 150000, 128000, 64000, 32000, 16000, 8000, 4000, 2000,
 176        1000, 512, 256, 128, 64, 16
 177};
 178
 179static const int ad5758_sr_step[8] = {
 180        4, 12, 64, 120, 256, 500, 1820, 2048
 181};
 182
 183static const int ad5758_dc_dc_ilim[6] = {
 184        150000, 200000, 250000, 300000, 350000, 400000
 185};
 186
 187static int ad5758_spi_reg_read(struct ad5758_state *st, unsigned int addr)
 188{
 189        struct spi_transfer t[] = {
 190                {
 191                        .tx_buf = &st->d32[0],
 192                        .len = 4,
 193                        .cs_change = 1,
 194                }, {
 195                        .tx_buf = &st->d32[1],
 196                        .rx_buf = &st->d32[2],
 197                        .len = 4,
 198                },
 199        };
 200        int ret;
 201
 202        st->d32[0] = cpu_to_be32(
 203                (AD5758_WR_FLAG_MSK(AD5758_TWO_STAGE_READBACK_SELECT) << 24) |
 204                (addr << 8));
 205        st->d32[1] = cpu_to_be32(AD5758_WR_FLAG_MSK(AD5758_NOP) << 24);
 206
 207        ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
 208        if (ret < 0)
 209                return ret;
 210
 211        return (be32_to_cpu(st->d32[2]) >> 8) & 0xFFFF;
 212}
 213
 214static int ad5758_spi_reg_write(struct ad5758_state *st,
 215                                unsigned int addr,
 216                                unsigned int val)
 217{
 218        st->d32[0] = cpu_to_be32((AD5758_WR_FLAG_MSK(addr) << 24) |
 219                                 ((val & 0xFFFF) << 8));
 220
 221        return spi_write(st->spi, &st->d32[0], sizeof(st->d32[0]));
 222}
 223
 224static int ad5758_spi_write_mask(struct ad5758_state *st,
 225                                 unsigned int addr,
 226                                 unsigned long int mask,
 227                                 unsigned int val)
 228{
 229        int regval;
 230
 231        regval = ad5758_spi_reg_read(st, addr);
 232        if (regval < 0)
 233                return regval;
 234
 235        regval &= ~mask;
 236        regval |= val;
 237
 238        return ad5758_spi_reg_write(st, addr, regval);
 239}
 240
 241static int cmpfunc(const void *a, const void *b)
 242{
 243        return *(int *)a - *(int *)b;
 244}
 245
 246static int ad5758_find_closest_match(const int *array,
 247                                     unsigned int size, int val)
 248{
 249        int i;
 250
 251        for (i = 0; i < size; i++) {
 252                if (val <= array[i])
 253                        return i;
 254        }
 255
 256        return size - 1;
 257}
 258
 259static int ad5758_wait_for_task_complete(struct ad5758_state *st,
 260                                         unsigned int reg,
 261                                         unsigned int mask)
 262{
 263        unsigned int timeout;
 264        int ret;
 265
 266        timeout = 10;
 267        do {
 268                ret = ad5758_spi_reg_read(st, reg);
 269                if (ret < 0)
 270                        return ret;
 271
 272                if (!(ret & mask))
 273                        return 0;
 274
 275                usleep_range(100, 1000);
 276        } while (--timeout);
 277
 278        dev_err(&st->spi->dev,
 279                "Error reading bit 0x%x in 0x%x register\n", mask, reg);
 280
 281        return -EIO;
 282}
 283
 284static int ad5758_calib_mem_refresh(struct ad5758_state *st)
 285{
 286        int ret;
 287
 288        ret = ad5758_spi_reg_write(st, AD5758_KEY,
 289                                   AD5758_KEY_CODE_CALIB_MEM_REFRESH);
 290        if (ret < 0) {
 291                dev_err(&st->spi->dev,
 292                        "Failed to initiate a calibration memory refresh\n");
 293                return ret;
 294        }
 295
 296        /* Wait to allow time for the internal calibrations to complete */
 297        return ad5758_wait_for_task_complete(st, AD5758_DIGITAL_DIAG_RESULTS,
 298                                             AD5758_CAL_MEM_UNREFRESHED_MSK);
 299}
 300
 301static int ad5758_soft_reset(struct ad5758_state *st)
 302{
 303        int ret;
 304
 305        ret = ad5758_spi_reg_write(st, AD5758_KEY, AD5758_KEY_CODE_RESET_1);
 306        if (ret < 0)
 307                return ret;
 308
 309        ret = ad5758_spi_reg_write(st, AD5758_KEY, AD5758_KEY_CODE_RESET_2);
 310
 311        /* Perform a software reset and wait at least 100us */
 312        usleep_range(100, 1000);
 313
 314        return ret;
 315}
 316
 317static int ad5758_set_dc_dc_conv_mode(struct ad5758_state *st,
 318                                      enum ad5758_dc_dc_mode mode)
 319{
 320        int ret;
 321
 322        /*
 323         * The ENABLE_PPC_BUFFERS bit must be set prior to enabling PPC current
 324         * mode.
 325         */
 326        if (mode == AD5758_DCDC_MODE_PPC_CURRENT) {
 327                ret  = ad5758_spi_write_mask(st, AD5758_ADC_CONFIG,
 328                                    AD5758_ADC_CONFIG_PPC_BUF_MSK,
 329                                    AD5758_ADC_CONFIG_PPC_BUF_EN(1));
 330                if (ret < 0)
 331                        return ret;
 332        }
 333
 334        ret = ad5758_spi_write_mask(st, AD5758_DCDC_CONFIG1,
 335                                    AD5758_DCDC_CONFIG1_DCDC_MODE_MSK,
 336                                    AD5758_DCDC_CONFIG1_DCDC_MODE_MODE(mode));
 337        if (ret < 0)
 338                return ret;
 339
 340        /*
 341         * Poll the BUSY_3WI bit in the DCDC_CONFIG2 register until it is 0.
 342         * This allows the 3-wire interface communication to complete.
 343         */
 344        ret = ad5758_wait_for_task_complete(st, AD5758_DCDC_CONFIG2,
 345                                            AD5758_DCDC_CONFIG2_BUSY_3WI_MSK);
 346        if (ret < 0)
 347                return ret;
 348
 349        st->dc_dc_mode = mode;
 350
 351        return ret;
 352}
 353
 354static int ad5758_set_dc_dc_ilim(struct ad5758_state *st, unsigned int ilim)
 355{
 356        int ret;
 357
 358        ret = ad5758_spi_write_mask(st, AD5758_DCDC_CONFIG2,
 359                                    AD5758_DCDC_CONFIG2_ILIMIT_MSK,
 360                                    AD5758_DCDC_CONFIG2_ILIMIT_MODE(ilim));
 361        if (ret < 0)
 362                return ret;
 363        /*
 364         * Poll the BUSY_3WI bit in the DCDC_CONFIG2 register until it is 0.
 365         * This allows the 3-wire interface communication to complete.
 366         */
 367        return ad5758_wait_for_task_complete(st, AD5758_DCDC_CONFIG2,
 368                                             AD5758_DCDC_CONFIG2_BUSY_3WI_MSK);
 369}
 370
 371static int ad5758_slew_rate_set(struct ad5758_state *st,
 372                                unsigned int sr_clk_idx,
 373                                unsigned int sr_step_idx)
 374{
 375        unsigned int mode;
 376        unsigned long int mask;
 377        int ret;
 378
 379        mask = AD5758_DAC_CONFIG_SR_EN_MSK |
 380               AD5758_DAC_CONFIG_SR_CLOCK_MSK |
 381               AD5758_DAC_CONFIG_SR_STEP_MSK;
 382        mode = AD5758_DAC_CONFIG_SR_EN_MODE(1) |
 383               AD5758_DAC_CONFIG_SR_STEP_MODE(sr_step_idx) |
 384               AD5758_DAC_CONFIG_SR_CLOCK_MODE(sr_clk_idx);
 385
 386        ret = ad5758_spi_write_mask(st, AD5758_DAC_CONFIG, mask, mode);
 387        if (ret < 0)
 388                return ret;
 389
 390        /* Wait to allow time for the internal calibrations to complete */
 391        return ad5758_wait_for_task_complete(st, AD5758_DIGITAL_DIAG_RESULTS,
 392                                             AD5758_CAL_MEM_UNREFRESHED_MSK);
 393}
 394
 395static int ad5758_slew_rate_config(struct ad5758_state *st)
 396{
 397        unsigned int sr_clk_idx, sr_step_idx;
 398        int i, res;
 399        s64 diff_new, diff_old;
 400        u64 sr_step, calc_slew_time;
 401
 402        sr_clk_idx = 0;
 403        sr_step_idx = 0;
 404        diff_old = S64_MAX;
 405        /*
 406         * The slew time can be determined by using the formula:
 407         * Slew Time = (Full Scale Out / (Step Size x Update Clk Freq))
 408         * where Slew time is expressed in microseconds
 409         * Given the desired slew time, the following algorithm determines the
 410         * best match for the step size and the update clock frequency.
 411         */
 412        for (i = 0; i < ARRAY_SIZE(ad5758_sr_clk); i++) {
 413                /*
 414                 * Go through each valid update clock freq and determine a raw
 415                 * value for the step size by using the formula:
 416                 * Step Size = Full Scale Out / (Update Clk Freq * Slew Time)
 417                 */
 418                sr_step = AD5758_FULL_SCALE_MICRO;
 419                do_div(sr_step, ad5758_sr_clk[i]);
 420                do_div(sr_step, st->slew_time);
 421                /*
 422                 * After a raw value for step size was determined, find the
 423                 * closest valid match
 424                 */
 425                res = ad5758_find_closest_match(ad5758_sr_step,
 426                                                ARRAY_SIZE(ad5758_sr_step),
 427                                                sr_step);
 428                /* Calculate the slew time */
 429                calc_slew_time = AD5758_FULL_SCALE_MICRO;
 430                do_div(calc_slew_time, ad5758_sr_step[res]);
 431                do_div(calc_slew_time, ad5758_sr_clk[i]);
 432                /*
 433                 * Determine with how many microseconds the calculated slew time
 434                 * is different from the desired slew time and store the diff
 435                 * for the next iteration
 436                 */
 437                diff_new = abs(st->slew_time - calc_slew_time);
 438                if (diff_new < diff_old) {
 439                        diff_old = diff_new;
 440                        sr_clk_idx = i;
 441                        sr_step_idx = res;
 442                }
 443        }
 444
 445        return ad5758_slew_rate_set(st, sr_clk_idx, sr_step_idx);
 446}
 447
 448static int ad5758_set_out_range(struct ad5758_state *st, int range)
 449{
 450        int ret;
 451
 452        ret = ad5758_spi_write_mask(st, AD5758_DAC_CONFIG,
 453                                    AD5758_DAC_CONFIG_RANGE_MSK,
 454                                    AD5758_DAC_CONFIG_RANGE_MODE(range));
 455        if (ret < 0)
 456                return ret;
 457
 458        /* Wait to allow time for the internal calibrations to complete */
 459        return ad5758_wait_for_task_complete(st, AD5758_DIGITAL_DIAG_RESULTS,
 460                                             AD5758_CAL_MEM_UNREFRESHED_MSK);
 461}
 462
 463static int ad5758_internal_buffers_en(struct ad5758_state *st, bool enable)
 464{
 465        int ret;
 466
 467        ret = ad5758_spi_write_mask(st, AD5758_DAC_CONFIG,
 468                                    AD5758_DAC_CONFIG_INT_EN_MSK,
 469                                    AD5758_DAC_CONFIG_INT_EN_MODE(enable));
 470        if (ret < 0)
 471                return ret;
 472
 473        /* Wait to allow time for the internal calibrations to complete */
 474        return ad5758_wait_for_task_complete(st, AD5758_DIGITAL_DIAG_RESULTS,
 475                                             AD5758_CAL_MEM_UNREFRESHED_MSK);
 476}
 477
 478static int ad5758_reset(struct ad5758_state *st)
 479{
 480        if (st->gpio_reset) {
 481                gpiod_set_value(st->gpio_reset, 0);
 482                usleep_range(100, 1000);
 483                gpiod_set_value(st->gpio_reset, 1);
 484                usleep_range(100, 1000);
 485
 486                return 0;
 487        } else {
 488                /* Perform a software reset */
 489                return ad5758_soft_reset(st);
 490        }
 491}
 492
 493static int ad5758_reg_access(struct iio_dev *indio_dev,
 494                             unsigned int reg,
 495                             unsigned int writeval,
 496                             unsigned int *readval)
 497{
 498        struct ad5758_state *st = iio_priv(indio_dev);
 499        int ret;
 500
 501        mutex_lock(&st->lock);
 502        if (readval) {
 503                ret = ad5758_spi_reg_read(st, reg);
 504                if (ret < 0) {
 505                        mutex_unlock(&st->lock);
 506                        return ret;
 507                }
 508
 509                *readval = ret;
 510                ret = 0;
 511        } else {
 512                ret = ad5758_spi_reg_write(st, reg, writeval);
 513        }
 514        mutex_unlock(&st->lock);
 515
 516        return ret;
 517}
 518
 519static int ad5758_read_raw(struct iio_dev *indio_dev,
 520                           struct iio_chan_spec const *chan,
 521                           int *val, int *val2, long info)
 522{
 523        struct ad5758_state *st = iio_priv(indio_dev);
 524        int max, min, ret;
 525
 526        switch (info) {
 527        case IIO_CHAN_INFO_RAW:
 528                mutex_lock(&st->lock);
 529                ret = ad5758_spi_reg_read(st, AD5758_DAC_INPUT);
 530                mutex_unlock(&st->lock);
 531                if (ret < 0)
 532                        return ret;
 533
 534                *val = ret;
 535                return IIO_VAL_INT;
 536        case IIO_CHAN_INFO_SCALE:
 537                min = st->out_range.min;
 538                max = st->out_range.max;
 539                *val = (max - min) / 1000;
 540                *val2 = 16;
 541                return IIO_VAL_FRACTIONAL_LOG2;
 542        case IIO_CHAN_INFO_OFFSET:
 543                min = st->out_range.min;
 544                max = st->out_range.max;
 545                *val = ((min * (1 << 16)) / (max - min)) / 1000;
 546                return IIO_VAL_INT;
 547        default:
 548                return -EINVAL;
 549        }
 550}
 551
 552static int ad5758_write_raw(struct iio_dev *indio_dev,
 553                            struct iio_chan_spec const *chan,
 554                            int val, int val2, long info)
 555{
 556        struct ad5758_state *st = iio_priv(indio_dev);
 557        int ret;
 558
 559        switch (info) {
 560        case IIO_CHAN_INFO_RAW:
 561                mutex_lock(&st->lock);
 562                ret = ad5758_spi_reg_write(st, AD5758_DAC_INPUT, val);
 563                mutex_unlock(&st->lock);
 564                return ret;
 565        default:
 566                return -EINVAL;
 567        }
 568}
 569
 570static ssize_t ad5758_read_powerdown(struct iio_dev *indio_dev,
 571                                     uintptr_t priv,
 572                                     const struct iio_chan_spec *chan,
 573                                     char *buf)
 574{
 575        struct ad5758_state *st = iio_priv(indio_dev);
 576
 577        return sysfs_emit(buf, "%d\n", st->pwr_down);
 578}
 579
 580static ssize_t ad5758_write_powerdown(struct iio_dev *indio_dev,
 581                                      uintptr_t priv,
 582                                      struct iio_chan_spec const *chan,
 583                                      const char *buf, size_t len)
 584{
 585        struct ad5758_state *st = iio_priv(indio_dev);
 586        bool pwr_down;
 587        unsigned int dac_config_mode, val;
 588        unsigned long int dac_config_msk;
 589        int ret;
 590
 591        ret = kstrtobool(buf, &pwr_down);
 592        if (ret)
 593                return ret;
 594
 595        mutex_lock(&st->lock);
 596        if (pwr_down)
 597                val = 0;
 598        else
 599                val = 1;
 600
 601        dac_config_mode = AD5758_DAC_CONFIG_OUT_EN_MODE(val) |
 602                          AD5758_DAC_CONFIG_INT_EN_MODE(val);
 603        dac_config_msk = AD5758_DAC_CONFIG_OUT_EN_MSK |
 604                         AD5758_DAC_CONFIG_INT_EN_MSK;
 605
 606        ret = ad5758_spi_write_mask(st, AD5758_DAC_CONFIG,
 607                                    dac_config_msk,
 608                                    dac_config_mode);
 609        if (ret < 0)
 610                goto err_unlock;
 611
 612        st->pwr_down = pwr_down;
 613
 614err_unlock:
 615        mutex_unlock(&st->lock);
 616
 617        return ret ? ret : len;
 618}
 619
 620static const struct iio_info ad5758_info = {
 621        .read_raw = ad5758_read_raw,
 622        .write_raw = ad5758_write_raw,
 623        .debugfs_reg_access = &ad5758_reg_access,
 624};
 625
 626static const struct iio_chan_spec_ext_info ad5758_ext_info[] = {
 627        {
 628                .name = "powerdown",
 629                .read = ad5758_read_powerdown,
 630                .write = ad5758_write_powerdown,
 631                .shared = IIO_SHARED_BY_TYPE,
 632        },
 633        { }
 634};
 635
 636#define AD5758_DAC_CHAN(_chan_type) {                           \
 637        .type = (_chan_type),                                   \
 638        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_RAW) |    \
 639                BIT(IIO_CHAN_INFO_SCALE) |                      \
 640                BIT(IIO_CHAN_INFO_OFFSET),                      \
 641        .indexed = 1,                                           \
 642        .output = 1,                                            \
 643        .ext_info = ad5758_ext_info,                            \
 644}
 645
 646static const struct iio_chan_spec ad5758_voltage_ch[] = {
 647        AD5758_DAC_CHAN(IIO_VOLTAGE)
 648};
 649
 650static const struct iio_chan_spec ad5758_current_ch[] = {
 651        AD5758_DAC_CHAN(IIO_CURRENT)
 652};
 653
 654static bool ad5758_is_valid_mode(enum ad5758_dc_dc_mode mode)
 655{
 656        switch (mode) {
 657        case AD5758_DCDC_MODE_DPC_CURRENT:
 658        case AD5758_DCDC_MODE_DPC_VOLTAGE:
 659        case AD5758_DCDC_MODE_PPC_CURRENT:
 660                return true;
 661        default:
 662                return false;
 663        }
 664}
 665
 666static int ad5758_crc_disable(struct ad5758_state *st)
 667{
 668        unsigned int mask;
 669
 670        mask = (AD5758_WR_FLAG_MSK(AD5758_DIGITAL_DIAG_CONFIG) << 24) | 0x5C3A;
 671        st->d32[0] = cpu_to_be32(mask);
 672
 673        return spi_write(st->spi, &st->d32[0], 4);
 674}
 675
 676static int ad5758_find_out_range(struct ad5758_state *st,
 677                                 const struct ad5758_range *range,
 678                                 unsigned int size,
 679                                 int min, int max)
 680{
 681        int i;
 682
 683        for (i = 0; i < size; i++) {
 684                if ((min == range[i].min) && (max == range[i].max)) {
 685                        st->out_range.reg = range[i].reg;
 686                        st->out_range.min = range[i].min;
 687                        st->out_range.max = range[i].max;
 688
 689                        return 0;
 690                }
 691        }
 692
 693        return -EINVAL;
 694}
 695
 696static int ad5758_parse_dt(struct ad5758_state *st)
 697{
 698        unsigned int tmp, tmparray[2], size;
 699        const struct ad5758_range *range;
 700        int *index, ret;
 701
 702        st->dc_dc_ilim = 0;
 703        ret = device_property_read_u32(&st->spi->dev,
 704                                       "adi,dc-dc-ilim-microamp", &tmp);
 705        if (ret) {
 706                dev_dbg(&st->spi->dev,
 707                        "Missing \"dc-dc-ilim-microamp\" property\n");
 708        } else {
 709                index = bsearch(&tmp, ad5758_dc_dc_ilim,
 710                                ARRAY_SIZE(ad5758_dc_dc_ilim),
 711                                sizeof(int), cmpfunc);
 712                if (!index)
 713                        dev_dbg(&st->spi->dev, "dc-dc-ilim out of range\n");
 714                else
 715                        st->dc_dc_ilim = index - ad5758_dc_dc_ilim;
 716        }
 717
 718        ret = device_property_read_u32(&st->spi->dev, "adi,dc-dc-mode",
 719                                       &st->dc_dc_mode);
 720        if (ret) {
 721                dev_err(&st->spi->dev, "Missing \"dc-dc-mode\" property\n");
 722                return ret;
 723        }
 724
 725        if (!ad5758_is_valid_mode(st->dc_dc_mode))
 726                return -EINVAL;
 727
 728        if (st->dc_dc_mode == AD5758_DCDC_MODE_DPC_VOLTAGE) {
 729                ret = device_property_read_u32_array(&st->spi->dev,
 730                                                     "adi,range-microvolt",
 731                                                     tmparray, 2);
 732                if (ret) {
 733                        dev_err(&st->spi->dev,
 734                                "Missing \"range-microvolt\" property\n");
 735                        return ret;
 736                }
 737                range = ad5758_voltage_range;
 738                size = ARRAY_SIZE(ad5758_voltage_range);
 739        } else {
 740                ret = device_property_read_u32_array(&st->spi->dev,
 741                                                     "adi,range-microamp",
 742                                                     tmparray, 2);
 743                if (ret) {
 744                        dev_err(&st->spi->dev,
 745                                "Missing \"range-microamp\" property\n");
 746                        return ret;
 747                }
 748                range = ad5758_current_range;
 749                size = ARRAY_SIZE(ad5758_current_range);
 750        }
 751
 752        ret = ad5758_find_out_range(st, range, size, tmparray[0], tmparray[1]);
 753        if (ret) {
 754                dev_err(&st->spi->dev, "range invalid\n");
 755                return ret;
 756        }
 757
 758        ret = device_property_read_u32(&st->spi->dev, "adi,slew-time-us", &tmp);
 759        if (ret) {
 760                dev_dbg(&st->spi->dev, "Missing \"slew-time-us\" property\n");
 761                st->slew_time = 0;
 762        } else {
 763                st->slew_time = tmp;
 764        }
 765
 766        return 0;
 767}
 768
 769static int ad5758_init(struct ad5758_state *st)
 770{
 771        int regval, ret;
 772
 773        st->gpio_reset = devm_gpiod_get_optional(&st->spi->dev, "reset",
 774                                                 GPIOD_OUT_HIGH);
 775        if (IS_ERR(st->gpio_reset))
 776                return PTR_ERR(st->gpio_reset);
 777
 778        /* Disable CRC checks */
 779        ret = ad5758_crc_disable(st);
 780        if (ret < 0)
 781                return ret;
 782
 783        /* Perform a reset */
 784        ret = ad5758_reset(st);
 785        if (ret < 0)
 786                return ret;
 787
 788        /* Disable CRC checks */
 789        ret = ad5758_crc_disable(st);
 790        if (ret < 0)
 791                return ret;
 792
 793        /* Perform a calibration memory refresh */
 794        ret = ad5758_calib_mem_refresh(st);
 795        if (ret < 0)
 796                return ret;
 797
 798        regval = ad5758_spi_reg_read(st, AD5758_DIGITAL_DIAG_RESULTS);
 799        if (regval < 0)
 800                return regval;
 801
 802        /* Clear all the error flags */
 803        ret = ad5758_spi_reg_write(st, AD5758_DIGITAL_DIAG_RESULTS, regval);
 804        if (ret < 0)
 805                return ret;
 806
 807        /* Set the dc-to-dc current limit */
 808        ret = ad5758_set_dc_dc_ilim(st, st->dc_dc_ilim);
 809        if (ret < 0)
 810                return ret;
 811
 812        /* Configure the dc-to-dc controller mode */
 813        ret = ad5758_set_dc_dc_conv_mode(st, st->dc_dc_mode);
 814        if (ret < 0)
 815                return ret;
 816
 817        /* Configure the output range */
 818        ret = ad5758_set_out_range(st, st->out_range.reg);
 819        if (ret < 0)
 820                return ret;
 821
 822        /* Enable Slew Rate Control, set the slew rate clock and step */
 823        if (st->slew_time) {
 824                ret = ad5758_slew_rate_config(st);
 825                if (ret < 0)
 826                        return ret;
 827        }
 828
 829        /* Power up the DAC and internal (INT) amplifiers */
 830        ret = ad5758_internal_buffers_en(st, 1);
 831        if (ret < 0)
 832                return ret;
 833
 834        /* Enable VIOUT */
 835        return ad5758_spi_write_mask(st, AD5758_DAC_CONFIG,
 836                                     AD5758_DAC_CONFIG_OUT_EN_MSK,
 837                                     AD5758_DAC_CONFIG_OUT_EN_MODE(1));
 838}
 839
 840static int ad5758_probe(struct spi_device *spi)
 841{
 842        struct ad5758_state *st;
 843        struct iio_dev *indio_dev;
 844        int ret;
 845
 846        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 847        if (!indio_dev)
 848                return -ENOMEM;
 849
 850        st = iio_priv(indio_dev);
 851        spi_set_drvdata(spi, indio_dev);
 852
 853        st->spi = spi;
 854
 855        mutex_init(&st->lock);
 856
 857        indio_dev->name = spi_get_device_id(spi)->name;
 858        indio_dev->info = &ad5758_info;
 859        indio_dev->modes = INDIO_DIRECT_MODE;
 860        indio_dev->num_channels = 1;
 861
 862        ret = ad5758_parse_dt(st);
 863        if (ret < 0)
 864                return ret;
 865
 866        if (st->dc_dc_mode == AD5758_DCDC_MODE_DPC_VOLTAGE)
 867                indio_dev->channels = ad5758_voltage_ch;
 868        else
 869                indio_dev->channels = ad5758_current_ch;
 870
 871        ret = ad5758_init(st);
 872        if (ret < 0) {
 873                dev_err(&spi->dev, "AD5758 init failed\n");
 874                return ret;
 875        }
 876
 877        return devm_iio_device_register(&st->spi->dev, indio_dev);
 878}
 879
 880static const struct spi_device_id ad5758_id[] = {
 881        { "ad5758", 0 },
 882        {}
 883};
 884MODULE_DEVICE_TABLE(spi, ad5758_id);
 885
 886static const struct of_device_id ad5758_of_match[] = {
 887        { .compatible = "adi,ad5758" },
 888        { },
 889};
 890MODULE_DEVICE_TABLE(of, ad5758_of_match);
 891
 892static struct spi_driver ad5758_driver = {
 893        .driver = {
 894                .name = KBUILD_MODNAME,
 895                .of_match_table = ad5758_of_match,
 896        },
 897        .probe = ad5758_probe,
 898        .id_table = ad5758_id,
 899};
 900
 901module_spi_driver(ad5758_driver);
 902
 903MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
 904MODULE_DESCRIPTION("Analog Devices AD5758 DAC");
 905MODULE_LICENSE("GPL v2");
 906