root/drivers/iio/potentiometer/max5481.c

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

DEFINITIONS

This source file includes following definitions.
  1. max5481_write_cmd
  2. max5481_read_raw
  3. max5481_write_raw
  4. max5481_probe
  5. max5481_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Maxim Integrated MAX5481-MAX5484 digital potentiometer driver
   4  * Copyright 2016 Rockwell Collins
   5  *
   6  * Datasheet:
   7  * http://datasheets.maximintegrated.com/en/ds/MAX5481-MAX5484.pdf
   8  */
   9 
  10 #include <linux/acpi.h>
  11 #include <linux/iio/iio.h>
  12 #include <linux/iio/sysfs.h>
  13 #include <linux/module.h>
  14 #include <linux/of.h>
  15 #include <linux/of_device.h>
  16 #include <linux/spi/spi.h>
  17 
  18 /* write wiper reg */
  19 #define MAX5481_WRITE_WIPER (0 << 4)
  20 /* copy wiper reg to NV reg */
  21 #define MAX5481_COPY_AB_TO_NV (2 << 4)
  22 /* copy NV reg to wiper reg */
  23 #define MAX5481_COPY_NV_TO_AB (3 << 4)
  24 
  25 #define MAX5481_MAX_POS    1023
  26 
  27 enum max5481_variant {
  28         max5481,
  29         max5482,
  30         max5483,
  31         max5484,
  32 };
  33 
  34 struct max5481_cfg {
  35         int kohms;
  36 };
  37 
  38 static const struct max5481_cfg max5481_cfg[] = {
  39         [max5481] = { .kohms =  10, },
  40         [max5482] = { .kohms =  50, },
  41         [max5483] = { .kohms =  10, },
  42         [max5484] = { .kohms =  50, },
  43 };
  44 
  45 struct max5481_data {
  46         struct spi_device *spi;
  47         const struct max5481_cfg *cfg;
  48         u8 msg[3] ____cacheline_aligned;
  49 };
  50 
  51 #define MAX5481_CHANNEL {                                       \
  52         .type = IIO_RESISTANCE,                                 \
  53         .indexed = 1,                                           \
  54         .output = 1,                                            \
  55         .channel = 0,                                           \
  56         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
  57         .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
  58 }
  59 
  60 static const struct iio_chan_spec max5481_channels[] = {
  61         MAX5481_CHANNEL,
  62 };
  63 
  64 static int max5481_write_cmd(struct max5481_data *data, u8 cmd, u16 val)
  65 {
  66         struct spi_device *spi = data->spi;
  67 
  68         data->msg[0] = cmd;
  69 
  70         switch (cmd) {
  71         case MAX5481_WRITE_WIPER:
  72                 data->msg[1] = val >> 2;
  73                 data->msg[2] = (val & 0x3) << 6;
  74                 return spi_write(spi, data->msg, 3);
  75 
  76         case MAX5481_COPY_AB_TO_NV:
  77         case MAX5481_COPY_NV_TO_AB:
  78                 return spi_write(spi, data->msg, 1);
  79 
  80         default:
  81                 return -EIO;
  82         }
  83 }
  84 
  85 static int max5481_read_raw(struct iio_dev *indio_dev,
  86                 struct iio_chan_spec const *chan,
  87                 int *val, int *val2, long mask)
  88 {
  89         struct max5481_data *data = iio_priv(indio_dev);
  90 
  91         if (mask != IIO_CHAN_INFO_SCALE)
  92                 return -EINVAL;
  93 
  94         *val = 1000 * data->cfg->kohms;
  95         *val2 = MAX5481_MAX_POS;
  96 
  97         return IIO_VAL_FRACTIONAL;
  98 }
  99 
 100 static int max5481_write_raw(struct iio_dev *indio_dev,
 101                 struct iio_chan_spec const *chan,
 102                 int val, int val2, long mask)
 103 {
 104         struct max5481_data *data = iio_priv(indio_dev);
 105 
 106         if (mask != IIO_CHAN_INFO_RAW)
 107                 return -EINVAL;
 108 
 109         if (val < 0 || val > MAX5481_MAX_POS)
 110                 return -EINVAL;
 111 
 112         return max5481_write_cmd(data, MAX5481_WRITE_WIPER, val);
 113 }
 114 
 115 static const struct iio_info max5481_info = {
 116         .read_raw = max5481_read_raw,
 117         .write_raw = max5481_write_raw,
 118 };
 119 
 120 #if defined(CONFIG_OF)
 121 static const struct of_device_id max5481_match[] = {
 122         { .compatible = "maxim,max5481", .data = &max5481_cfg[max5481] },
 123         { .compatible = "maxim,max5482", .data = &max5481_cfg[max5482] },
 124         { .compatible = "maxim,max5483", .data = &max5481_cfg[max5483] },
 125         { .compatible = "maxim,max5484", .data = &max5481_cfg[max5484] },
 126         { }
 127 };
 128 MODULE_DEVICE_TABLE(of, max5481_match);
 129 #endif
 130 
 131 static int max5481_probe(struct spi_device *spi)
 132 {
 133         struct iio_dev *indio_dev;
 134         struct max5481_data *data;
 135         const struct spi_device_id *id = spi_get_device_id(spi);
 136         int ret;
 137 
 138         indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data));
 139         if (!indio_dev)
 140                 return -ENOMEM;
 141 
 142         dev_set_drvdata(&spi->dev, indio_dev);
 143         data = iio_priv(indio_dev);
 144 
 145         data->spi = spi;
 146 
 147         data->cfg = of_device_get_match_data(&spi->dev);
 148         if (!data->cfg)
 149                 data->cfg = &max5481_cfg[id->driver_data];
 150 
 151         indio_dev->name = id->name;
 152         indio_dev->dev.parent = &spi->dev;
 153         indio_dev->modes = INDIO_DIRECT_MODE;
 154 
 155         /* variant specific configuration */
 156         indio_dev->info = &max5481_info;
 157         indio_dev->channels = max5481_channels;
 158         indio_dev->num_channels = ARRAY_SIZE(max5481_channels);
 159 
 160         /* restore wiper from NV */
 161         ret = max5481_write_cmd(data, MAX5481_COPY_NV_TO_AB, 0);
 162         if (ret < 0)
 163                 return ret;
 164 
 165         return iio_device_register(indio_dev);
 166 }
 167 
 168 static int max5481_remove(struct spi_device *spi)
 169 {
 170         struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev);
 171         struct max5481_data *data = iio_priv(indio_dev);
 172 
 173         iio_device_unregister(indio_dev);
 174 
 175         /* save wiper reg to NV reg */
 176         return max5481_write_cmd(data, MAX5481_COPY_AB_TO_NV, 0);
 177 }
 178 
 179 static const struct spi_device_id max5481_id_table[] = {
 180         { "max5481", max5481 },
 181         { "max5482", max5482 },
 182         { "max5483", max5483 },
 183         { "max5484", max5484 },
 184         { }
 185 };
 186 MODULE_DEVICE_TABLE(spi, max5481_id_table);
 187 
 188 #if defined(CONFIG_ACPI)
 189 static const struct acpi_device_id max5481_acpi_match[] = {
 190         { "max5481", max5481 },
 191         { "max5482", max5482 },
 192         { "max5483", max5483 },
 193         { "max5484", max5484 },
 194         { }
 195 };
 196 MODULE_DEVICE_TABLE(acpi, max5481_acpi_match);
 197 #endif
 198 
 199 static struct spi_driver max5481_driver = {
 200         .driver = {
 201                 .name  = "max5481",
 202                 .of_match_table = of_match_ptr(max5481_match),
 203                 .acpi_match_table = ACPI_PTR(max5481_acpi_match),
 204         },
 205         .probe = max5481_probe,
 206         .remove = max5481_remove,
 207         .id_table = max5481_id_table,
 208 };
 209 
 210 module_spi_driver(max5481_driver);
 211 
 212 MODULE_AUTHOR("Maury Anderson <maury.anderson@rockwellcollins.com>");
 213 MODULE_DESCRIPTION("max5481 SPI driver");
 214 MODULE_LICENSE("GPL v2");

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