0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/iio/iio.h>
0011 #include <linux/iio/sysfs.h>
0012 #include <linux/module.h>
0013 #include <linux/mod_devicetable.h>
0014 #include <linux/property.h>
0015 #include <linux/spi/spi.h>
0016
0017
0018 #define MAX5481_WRITE_WIPER (0 << 4)
0019
0020 #define MAX5481_COPY_AB_TO_NV (2 << 4)
0021
0022 #define MAX5481_COPY_NV_TO_AB (3 << 4)
0023
0024 #define MAX5481_MAX_POS 1023
0025
0026 enum max5481_variant {
0027 max5481,
0028 max5482,
0029 max5483,
0030 max5484,
0031 };
0032
0033 struct max5481_cfg {
0034 int kohms;
0035 };
0036
0037 static const struct max5481_cfg max5481_cfg[] = {
0038 [max5481] = { .kohms = 10, },
0039 [max5482] = { .kohms = 50, },
0040 [max5483] = { .kohms = 10, },
0041 [max5484] = { .kohms = 50, },
0042 };
0043
0044 struct max5481_data {
0045 struct spi_device *spi;
0046 const struct max5481_cfg *cfg;
0047 u8 msg[3] __aligned(IIO_DMA_MINALIGN);
0048 };
0049
0050 #define MAX5481_CHANNEL { \
0051 .type = IIO_RESISTANCE, \
0052 .indexed = 1, \
0053 .output = 1, \
0054 .channel = 0, \
0055 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
0056 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
0057 }
0058
0059 static const struct iio_chan_spec max5481_channels[] = {
0060 MAX5481_CHANNEL,
0061 };
0062
0063 static int max5481_write_cmd(struct max5481_data *data, u8 cmd, u16 val)
0064 {
0065 struct spi_device *spi = data->spi;
0066
0067 data->msg[0] = cmd;
0068
0069 switch (cmd) {
0070 case MAX5481_WRITE_WIPER:
0071 data->msg[1] = val >> 2;
0072 data->msg[2] = (val & 0x3) << 6;
0073 return spi_write(spi, data->msg, 3);
0074
0075 case MAX5481_COPY_AB_TO_NV:
0076 case MAX5481_COPY_NV_TO_AB:
0077 return spi_write(spi, data->msg, 1);
0078
0079 default:
0080 return -EIO;
0081 }
0082 }
0083
0084 static int max5481_read_raw(struct iio_dev *indio_dev,
0085 struct iio_chan_spec const *chan,
0086 int *val, int *val2, long mask)
0087 {
0088 struct max5481_data *data = iio_priv(indio_dev);
0089
0090 if (mask != IIO_CHAN_INFO_SCALE)
0091 return -EINVAL;
0092
0093 *val = 1000 * data->cfg->kohms;
0094 *val2 = MAX5481_MAX_POS;
0095
0096 return IIO_VAL_FRACTIONAL;
0097 }
0098
0099 static int max5481_write_raw(struct iio_dev *indio_dev,
0100 struct iio_chan_spec const *chan,
0101 int val, int val2, long mask)
0102 {
0103 struct max5481_data *data = iio_priv(indio_dev);
0104
0105 if (mask != IIO_CHAN_INFO_RAW)
0106 return -EINVAL;
0107
0108 if (val < 0 || val > MAX5481_MAX_POS)
0109 return -EINVAL;
0110
0111 return max5481_write_cmd(data, MAX5481_WRITE_WIPER, val);
0112 }
0113
0114 static const struct iio_info max5481_info = {
0115 .read_raw = max5481_read_raw,
0116 .write_raw = max5481_write_raw,
0117 };
0118
0119 static const struct of_device_id max5481_match[] = {
0120 { .compatible = "maxim,max5481", .data = &max5481_cfg[max5481] },
0121 { .compatible = "maxim,max5482", .data = &max5481_cfg[max5482] },
0122 { .compatible = "maxim,max5483", .data = &max5481_cfg[max5483] },
0123 { .compatible = "maxim,max5484", .data = &max5481_cfg[max5484] },
0124 { }
0125 };
0126 MODULE_DEVICE_TABLE(of, max5481_match);
0127
0128 static void max5481_wiper_save(void *data)
0129 {
0130 max5481_write_cmd(data, MAX5481_COPY_AB_TO_NV, 0);
0131 }
0132
0133 static int max5481_probe(struct spi_device *spi)
0134 {
0135 struct iio_dev *indio_dev;
0136 struct max5481_data *data;
0137 const struct spi_device_id *id = spi_get_device_id(spi);
0138 int ret;
0139
0140 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data));
0141 if (!indio_dev)
0142 return -ENOMEM;
0143
0144 data = iio_priv(indio_dev);
0145
0146 data->spi = spi;
0147
0148 data->cfg = device_get_match_data(&spi->dev);
0149 if (!data->cfg)
0150 data->cfg = &max5481_cfg[id->driver_data];
0151
0152 indio_dev->name = id->name;
0153 indio_dev->modes = INDIO_DIRECT_MODE;
0154
0155
0156 indio_dev->info = &max5481_info;
0157 indio_dev->channels = max5481_channels;
0158 indio_dev->num_channels = ARRAY_SIZE(max5481_channels);
0159
0160
0161 ret = max5481_write_cmd(data, MAX5481_COPY_NV_TO_AB, 0);
0162 if (ret < 0)
0163 return ret;
0164
0165 ret = devm_add_action(&spi->dev, max5481_wiper_save, data);
0166 if (ret < 0)
0167 return ret;
0168
0169 return devm_iio_device_register(&spi->dev, indio_dev);
0170 }
0171
0172 static const struct spi_device_id max5481_id_table[] = {
0173 { "max5481", max5481 },
0174 { "max5482", max5482 },
0175 { "max5483", max5483 },
0176 { "max5484", max5484 },
0177 { }
0178 };
0179 MODULE_DEVICE_TABLE(spi, max5481_id_table);
0180
0181 static struct spi_driver max5481_driver = {
0182 .driver = {
0183 .name = "max5481",
0184 .of_match_table = max5481_match,
0185 },
0186 .probe = max5481_probe,
0187 .id_table = max5481_id_table,
0188 };
0189
0190 module_spi_driver(max5481_driver);
0191
0192 MODULE_AUTHOR("Maury Anderson <maury.anderson@rockwellcollins.com>");
0193 MODULE_DESCRIPTION("max5481 SPI driver");
0194 MODULE_LICENSE("GPL v2");