195 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Maxim Integrated MAX5481-MAX5484 digital potentiometer driver4 * Copyright 2016 Rockwell Collins5 *6 * Datasheet:7 * https://datasheets.maximintegrated.com/en/ds/MAX5481-MAX5484.pdf8 */9 10#include <linux/iio/iio.h>11#include <linux/iio/sysfs.h>12#include <linux/module.h>13#include <linux/mod_devicetable.h>14#include <linux/property.h>15#include <linux/spi/spi.h>16 17/* write wiper reg */18#define MAX5481_WRITE_WIPER (0 << 4)19/* copy wiper reg to NV reg */20#define MAX5481_COPY_AB_TO_NV (2 << 4)21/* copy NV reg to wiper reg */22#define MAX5481_COPY_NV_TO_AB (3 << 4)23 24#define MAX5481_MAX_POS 102325 26enum max5481_variant {27 max5481,28 max5482,29 max5483,30 max5484,31};32 33struct max5481_cfg {34 int kohms;35};36 37static const struct max5481_cfg max5481_cfg[] = {38 [max5481] = { .kohms = 10, },39 [max5482] = { .kohms = 50, },40 [max5483] = { .kohms = 10, },41 [max5484] = { .kohms = 50, },42};43 44struct max5481_data {45 struct spi_device *spi;46 const struct max5481_cfg *cfg;47 u8 msg[3] __aligned(IIO_DMA_MINALIGN);48};49 50#define MAX5481_CHANNEL { \51 .type = IIO_RESISTANCE, \52 .indexed = 1, \53 .output = 1, \54 .channel = 0, \55 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \56 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \57}58 59static const struct iio_chan_spec max5481_channels[] = {60 MAX5481_CHANNEL,61};62 63static int max5481_write_cmd(struct max5481_data *data, u8 cmd, u16 val)64{65 struct spi_device *spi = data->spi;66 67 data->msg[0] = cmd;68 69 switch (cmd) {70 case MAX5481_WRITE_WIPER:71 data->msg[1] = val >> 2;72 data->msg[2] = (val & 0x3) << 6;73 return spi_write(spi, data->msg, 3);74 75 case MAX5481_COPY_AB_TO_NV:76 case MAX5481_COPY_NV_TO_AB:77 return spi_write(spi, data->msg, 1);78 79 default:80 return -EIO;81 }82}83 84static int max5481_read_raw(struct iio_dev *indio_dev,85 struct iio_chan_spec const *chan,86 int *val, int *val2, long mask)87{88 struct max5481_data *data = iio_priv(indio_dev);89 90 if (mask != IIO_CHAN_INFO_SCALE)91 return -EINVAL;92 93 *val = 1000 * data->cfg->kohms;94 *val2 = MAX5481_MAX_POS;95 96 return IIO_VAL_FRACTIONAL;97}98 99static int max5481_write_raw(struct iio_dev *indio_dev,100 struct iio_chan_spec const *chan,101 int val, int val2, long mask)102{103 struct max5481_data *data = iio_priv(indio_dev);104 105 if (mask != IIO_CHAN_INFO_RAW)106 return -EINVAL;107 108 if (val < 0 || val > MAX5481_MAX_POS)109 return -EINVAL;110 111 return max5481_write_cmd(data, MAX5481_WRITE_WIPER, val);112}113 114static const struct iio_info max5481_info = {115 .read_raw = max5481_read_raw,116 .write_raw = max5481_write_raw,117};118 119static const struct of_device_id max5481_match[] = {120 { .compatible = "maxim,max5481", .data = &max5481_cfg[max5481] },121 { .compatible = "maxim,max5482", .data = &max5481_cfg[max5482] },122 { .compatible = "maxim,max5483", .data = &max5481_cfg[max5483] },123 { .compatible = "maxim,max5484", .data = &max5481_cfg[max5484] },124 { }125};126MODULE_DEVICE_TABLE(of, max5481_match);127 128static void max5481_wiper_save(void *data)129{130 max5481_write_cmd(data, MAX5481_COPY_AB_TO_NV, 0);131}132 133static int max5481_probe(struct spi_device *spi)134{135 struct iio_dev *indio_dev;136 struct max5481_data *data;137 const struct spi_device_id *id = spi_get_device_id(spi);138 int ret;139 140 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data));141 if (!indio_dev)142 return -ENOMEM;143 144 data = iio_priv(indio_dev);145 146 data->spi = spi;147 148 data->cfg = device_get_match_data(&spi->dev);149 if (!data->cfg)150 data->cfg = &max5481_cfg[id->driver_data];151 152 indio_dev->name = id->name;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 ret = devm_add_action(&spi->dev, max5481_wiper_save, data);166 if (ret < 0)167 return ret;168 169 return devm_iio_device_register(&spi->dev, indio_dev);170}171 172static const struct spi_device_id max5481_id_table[] = {173 { "max5481", max5481 },174 { "max5482", max5482 },175 { "max5483", max5483 },176 { "max5484", max5484 },177 { }178};179MODULE_DEVICE_TABLE(spi, max5481_id_table);180 181static struct spi_driver max5481_driver = {182 .driver = {183 .name = "max5481",184 .of_match_table = max5481_match,185 },186 .probe = max5481_probe,187 .id_table = max5481_id_table,188};189 190module_spi_driver(max5481_driver);191 192MODULE_AUTHOR("Maury Anderson <maury.anderson@rockwellcollins.com>");193MODULE_DESCRIPTION("max5481 SPI driver");194MODULE_LICENSE("GPL v2");195