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