1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (C) 2016 - Marcin Malagowski <mrc@bourne.st> |
4 | */ |
5 | #include <linux/delay.h> |
6 | #include <linux/device.h> |
7 | #include <linux/err.h> |
8 | #include <linux/i2c.h> |
9 | #include <linux/io.h> |
10 | #include <linux/kernel.h> |
11 | #include <linux/module.h> |
12 | #include <linux/iio/iio.h> |
13 | |
14 | #define ABP060MG_ERROR_MASK 0xC000 |
15 | #define ABP060MG_RESP_TIME_MS 40 |
16 | #define ABP060MG_MIN_COUNTS 1638 /* = 0x0666 (10% of u14) */ |
17 | #define ABP060MG_MAX_COUNTS 14745 /* = 0x3999 (90% of u14) */ |
18 | #define ABP060MG_NUM_COUNTS (ABP060MG_MAX_COUNTS - ABP060MG_MIN_COUNTS) |
19 | |
20 | enum abp_variant { |
21 | /* gage [kPa] */ |
22 | ABP006KG, ABP010KG, ABP016KG, ABP025KG, ABP040KG, ABP060KG, ABP100KG, |
23 | ABP160KG, ABP250KG, ABP400KG, ABP600KG, ABP001GG, |
24 | /* differential [kPa] */ |
25 | ABP006KD, ABP010KD, ABP016KD, ABP025KD, ABP040KD, ABP060KD, ABP100KD, |
26 | ABP160KD, ABP250KD, ABP400KD, |
27 | /* gage [psi] */ |
28 | ABP001PG, ABP005PG, ABP015PG, ABP030PG, ABP060PG, ABP100PG, ABP150PG, |
29 | /* differential [psi] */ |
30 | ABP001PD, ABP005PD, ABP015PD, ABP030PD, ABP060PD, |
31 | }; |
32 | |
33 | struct abp_config { |
34 | int min; |
35 | int max; |
36 | }; |
37 | |
38 | static struct abp_config abp_config[] = { |
39 | /* mbar & kPa variants */ |
40 | [ABP006KG] = { .min = 0, .max = 6000 }, |
41 | [ABP010KG] = { .min = 0, .max = 10000 }, |
42 | [ABP016KG] = { .min = 0, .max = 16000 }, |
43 | [ABP025KG] = { .min = 0, .max = 25000 }, |
44 | [ABP040KG] = { .min = 0, .max = 40000 }, |
45 | [ABP060KG] = { .min = 0, .max = 60000 }, |
46 | [ABP100KG] = { .min = 0, .max = 100000 }, |
47 | [ABP160KG] = { .min = 0, .max = 160000 }, |
48 | [ABP250KG] = { .min = 0, .max = 250000 }, |
49 | [ABP400KG] = { .min = 0, .max = 400000 }, |
50 | [ABP600KG] = { .min = 0, .max = 600000 }, |
51 | [ABP001GG] = { .min = 0, .max = 1000000 }, |
52 | [ABP006KD] = { .min = -6000, .max = 6000 }, |
53 | [ABP010KD] = { .min = -10000, .max = 10000 }, |
54 | [ABP016KD] = { .min = -16000, .max = 16000 }, |
55 | [ABP025KD] = { .min = -25000, .max = 25000 }, |
56 | [ABP040KD] = { .min = -40000, .max = 40000 }, |
57 | [ABP060KD] = { .min = -60000, .max = 60000 }, |
58 | [ABP100KD] = { .min = -100000, .max = 100000 }, |
59 | [ABP160KD] = { .min = -160000, .max = 160000 }, |
60 | [ABP250KD] = { .min = -250000, .max = 250000 }, |
61 | [ABP400KD] = { .min = -400000, .max = 400000 }, |
62 | /* psi variants (1 psi ~ 6895 Pa) */ |
63 | [ABP001PG] = { .min = 0, .max = 6985 }, |
64 | [ABP005PG] = { .min = 0, .max = 34474 }, |
65 | [ABP015PG] = { .min = 0, .max = 103421 }, |
66 | [ABP030PG] = { .min = 0, .max = 206843 }, |
67 | [ABP060PG] = { .min = 0, .max = 413686 }, |
68 | [ABP100PG] = { .min = 0, .max = 689476 }, |
69 | [ABP150PG] = { .min = 0, .max = 1034214 }, |
70 | [ABP001PD] = { .min = -6895, .max = 6895 }, |
71 | [ABP005PD] = { .min = -34474, .max = 34474 }, |
72 | [ABP015PD] = { .min = -103421, .max = 103421 }, |
73 | [ABP030PD] = { .min = -206843, .max = 206843 }, |
74 | [ABP060PD] = { .min = -413686, .max = 413686 }, |
75 | }; |
76 | |
77 | struct abp_state { |
78 | struct i2c_client *client; |
79 | struct mutex lock; |
80 | |
81 | /* |
82 | * bus-dependent MEASURE_REQUEST length. |
83 | * If no SMBUS_QUICK support, need to send dummy byte |
84 | */ |
85 | int mreq_len; |
86 | |
87 | /* model-dependent values (calculated on probe) */ |
88 | int scale; |
89 | int offset; |
90 | }; |
91 | |
92 | static const struct iio_chan_spec abp060mg_channels[] = { |
93 | { |
94 | .type = IIO_PRESSURE, |
95 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
96 | BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE), |
97 | }, |
98 | }; |
99 | |
100 | static int abp060mg_get_measurement(struct abp_state *state, int *val) |
101 | { |
102 | struct i2c_client *client = state->client; |
103 | __be16 buf[2]; |
104 | u16 pressure; |
105 | int ret; |
106 | |
107 | buf[0] = 0; |
108 | ret = i2c_master_send(client, buf: (u8 *)&buf, count: state->mreq_len); |
109 | if (ret < 0) |
110 | return ret; |
111 | |
112 | msleep_interruptible(ABP060MG_RESP_TIME_MS); |
113 | |
114 | ret = i2c_master_recv(client, buf: (u8 *)&buf, count: sizeof(buf)); |
115 | if (ret < 0) |
116 | return ret; |
117 | |
118 | pressure = be16_to_cpu(buf[0]); |
119 | if (pressure & ABP060MG_ERROR_MASK) |
120 | return -EIO; |
121 | |
122 | if (pressure < ABP060MG_MIN_COUNTS || pressure > ABP060MG_MAX_COUNTS) |
123 | return -EIO; |
124 | |
125 | *val = pressure; |
126 | |
127 | return IIO_VAL_INT; |
128 | } |
129 | |
130 | static int abp060mg_read_raw(struct iio_dev *indio_dev, |
131 | struct iio_chan_spec const *chan, int *val, |
132 | int *val2, long mask) |
133 | { |
134 | struct abp_state *state = iio_priv(indio_dev); |
135 | int ret; |
136 | |
137 | mutex_lock(&state->lock); |
138 | |
139 | switch (mask) { |
140 | case IIO_CHAN_INFO_RAW: |
141 | ret = abp060mg_get_measurement(state, val); |
142 | break; |
143 | case IIO_CHAN_INFO_OFFSET: |
144 | *val = state->offset; |
145 | ret = IIO_VAL_INT; |
146 | break; |
147 | case IIO_CHAN_INFO_SCALE: |
148 | *val = state->scale; |
149 | *val2 = ABP060MG_NUM_COUNTS * 1000; /* to kPa */ |
150 | ret = IIO_VAL_FRACTIONAL; |
151 | break; |
152 | default: |
153 | ret = -EINVAL; |
154 | break; |
155 | } |
156 | |
157 | mutex_unlock(lock: &state->lock); |
158 | return ret; |
159 | } |
160 | |
161 | static const struct iio_info abp060mg_info = { |
162 | .read_raw = abp060mg_read_raw, |
163 | }; |
164 | |
165 | static void abp060mg_init_device(struct iio_dev *indio_dev, unsigned long id) |
166 | { |
167 | struct abp_state *state = iio_priv(indio_dev); |
168 | struct abp_config *cfg = &abp_config[id]; |
169 | |
170 | state->scale = cfg->max - cfg->min; |
171 | state->offset = -ABP060MG_MIN_COUNTS; |
172 | |
173 | if (cfg->min < 0) /* differential */ |
174 | state->offset -= ABP060MG_NUM_COUNTS >> 1; |
175 | } |
176 | |
177 | static int abp060mg_probe(struct i2c_client *client) |
178 | { |
179 | const struct i2c_device_id *id = i2c_client_get_device_id(client); |
180 | struct iio_dev *indio_dev; |
181 | struct abp_state *state; |
182 | unsigned long cfg_id = id->driver_data; |
183 | |
184 | indio_dev = devm_iio_device_alloc(parent: &client->dev, sizeof_priv: sizeof(*state)); |
185 | if (!indio_dev) |
186 | return -ENOMEM; |
187 | |
188 | state = iio_priv(indio_dev); |
189 | i2c_set_clientdata(client, data: state); |
190 | state->client = client; |
191 | |
192 | if (!i2c_check_functionality(adap: client->adapter, I2C_FUNC_SMBUS_QUICK)) |
193 | state->mreq_len = 1; |
194 | |
195 | abp060mg_init_device(indio_dev, id: cfg_id); |
196 | |
197 | indio_dev->name = dev_name(dev: &client->dev); |
198 | indio_dev->modes = INDIO_DIRECT_MODE; |
199 | indio_dev->info = &abp060mg_info; |
200 | |
201 | indio_dev->channels = abp060mg_channels; |
202 | indio_dev->num_channels = ARRAY_SIZE(abp060mg_channels); |
203 | |
204 | mutex_init(&state->lock); |
205 | |
206 | return devm_iio_device_register(&client->dev, indio_dev); |
207 | } |
208 | |
209 | static const struct i2c_device_id abp060mg_id_table[] = { |
210 | /* mbar & kPa variants (abp060m [60 mbar] == abp006k [6 kPa]) */ |
211 | /* gage: */ |
212 | { "abp060mg" , ABP006KG }, { "abp006kg" , ABP006KG }, |
213 | { "abp100mg" , ABP010KG }, { "abp010kg" , ABP010KG }, |
214 | { "abp160mg" , ABP016KG }, { "abp016kg" , ABP016KG }, |
215 | { "abp250mg" , ABP025KG }, { "abp025kg" , ABP025KG }, |
216 | { "abp400mg" , ABP040KG }, { "abp040kg" , ABP040KG }, |
217 | { "abp600mg" , ABP060KG }, { "abp060kg" , ABP060KG }, |
218 | { "abp001bg" , ABP100KG }, { "abp100kg" , ABP100KG }, |
219 | { "abp1_6bg" , ABP160KG }, { "abp160kg" , ABP160KG }, |
220 | { "abp2_5bg" , ABP250KG }, { "abp250kg" , ABP250KG }, |
221 | { "abp004bg" , ABP400KG }, { "abp400kg" , ABP400KG }, |
222 | { "abp006bg" , ABP600KG }, { "abp600kg" , ABP600KG }, |
223 | { "abp010bg" , ABP001GG }, { "abp001gg" , ABP001GG }, |
224 | /* differential: */ |
225 | { "abp060md" , ABP006KD }, { "abp006kd" , ABP006KD }, |
226 | { "abp100md" , ABP010KD }, { "abp010kd" , ABP010KD }, |
227 | { "abp160md" , ABP016KD }, { "abp016kd" , ABP016KD }, |
228 | { "abp250md" , ABP025KD }, { "abp025kd" , ABP025KD }, |
229 | { "abp400md" , ABP040KD }, { "abp040kd" , ABP040KD }, |
230 | { "abp600md" , ABP060KD }, { "abp060kd" , ABP060KD }, |
231 | { "abp001bd" , ABP100KD }, { "abp100kd" , ABP100KD }, |
232 | { "abp1_6bd" , ABP160KD }, { "abp160kd" , ABP160KD }, |
233 | { "abp2_5bd" , ABP250KD }, { "abp250kd" , ABP250KD }, |
234 | { "abp004bd" , ABP400KD }, { "abp400kd" , ABP400KD }, |
235 | /* psi variants */ |
236 | /* gage: */ |
237 | { "abp001pg" , ABP001PG }, |
238 | { "abp005pg" , ABP005PG }, |
239 | { "abp015pg" , ABP015PG }, |
240 | { "abp030pg" , ABP030PG }, |
241 | { "abp060pg" , ABP060PG }, |
242 | { "abp100pg" , ABP100PG }, |
243 | { "abp150pg" , ABP150PG }, |
244 | /* differential: */ |
245 | { "abp001pd" , ABP001PD }, |
246 | { "abp005pd" , ABP005PD }, |
247 | { "abp015pd" , ABP015PD }, |
248 | { "abp030pd" , ABP030PD }, |
249 | { "abp060pd" , ABP060PD }, |
250 | { /* empty */ }, |
251 | }; |
252 | MODULE_DEVICE_TABLE(i2c, abp060mg_id_table); |
253 | |
254 | static struct i2c_driver abp060mg_driver = { |
255 | .driver = { |
256 | .name = "abp060mg" , |
257 | }, |
258 | .probe = abp060mg_probe, |
259 | .id_table = abp060mg_id_table, |
260 | }; |
261 | module_i2c_driver(abp060mg_driver); |
262 | |
263 | MODULE_AUTHOR("Marcin Malagowski <mrc@bourne.st>" ); |
264 | MODULE_DESCRIPTION("Honeywell ABP pressure sensor driver" ); |
265 | MODULE_LICENSE("GPL" ); |
266 | |