root/drivers/iio/dac/mcp4922.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mcp4922_spi_write
  2. mcp4922_read_raw
  3. mcp4922_write_raw
  4. mcp4922_probe
  5. mcp4922_remove

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * mcp4922.c
   4  *
   5  * Driver for Microchip Digital to Analog Converters.
   6  * Supports MCP4902, MCP4912, and MCP4922.
   7  *
   8  * Copyright (c) 2014 EMAC Inc.
   9  */
  10 
  11 #include <linux/module.h>
  12 #include <linux/init.h>
  13 #include <linux/spi/spi.h>
  14 #include <linux/iio/iio.h>
  15 #include <linux/iio/sysfs.h>
  16 #include <linux/regulator/consumer.h>
  17 #include <linux/bitops.h>
  18 
  19 #define MCP4922_NUM_CHANNELS    2
  20 
  21 enum mcp4922_supported_device_ids {
  22         ID_MCP4902,
  23         ID_MCP4912,
  24         ID_MCP4922,
  25 };
  26 
  27 struct mcp4922_state {
  28         struct spi_device *spi;
  29         unsigned int value[MCP4922_NUM_CHANNELS];
  30         unsigned int vref_mv;
  31         struct regulator *vref_reg;
  32         u8 mosi[2] ____cacheline_aligned;
  33 };
  34 
  35 #define MCP4922_CHAN(chan, bits) {                      \
  36         .type = IIO_VOLTAGE,                            \
  37         .output = 1,                                    \
  38         .indexed = 1,                                   \
  39         .channel = chan,                                \
  40         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
  41         .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
  42         .scan_type = {                                  \
  43                 .sign = 'u',                            \
  44                 .realbits = (bits),                     \
  45                 .storagebits = 16,                      \
  46                 .shift = 12 - (bits),                   \
  47         },                                              \
  48 }
  49 
  50 static int mcp4922_spi_write(struct mcp4922_state *state, u8 addr, u32 val)
  51 {
  52         state->mosi[1] = val & 0xff;
  53         state->mosi[0] = (addr == 0) ? 0x00 : 0x80;
  54         state->mosi[0] |= 0x30 | ((val >> 8) & 0x0f);
  55 
  56         return spi_write(state->spi, state->mosi, 2);
  57 }
  58 
  59 static int mcp4922_read_raw(struct iio_dev *indio_dev,
  60                 struct iio_chan_spec const *chan,
  61                 int *val,
  62                 int *val2,
  63                 long mask)
  64 {
  65         struct mcp4922_state *state = iio_priv(indio_dev);
  66 
  67         switch (mask) {
  68         case IIO_CHAN_INFO_RAW:
  69                 *val = state->value[chan->channel];
  70                 return IIO_VAL_INT;
  71         case IIO_CHAN_INFO_SCALE:
  72                 *val = state->vref_mv;
  73                 *val2 = chan->scan_type.realbits;
  74                 return IIO_VAL_FRACTIONAL_LOG2;
  75         default:
  76                 return -EINVAL;
  77         }
  78 }
  79 
  80 static int mcp4922_write_raw(struct iio_dev *indio_dev,
  81                 struct iio_chan_spec const *chan,
  82                 int val,
  83                 int val2,
  84                 long mask)
  85 {
  86         struct mcp4922_state *state = iio_priv(indio_dev);
  87         int ret;
  88 
  89         if (val2 != 0)
  90                 return -EINVAL;
  91 
  92         switch (mask) {
  93         case IIO_CHAN_INFO_RAW:
  94                 if (val < 0 || val > GENMASK(chan->scan_type.realbits - 1, 0))
  95                         return -EINVAL;
  96                 val <<= chan->scan_type.shift;
  97 
  98                 ret = mcp4922_spi_write(state, chan->channel, val);
  99                 if (!ret)
 100                         state->value[chan->channel] = val;
 101                 return ret;
 102 
 103         default:
 104                 return -EINVAL;
 105         }
 106 }
 107 
 108 static const struct iio_chan_spec mcp4922_channels[3][MCP4922_NUM_CHANNELS] = {
 109         [ID_MCP4902] = { MCP4922_CHAN(0, 8),    MCP4922_CHAN(1, 8) },
 110         [ID_MCP4912] = { MCP4922_CHAN(0, 10),   MCP4922_CHAN(1, 10) },
 111         [ID_MCP4922] = { MCP4922_CHAN(0, 12),   MCP4922_CHAN(1, 12) },
 112 };
 113 
 114 static const struct iio_info mcp4922_info = {
 115         .read_raw = &mcp4922_read_raw,
 116         .write_raw = &mcp4922_write_raw,
 117 };
 118 
 119 static int mcp4922_probe(struct spi_device *spi)
 120 {
 121         struct iio_dev *indio_dev;
 122         struct mcp4922_state *state;
 123         const struct spi_device_id *id;
 124         int ret;
 125 
 126         indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*state));
 127         if (indio_dev == NULL)
 128                 return -ENOMEM;
 129 
 130         state = iio_priv(indio_dev);
 131         state->spi = spi;
 132         state->vref_reg = devm_regulator_get(&spi->dev, "vref");
 133         if (IS_ERR(state->vref_reg)) {
 134                 dev_err(&spi->dev, "Vref regulator not specified\n");
 135                 return PTR_ERR(state->vref_reg);
 136         }
 137 
 138         ret = regulator_enable(state->vref_reg);
 139         if (ret) {
 140                 dev_err(&spi->dev, "Failed to enable vref regulator: %d\n",
 141                                 ret);
 142                 return ret;
 143         }
 144 
 145         ret = regulator_get_voltage(state->vref_reg);
 146         if (ret < 0) {
 147                 dev_err(&spi->dev, "Failed to read vref regulator: %d\n",
 148                                 ret);
 149                 goto error_disable_reg;
 150         }
 151         state->vref_mv = ret / 1000;
 152 
 153         spi_set_drvdata(spi, indio_dev);
 154         id = spi_get_device_id(spi);
 155         indio_dev->dev.parent = &spi->dev;
 156         indio_dev->info = &mcp4922_info;
 157         indio_dev->modes = INDIO_DIRECT_MODE;
 158         indio_dev->channels = mcp4922_channels[id->driver_data];
 159         indio_dev->num_channels = MCP4922_NUM_CHANNELS;
 160         indio_dev->name = id->name;
 161 
 162         ret = iio_device_register(indio_dev);
 163         if (ret) {
 164                 dev_err(&spi->dev, "Failed to register iio device: %d\n",
 165                                 ret);
 166                 goto error_disable_reg;
 167         }
 168 
 169         return 0;
 170 
 171 error_disable_reg:
 172         regulator_disable(state->vref_reg);
 173 
 174         return ret;
 175 }
 176 
 177 static int mcp4922_remove(struct spi_device *spi)
 178 {
 179         struct iio_dev *indio_dev = spi_get_drvdata(spi);
 180         struct mcp4922_state *state;
 181 
 182         iio_device_unregister(indio_dev);
 183         state = iio_priv(indio_dev);
 184         regulator_disable(state->vref_reg);
 185 
 186         return 0;
 187 }
 188 
 189 static const struct spi_device_id mcp4922_id[] = {
 190         {"mcp4902", ID_MCP4902},
 191         {"mcp4912", ID_MCP4912},
 192         {"mcp4922", ID_MCP4922},
 193         {}
 194 };
 195 MODULE_DEVICE_TABLE(spi, mcp4922_id);
 196 
 197 static struct spi_driver mcp4922_driver = {
 198         .driver = {
 199                    .name = "mcp4922",
 200                    },
 201         .probe = mcp4922_probe,
 202         .remove = mcp4922_remove,
 203         .id_table = mcp4922_id,
 204 };
 205 module_spi_driver(mcp4922_driver);
 206 
 207 MODULE_AUTHOR("Michael Welling <mwelling@ieee.org>");
 208 MODULE_DESCRIPTION("Microchip MCP4902, MCP4912, MCP4922 DAC");
 209 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */