1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * ltc2497.c - Driver for Analog Devices/Linear Technology LTC2497 ADC |
4 | * |
5 | * Copyright (C) 2017 Analog Devices Inc. |
6 | * |
7 | * Datasheet: http://cds.linear.com/docs/en/datasheet/2497fd.pdf |
8 | */ |
9 | |
10 | #include <linux/i2c.h> |
11 | #include <linux/iio/iio.h> |
12 | #include <linux/iio/driver.h> |
13 | #include <linux/module.h> |
14 | #include <linux/mod_devicetable.h> |
15 | #include <linux/property.h> |
16 | |
17 | #include <asm/unaligned.h> |
18 | |
19 | #include "ltc2497.h" |
20 | |
21 | enum ltc2497_chip_type { |
22 | TYPE_LTC2497, |
23 | TYPE_LTC2499, |
24 | }; |
25 | |
26 | struct ltc2497_driverdata { |
27 | /* this must be the first member */ |
28 | struct ltc2497core_driverdata common_ddata; |
29 | struct i2c_client *client; |
30 | u32 recv_size; |
31 | /* |
32 | * DMA (thus cache coherency maintenance) may require the |
33 | * transfer buffers to live in their own cache lines. |
34 | */ |
35 | union { |
36 | __be32 d32; |
37 | u8 d8[3]; |
38 | } data __aligned(IIO_DMA_MINALIGN); |
39 | }; |
40 | |
41 | static int ltc2497_result_and_measure(struct ltc2497core_driverdata *ddata, |
42 | u8 address, int *val) |
43 | { |
44 | struct ltc2497_driverdata *st = |
45 | container_of(ddata, struct ltc2497_driverdata, common_ddata); |
46 | int ret; |
47 | |
48 | if (val) { |
49 | if (st->recv_size == 3) |
50 | ret = i2c_master_recv(client: st->client, buf: (char *)&st->data.d8, |
51 | count: st->recv_size); |
52 | else |
53 | ret = i2c_master_recv(client: st->client, buf: (char *)&st->data.d32, |
54 | count: st->recv_size); |
55 | if (ret < 0) { |
56 | dev_err(&st->client->dev, "i2c_master_recv failed\n" ); |
57 | return ret; |
58 | } |
59 | |
60 | /* |
61 | * The data format is 16/24 bit 2s complement, but with an upper sign bit on the |
62 | * resolution + 1 position, which is set for positive values only. Given this |
63 | * bit's value, subtracting BIT(resolution + 1) from the ADC's result is |
64 | * equivalent to a sign extension. |
65 | */ |
66 | if (st->recv_size == 3) { |
67 | *val = (get_unaligned_be24(p: st->data.d8) >> 6) |
68 | - BIT(ddata->chip_info->resolution + 1); |
69 | } else { |
70 | *val = (be32_to_cpu(st->data.d32) >> 6) |
71 | - BIT(ddata->chip_info->resolution + 1); |
72 | } |
73 | |
74 | /* |
75 | * The part started a new conversion at the end of the above i2c |
76 | * transfer, so if the address didn't change since the last call |
77 | * everything is fine and we can return early. |
78 | * If not (which should only happen when some sort of bulk |
79 | * conversion is implemented) we have to program the new |
80 | * address. Note that this probably fails as the conversion that |
81 | * was triggered above is like not complete yet and the two |
82 | * operations have to be done in a single transfer. |
83 | */ |
84 | if (ddata->addr_prev == address) |
85 | return 0; |
86 | } |
87 | |
88 | ret = i2c_smbus_write_byte(client: st->client, |
89 | LTC2497_ENABLE | address); |
90 | if (ret) |
91 | dev_err(&st->client->dev, "i2c transfer failed: %pe\n" , |
92 | ERR_PTR(ret)); |
93 | return ret; |
94 | } |
95 | |
96 | static int ltc2497_probe(struct i2c_client *client) |
97 | { |
98 | const struct ltc2497_chip_info *chip_info; |
99 | struct iio_dev *indio_dev; |
100 | struct ltc2497_driverdata *st; |
101 | struct device *dev = &client->dev; |
102 | u32 resolution; |
103 | |
104 | if (!i2c_check_functionality(adap: client->adapter, I2C_FUNC_I2C | |
105 | I2C_FUNC_SMBUS_WRITE_BYTE)) |
106 | return -EOPNOTSUPP; |
107 | |
108 | indio_dev = devm_iio_device_alloc(parent: dev, sizeof_priv: sizeof(*st)); |
109 | if (!indio_dev) |
110 | return -ENOMEM; |
111 | |
112 | st = iio_priv(indio_dev); |
113 | i2c_set_clientdata(client, data: indio_dev); |
114 | st->client = client; |
115 | st->common_ddata.result_and_measure = ltc2497_result_and_measure; |
116 | |
117 | chip_info = i2c_get_match_data(client); |
118 | st->common_ddata.chip_info = chip_info; |
119 | |
120 | resolution = chip_info->resolution; |
121 | st->recv_size = BITS_TO_BYTES(resolution) + 1; |
122 | |
123 | return ltc2497core_probe(dev, indio_dev); |
124 | } |
125 | |
126 | static void ltc2497_remove(struct i2c_client *client) |
127 | { |
128 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
129 | |
130 | ltc2497core_remove(indio_dev); |
131 | } |
132 | |
133 | static const struct ltc2497_chip_info ltc2497_info[] = { |
134 | [TYPE_LTC2497] = { |
135 | .resolution = 16, |
136 | .name = NULL, |
137 | }, |
138 | [TYPE_LTC2499] = { |
139 | .resolution = 24, |
140 | .name = "ltc2499" , |
141 | }, |
142 | }; |
143 | |
144 | static const struct i2c_device_id ltc2497_id[] = { |
145 | { "ltc2497" , (kernel_ulong_t)<c2497_info[TYPE_LTC2497] }, |
146 | { "ltc2499" , (kernel_ulong_t)<c2497_info[TYPE_LTC2499] }, |
147 | { } |
148 | }; |
149 | MODULE_DEVICE_TABLE(i2c, ltc2497_id); |
150 | |
151 | static const struct of_device_id ltc2497_of_match[] = { |
152 | { .compatible = "lltc,ltc2497" , .data = <c2497_info[TYPE_LTC2497] }, |
153 | { .compatible = "lltc,ltc2499" , .data = <c2497_info[TYPE_LTC2499] }, |
154 | {}, |
155 | }; |
156 | MODULE_DEVICE_TABLE(of, ltc2497_of_match); |
157 | |
158 | static struct i2c_driver ltc2497_driver = { |
159 | .driver = { |
160 | .name = "ltc2497" , |
161 | .of_match_table = ltc2497_of_match, |
162 | }, |
163 | .probe = ltc2497_probe, |
164 | .remove = ltc2497_remove, |
165 | .id_table = ltc2497_id, |
166 | }; |
167 | module_i2c_driver(ltc2497_driver); |
168 | |
169 | MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>" ); |
170 | MODULE_DESCRIPTION("Linear Technology LTC2497 ADC driver" ); |
171 | MODULE_LICENSE("GPL v2" ); |
172 | |