^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Maxim Integrated MAX5432-MAX5435 digital potentiometer driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2019 Martin Kaiser <martin@kaiser.cx>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Datasheet:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * https://datasheets.maximintegrated.com/en/ds/MAX5432-MAX5435.pdf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/iio/iio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/limits.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/mod_devicetable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/property.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) /* All chip variants have 32 wiper positions. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define MAX5432_MAX_POS 31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define MAX5432_OHM_50K (50 * 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define MAX5432_OHM_100K (100 * 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* Update the volatile (currently active) setting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define MAX5432_CMD_VREG 0x11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct max5432_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) unsigned long ohm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static const struct iio_chan_spec max5432_channels[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) .type = IIO_RESISTANCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) .indexed = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) .output = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) .channel = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) .address = MAX5432_CMD_VREG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static int max5432_read_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct iio_chan_spec const *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int *val, int *val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct max5432_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (mask != IIO_CHAN_INFO_SCALE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (unlikely(data->ohm > INT_MAX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) *val = data->ohm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) *val2 = MAX5432_MAX_POS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return IIO_VAL_FRACTIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static int max5432_write_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct iio_chan_spec const *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int val, int val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct max5432_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) u8 data_byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (mask != IIO_CHAN_INFO_RAW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (val < 0 || val > MAX5432_MAX_POS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (val2 != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* Wiper position is in bits D7-D3. (D2-D0 are don't care bits.) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) data_byte = val << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return i2c_smbus_write_byte_data(data->client, chan->address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) data_byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static const struct iio_info max5432_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .read_raw = max5432_read_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) .write_raw = max5432_write_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static int max5432_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct device *dev = &client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct iio_dev *indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct max5432_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) indio_dev = devm_iio_device_alloc(dev, sizeof(struct max5432_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (!indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) i2c_set_clientdata(client, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) data->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) data->ohm = (unsigned long)device_get_match_data(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) indio_dev->info = &max5432_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) indio_dev->channels = max5432_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) indio_dev->num_channels = ARRAY_SIZE(max5432_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) indio_dev->name = client->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return devm_iio_device_register(dev, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static const struct of_device_id max5432_dt_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) { .compatible = "maxim,max5432", .data = (void *)MAX5432_OHM_50K },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) { .compatible = "maxim,max5433", .data = (void *)MAX5432_OHM_100K },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) { .compatible = "maxim,max5434", .data = (void *)MAX5432_OHM_50K },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) { .compatible = "maxim,max5435", .data = (void *)MAX5432_OHM_100K },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) MODULE_DEVICE_TABLE(of, max5432_dt_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static struct i2c_driver max5432_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .name = "max5432",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .of_match_table = max5432_dt_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .probe = max5432_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) module_i2c_driver(max5432_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) MODULE_AUTHOR("Martin Kaiser <martin@kaiser.cx>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) MODULE_DESCRIPTION("max5432-max5435 digital potentiometers");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) MODULE_LICENSE("GPL v2");