158 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * max5487.c - Support for MAX5487, MAX5488, MAX5489 digital potentiometers4 *5 * Copyright (C) 2016 Cristina-Gabriela Moraru <cristina.moraru09@gmail.com>6 */7#include <linux/module.h>8#include <linux/mod_devicetable.h>9#include <linux/spi/spi.h>10 11#include <linux/iio/sysfs.h>12#include <linux/iio/iio.h>13 14#define MAX5487_WRITE_WIPER_A (0x01 << 8)15#define MAX5487_WRITE_WIPER_B (0x02 << 8)16 17/* copy both wiper regs to NV regs */18#define MAX5487_COPY_AB_TO_NV (0x23 << 8)19/* copy both NV regs to wiper regs */20#define MAX5487_COPY_NV_TO_AB (0x33 << 8)21 22#define MAX5487_MAX_POS 25523 24struct max5487_data {25 struct spi_device *spi;26 int kohms;27};28 29#define MAX5487_CHANNEL(ch, addr) { \30 .type = IIO_RESISTANCE, \31 .indexed = 1, \32 .output = 1, \33 .channel = ch, \34 .address = addr, \35 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \36 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \37}38 39static const struct iio_chan_spec max5487_channels[] = {40 MAX5487_CHANNEL(0, MAX5487_WRITE_WIPER_A),41 MAX5487_CHANNEL(1, MAX5487_WRITE_WIPER_B),42};43 44static int max5487_write_cmd(struct spi_device *spi, u16 cmd)45{46 return spi_write(spi, (const void *) &cmd, sizeof(u16));47}48 49static int max5487_read_raw(struct iio_dev *indio_dev,50 struct iio_chan_spec const *chan,51 int *val, int *val2, long mask)52{53 struct max5487_data *data = iio_priv(indio_dev);54 55 if (mask != IIO_CHAN_INFO_SCALE)56 return -EINVAL;57 58 *val = 1000 * data->kohms;59 *val2 = MAX5487_MAX_POS;60 61 return IIO_VAL_FRACTIONAL;62}63 64static int max5487_write_raw(struct iio_dev *indio_dev,65 struct iio_chan_spec const *chan,66 int val, int val2, long mask)67{68 struct max5487_data *data = iio_priv(indio_dev);69 70 if (mask != IIO_CHAN_INFO_RAW)71 return -EINVAL;72 73 if (val < 0 || val > MAX5487_MAX_POS)74 return -EINVAL;75 76 return max5487_write_cmd(data->spi, chan->address | val);77}78 79static const struct iio_info max5487_info = {80 .read_raw = max5487_read_raw,81 .write_raw = max5487_write_raw,82};83 84static int max5487_spi_probe(struct spi_device *spi)85{86 struct iio_dev *indio_dev;87 struct max5487_data *data;88 const struct spi_device_id *id = spi_get_device_id(spi);89 int ret;90 91 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data));92 if (!indio_dev)93 return -ENOMEM;94 95 spi_set_drvdata(spi, indio_dev);96 data = iio_priv(indio_dev);97 98 data->spi = spi;99 data->kohms = id->driver_data;100 101 indio_dev->info = &max5487_info;102 indio_dev->name = id->name;103 indio_dev->modes = INDIO_DIRECT_MODE;104 indio_dev->channels = max5487_channels;105 indio_dev->num_channels = ARRAY_SIZE(max5487_channels);106 107 /* restore both wiper regs from NV regs */108 ret = max5487_write_cmd(data->spi, MAX5487_COPY_NV_TO_AB);109 if (ret < 0)110 return ret;111 112 return iio_device_register(indio_dev);113}114 115static void max5487_spi_remove(struct spi_device *spi)116{117 struct iio_dev *indio_dev = spi_get_drvdata(spi);118 int ret;119 120 iio_device_unregister(indio_dev);121 122 /* save both wiper regs to NV regs */123 ret = max5487_write_cmd(spi, MAX5487_COPY_AB_TO_NV);124 if (ret)125 dev_warn(&spi->dev, "Failed to save wiper regs to NV regs\n");126}127 128static const struct spi_device_id max5487_id[] = {129 { "MAX5487", 10 },130 { "MAX5488", 50 },131 { "MAX5489", 100 },132 { }133};134MODULE_DEVICE_TABLE(spi, max5487_id);135 136static const struct acpi_device_id max5487_acpi_match[] = {137 { "MAX5487", 10 },138 { "MAX5488", 50 },139 { "MAX5489", 100 },140 { },141};142MODULE_DEVICE_TABLE(acpi, max5487_acpi_match);143 144static struct spi_driver max5487_driver = {145 .driver = {146 .name = "max5487",147 .acpi_match_table = max5487_acpi_match,148 },149 .id_table = max5487_id,150 .probe = max5487_spi_probe,151 .remove = max5487_spi_remove152};153module_spi_driver(max5487_driver);154 155MODULE_AUTHOR("Cristina-Gabriela Moraru <cristina.moraru09@gmail.com>");156MODULE_DESCRIPTION("max5487 SPI driver");157MODULE_LICENSE("GPL v2");158