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