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