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 }; 123 124 #if defined(CONFIG_OF) 125 static const struct of_device_id max5481_match[] = { 126 { .compatible = "maxim,max5481", .data = &max5481_cfg[max5481] }, 127 { .compatible = "maxim,max5482", .data = &max5481_cfg[max5482] }, 128 { .compatible = "maxim,max5483", .data = &max5481_cfg[max5483] }, 129 { .compatible = "maxim,max5484", .data = &max5481_cfg[max5484] }, 130 { } 131 }; 132 MODULE_DEVICE_TABLE(of, max5481_match); 133 #endif 134 135 static int max5481_probe(struct spi_device *spi) 136 { 137 struct iio_dev *indio_dev; 138 struct max5481_data *data; 139 const struct spi_device_id *id = spi_get_device_id(spi); 140 const struct of_device_id *match; 141 int ret; 142 143 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data)); 144 if (!indio_dev) 145 return -ENOMEM; 146 147 dev_set_drvdata(&spi->dev, indio_dev); 148 data = iio_priv(indio_dev); 149 150 data->spi = spi; 151 152 match = of_match_device(of_match_ptr(max5481_match), &spi->dev); 153 if (match) 154 data->cfg = of_device_get_match_data(&spi->dev); 155 else 156 data->cfg = &max5481_cfg[id->driver_data]; 157 158 indio_dev->name = id->name; 159 indio_dev->dev.parent = &spi->dev; 160 indio_dev->modes = INDIO_DIRECT_MODE; 161 162 /* variant specific configuration */ 163 indio_dev->info = &max5481_info; 164 indio_dev->channels = max5481_channels; 165 indio_dev->num_channels = ARRAY_SIZE(max5481_channels); 166 167 /* restore wiper from NV */ 168 ret = max5481_write_cmd(data, MAX5481_COPY_NV_TO_AB, 0); 169 if (ret < 0) 170 return ret; 171 172 return iio_device_register(indio_dev); 173 } 174 175 static int max5481_remove(struct spi_device *spi) 176 { 177 struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev); 178 struct max5481_data *data = iio_priv(indio_dev); 179 180 iio_device_unregister(indio_dev); 181 182 /* save wiper reg to NV reg */ 183 return max5481_write_cmd(data, MAX5481_COPY_AB_TO_NV, 0); 184 } 185 186 static const struct spi_device_id max5481_id_table[] = { 187 { "max5481", max5481 }, 188 { "max5482", max5482 }, 189 { "max5483", max5483 }, 190 { "max5484", max5484 }, 191 { } 192 }; 193 MODULE_DEVICE_TABLE(spi, max5481_id_table); 194 195 #if defined(CONFIG_ACPI) 196 static const struct acpi_device_id max5481_acpi_match[] = { 197 { "max5481", max5481 }, 198 { "max5482", max5482 }, 199 { "max5483", max5483 }, 200 { "max5484", max5484 }, 201 { } 202 }; 203 MODULE_DEVICE_TABLE(acpi, max5481_acpi_match); 204 #endif 205 206 static struct spi_driver max5481_driver = { 207 .driver = { 208 .name = "max5481", 209 .of_match_table = of_match_ptr(max5481_match), 210 .acpi_match_table = ACPI_PTR(max5481_acpi_match), 211 }, 212 .probe = max5481_probe, 213 .remove = max5481_remove, 214 .id_table = max5481_id_table, 215 }; 216 217 module_spi_driver(max5481_driver); 218 219 MODULE_AUTHOR("Maury Anderson <maury.anderson@rockwellcollins.com>"); 220 MODULE_DESCRIPTION("max5481 SPI driver"); 221 MODULE_LICENSE("GPL v2"); 222