linux/drivers/iio/dac/ad5592r.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * AD5592R Digital <-> Analog converters driver
   4 *
   5 * Copyright 2015-2016 Analog Devices Inc.
   6 * Author: Paul Cercueil <paul.cercueil@analog.com>
   7 */
   8
   9#include "ad5592r-base.h"
  10
  11#include <linux/bitops.h>
  12#include <linux/module.h>
  13#include <linux/mod_devicetable.h>
  14#include <linux/spi/spi.h>
  15
  16#define AD5592R_GPIO_READBACK_EN        BIT(10)
  17#define AD5592R_LDAC_READBACK_EN        BIT(6)
  18
  19static int ad5592r_spi_wnop_r16(struct ad5592r_state *st, __be16 *buf)
  20{
  21        struct spi_device *spi = container_of(st->dev, struct spi_device, dev);
  22        struct spi_transfer t = {
  23                        .tx_buf = &st->spi_msg_nop,
  24                        .rx_buf = buf,
  25                        .len = 2
  26                };
  27
  28        st->spi_msg_nop = 0; /* NOP */
  29
  30        return spi_sync_transfer(spi, &t, 1);
  31}
  32
  33static int ad5592r_write_dac(struct ad5592r_state *st, unsigned chan, u16 value)
  34{
  35        struct spi_device *spi = container_of(st->dev, struct spi_device, dev);
  36
  37        st->spi_msg = cpu_to_be16(BIT(15) | (chan << 12) | value);
  38
  39        return spi_write(spi, &st->spi_msg, sizeof(st->spi_msg));
  40}
  41
  42static int ad5592r_read_adc(struct ad5592r_state *st, unsigned chan, u16 *value)
  43{
  44        struct spi_device *spi = container_of(st->dev, struct spi_device, dev);
  45        int ret;
  46
  47        st->spi_msg = cpu_to_be16((AD5592R_REG_ADC_SEQ << 11) | BIT(chan));
  48
  49        ret = spi_write(spi, &st->spi_msg, sizeof(st->spi_msg));
  50        if (ret)
  51                return ret;
  52
  53        /*
  54         * Invalid data:
  55         * See Figure 40. Single-Channel ADC Conversion Sequence
  56         */
  57        ret = ad5592r_spi_wnop_r16(st, &st->spi_msg);
  58        if (ret)
  59                return ret;
  60
  61        ret = ad5592r_spi_wnop_r16(st, &st->spi_msg);
  62        if (ret)
  63                return ret;
  64
  65        *value = be16_to_cpu(st->spi_msg);
  66
  67        return 0;
  68}
  69
  70static int ad5592r_reg_write(struct ad5592r_state *st, u8 reg, u16 value)
  71{
  72        struct spi_device *spi = container_of(st->dev, struct spi_device, dev);
  73
  74        st->spi_msg = cpu_to_be16((reg << 11) | value);
  75
  76        return spi_write(spi, &st->spi_msg, sizeof(st->spi_msg));
  77}
  78
  79static int ad5592r_reg_read(struct ad5592r_state *st, u8 reg, u16 *value)
  80{
  81        struct spi_device *spi = container_of(st->dev, struct spi_device, dev);
  82        int ret;
  83
  84        st->spi_msg = cpu_to_be16((AD5592R_REG_LDAC << 11) |
  85                                   AD5592R_LDAC_READBACK_EN | (reg << 2));
  86
  87        ret = spi_write(spi, &st->spi_msg, sizeof(st->spi_msg));
  88        if (ret)
  89                return ret;
  90
  91        ret = ad5592r_spi_wnop_r16(st, &st->spi_msg);
  92        if (ret)
  93                return ret;
  94
  95        *value = be16_to_cpu(st->spi_msg);
  96
  97        return 0;
  98}
  99
 100static int ad5592r_gpio_read(struct ad5592r_state *st, u8 *value)
 101{
 102        int ret;
 103
 104        ret = ad5592r_reg_write(st, AD5592R_REG_GPIO_IN_EN,
 105                                AD5592R_GPIO_READBACK_EN | st->gpio_in);
 106        if (ret)
 107                return ret;
 108
 109        ret = ad5592r_spi_wnop_r16(st, &st->spi_msg);
 110        if (ret)
 111                return ret;
 112
 113        *value = (u8) be16_to_cpu(st->spi_msg);
 114
 115        return 0;
 116}
 117
 118static const struct ad5592r_rw_ops ad5592r_rw_ops = {
 119        .write_dac = ad5592r_write_dac,
 120        .read_adc = ad5592r_read_adc,
 121        .reg_write = ad5592r_reg_write,
 122        .reg_read = ad5592r_reg_read,
 123        .gpio_read = ad5592r_gpio_read,
 124};
 125
 126static int ad5592r_spi_probe(struct spi_device *spi)
 127{
 128        const struct spi_device_id *id = spi_get_device_id(spi);
 129
 130        return ad5592r_probe(&spi->dev, id->name, &ad5592r_rw_ops);
 131}
 132
 133static int ad5592r_spi_remove(struct spi_device *spi)
 134{
 135        return ad5592r_remove(&spi->dev);
 136}
 137
 138static const struct spi_device_id ad5592r_spi_ids[] = {
 139        { .name = "ad5592r", },
 140        {}
 141};
 142MODULE_DEVICE_TABLE(spi, ad5592r_spi_ids);
 143
 144static const struct of_device_id ad5592r_of_match[] = {
 145        { .compatible = "adi,ad5592r", },
 146        {},
 147};
 148MODULE_DEVICE_TABLE(of, ad5592r_of_match);
 149
 150static const struct acpi_device_id ad5592r_acpi_match[] = {
 151        {"ADS5592", },
 152        { },
 153};
 154MODULE_DEVICE_TABLE(acpi, ad5592r_acpi_match);
 155
 156static struct spi_driver ad5592r_spi_driver = {
 157        .driver = {
 158                .name = "ad5592r",
 159                .of_match_table = ad5592r_of_match,
 160                .acpi_match_table = ad5592r_acpi_match,
 161        },
 162        .probe = ad5592r_spi_probe,
 163        .remove = ad5592r_spi_remove,
 164        .id_table = ad5592r_spi_ids,
 165};
 166module_spi_driver(ad5592r_spi_driver);
 167
 168MODULE_AUTHOR("Paul Cercueil <paul.cercueil@analog.com>");
 169MODULE_DESCRIPTION("Analog Devices AD5592R multi-channel converters");
 170MODULE_LICENSE("GPL v2");
 171