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