Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2016 - Marcin Malagowski <mrc@bourne.st>
0004  */
0005 #include <linux/delay.h>
0006 #include <linux/device.h>
0007 #include <linux/err.h>
0008 #include <linux/i2c.h>
0009 #include <linux/io.h>
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/iio/iio.h>
0013 
0014 #define ABP060MG_ERROR_MASK   0xC000
0015 #define ABP060MG_RESP_TIME_MS 40
0016 #define ABP060MG_MIN_COUNTS   1638  /* = 0x0666 (10% of u14) */
0017 #define ABP060MG_MAX_COUNTS   14745 /* = 0x3999 (90% of u14) */
0018 #define ABP060MG_NUM_COUNTS   (ABP060MG_MAX_COUNTS - ABP060MG_MIN_COUNTS)
0019 
0020 enum abp_variant {
0021     /* gage [kPa] */
0022     ABP006KG, ABP010KG, ABP016KG, ABP025KG, ABP040KG, ABP060KG, ABP100KG,
0023     ABP160KG, ABP250KG, ABP400KG, ABP600KG, ABP001GG,
0024     /* differential [kPa] */
0025     ABP006KD, ABP010KD, ABP016KD, ABP025KD, ABP040KD, ABP060KD, ABP100KD,
0026     ABP160KD, ABP250KD, ABP400KD,
0027     /* gage [psi] */
0028     ABP001PG, ABP005PG, ABP015PG, ABP030PG, ABP060PG, ABP100PG, ABP150PG,
0029     /* differential [psi] */
0030     ABP001PD, ABP005PD, ABP015PD, ABP030PD, ABP060PD,
0031 };
0032 
0033 struct abp_config {
0034     int min;
0035     int max;
0036 };
0037 
0038 static struct abp_config abp_config[] = {
0039     /* mbar & kPa variants */
0040     [ABP006KG] = { .min =       0, .max =     6000 },
0041     [ABP010KG] = { .min =       0, .max =    10000 },
0042     [ABP016KG] = { .min =       0, .max =    16000 },
0043     [ABP025KG] = { .min =       0, .max =    25000 },
0044     [ABP040KG] = { .min =       0, .max =    40000 },
0045     [ABP060KG] = { .min =       0, .max =    60000 },
0046     [ABP100KG] = { .min =       0, .max =   100000 },
0047     [ABP160KG] = { .min =       0, .max =   160000 },
0048     [ABP250KG] = { .min =       0, .max =   250000 },
0049     [ABP400KG] = { .min =       0, .max =   400000 },
0050     [ABP600KG] = { .min =       0, .max =   600000 },
0051     [ABP001GG] = { .min =       0, .max =  1000000 },
0052     [ABP006KD] = { .min =   -6000, .max =     6000 },
0053     [ABP010KD] = { .min =  -10000, .max =    10000 },
0054     [ABP016KD] = { .min =  -16000, .max =    16000 },
0055     [ABP025KD] = { .min =  -25000, .max =    25000 },
0056     [ABP040KD] = { .min =  -40000, .max =    40000 },
0057     [ABP060KD] = { .min =  -60000, .max =    60000 },
0058     [ABP100KD] = { .min = -100000, .max =   100000 },
0059     [ABP160KD] = { .min = -160000, .max =   160000 },
0060     [ABP250KD] = { .min = -250000, .max =   250000 },
0061     [ABP400KD] = { .min = -400000, .max =   400000 },
0062     /* psi variants (1 psi ~ 6895 Pa) */
0063     [ABP001PG] = { .min =       0, .max =     6985 },
0064     [ABP005PG] = { .min =       0, .max =    34474 },
0065     [ABP015PG] = { .min =       0, .max =   103421 },
0066     [ABP030PG] = { .min =       0, .max =   206843 },
0067     [ABP060PG] = { .min =       0, .max =   413686 },
0068     [ABP100PG] = { .min =       0, .max =   689476 },
0069     [ABP150PG] = { .min =       0, .max =  1034214 },
0070     [ABP001PD] = { .min =   -6895, .max =     6895 },
0071     [ABP005PD] = { .min =  -34474, .max =    34474 },
0072     [ABP015PD] = { .min = -103421, .max =   103421 },
0073     [ABP030PD] = { .min = -206843, .max =   206843 },
0074     [ABP060PD] = { .min = -413686, .max =   413686 },
0075 };
0076 
0077 struct abp_state {
0078     struct i2c_client *client;
0079     struct mutex lock;
0080 
0081     /*
0082      * bus-dependent MEASURE_REQUEST length.
0083      * If no SMBUS_QUICK support, need to send dummy byte
0084      */
0085     int mreq_len;
0086 
0087     /* model-dependent values (calculated on probe) */
0088     int scale;
0089     int offset;
0090 };
0091 
0092 static const struct iio_chan_spec abp060mg_channels[] = {
0093     {
0094         .type = IIO_PRESSURE,
0095         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0096             BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE),
0097     },
0098 };
0099 
0100 static int abp060mg_get_measurement(struct abp_state *state, int *val)
0101 {
0102     struct i2c_client *client = state->client;
0103     __be16 buf[2];
0104     u16 pressure;
0105     int ret;
0106 
0107     buf[0] = 0;
0108     ret = i2c_master_send(client, (u8 *)&buf, state->mreq_len);
0109     if (ret < 0)
0110         return ret;
0111 
0112     msleep_interruptible(ABP060MG_RESP_TIME_MS);
0113 
0114     ret = i2c_master_recv(client, (u8 *)&buf, sizeof(buf));
0115     if (ret < 0)
0116         return ret;
0117 
0118     pressure = be16_to_cpu(buf[0]);
0119     if (pressure & ABP060MG_ERROR_MASK)
0120         return -EIO;
0121 
0122     if (pressure < ABP060MG_MIN_COUNTS || pressure > ABP060MG_MAX_COUNTS)
0123         return -EIO;
0124 
0125     *val = pressure;
0126 
0127     return IIO_VAL_INT;
0128 }
0129 
0130 static int abp060mg_read_raw(struct iio_dev *indio_dev,
0131             struct iio_chan_spec const *chan, int *val,
0132             int *val2, long mask)
0133 {
0134     struct abp_state *state = iio_priv(indio_dev);
0135     int ret;
0136 
0137     mutex_lock(&state->lock);
0138 
0139     switch (mask) {
0140     case IIO_CHAN_INFO_RAW:
0141         ret = abp060mg_get_measurement(state, val);
0142         break;
0143     case IIO_CHAN_INFO_OFFSET:
0144         *val = state->offset;
0145         ret = IIO_VAL_INT;
0146         break;
0147     case IIO_CHAN_INFO_SCALE:
0148         *val = state->scale;
0149         *val2 = ABP060MG_NUM_COUNTS * 1000; /* to kPa */
0150         ret = IIO_VAL_FRACTIONAL;
0151         break;
0152     default:
0153         ret = -EINVAL;
0154         break;
0155     }
0156 
0157     mutex_unlock(&state->lock);
0158     return ret;
0159 }
0160 
0161 static const struct iio_info abp060mg_info = {
0162     .read_raw = abp060mg_read_raw,
0163 };
0164 
0165 static void abp060mg_init_device(struct iio_dev *indio_dev, unsigned long id)
0166 {
0167     struct abp_state *state = iio_priv(indio_dev);
0168     struct abp_config *cfg = &abp_config[id];
0169 
0170     state->scale = cfg->max - cfg->min;
0171     state->offset = -ABP060MG_MIN_COUNTS;
0172 
0173     if (cfg->min < 0) /* differential */
0174         state->offset -= ABP060MG_NUM_COUNTS >> 1;
0175 }
0176 
0177 static int abp060mg_probe(struct i2c_client *client,
0178             const struct i2c_device_id *id)
0179 {
0180     struct iio_dev *indio_dev;
0181     struct abp_state *state;
0182     unsigned long cfg_id = id->driver_data;
0183 
0184     indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*state));
0185     if (!indio_dev)
0186         return -ENOMEM;
0187 
0188     state = iio_priv(indio_dev);
0189     i2c_set_clientdata(client, state);
0190     state->client = client;
0191 
0192     if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_QUICK))
0193         state->mreq_len = 1;
0194 
0195     abp060mg_init_device(indio_dev, cfg_id);
0196 
0197     indio_dev->name = dev_name(&client->dev);
0198     indio_dev->modes = INDIO_DIRECT_MODE;
0199     indio_dev->info = &abp060mg_info;
0200 
0201     indio_dev->channels = abp060mg_channels;
0202     indio_dev->num_channels = ARRAY_SIZE(abp060mg_channels);
0203 
0204     mutex_init(&state->lock);
0205 
0206     return devm_iio_device_register(&client->dev, indio_dev);
0207 }
0208 
0209 static const struct i2c_device_id abp060mg_id_table[] = {
0210     /* mbar & kPa variants (abp060m [60 mbar] == abp006k [6 kPa]) */
0211     /*    gage: */
0212     { "abp060mg", ABP006KG }, { "abp006kg", ABP006KG },
0213     { "abp100mg", ABP010KG }, { "abp010kg", ABP010KG },
0214     { "abp160mg", ABP016KG }, { "abp016kg", ABP016KG },
0215     { "abp250mg", ABP025KG }, { "abp025kg", ABP025KG },
0216     { "abp400mg", ABP040KG }, { "abp040kg", ABP040KG },
0217     { "abp600mg", ABP060KG }, { "abp060kg", ABP060KG },
0218     { "abp001bg", ABP100KG }, { "abp100kg", ABP100KG },
0219     { "abp1_6bg", ABP160KG }, { "abp160kg", ABP160KG },
0220     { "abp2_5bg", ABP250KG }, { "abp250kg", ABP250KG },
0221     { "abp004bg", ABP400KG }, { "abp400kg", ABP400KG },
0222     { "abp006bg", ABP600KG }, { "abp600kg", ABP600KG },
0223     { "abp010bg", ABP001GG }, { "abp001gg", ABP001GG },
0224     /*    differential: */
0225     { "abp060md", ABP006KD }, { "abp006kd", ABP006KD },
0226     { "abp100md", ABP010KD }, { "abp010kd", ABP010KD },
0227     { "abp160md", ABP016KD }, { "abp016kd", ABP016KD },
0228     { "abp250md", ABP025KD }, { "abp025kd", ABP025KD },
0229     { "abp400md", ABP040KD }, { "abp040kd", ABP040KD },
0230     { "abp600md", ABP060KD }, { "abp060kd", ABP060KD },
0231     { "abp001bd", ABP100KD }, { "abp100kd", ABP100KD },
0232     { "abp1_6bd", ABP160KD }, { "abp160kd", ABP160KD },
0233     { "abp2_5bd", ABP250KD }, { "abp250kd", ABP250KD },
0234     { "abp004bd", ABP400KD }, { "abp400kd", ABP400KD },
0235     /* psi variants */
0236     /*    gage: */
0237     { "abp001pg", ABP001PG },
0238     { "abp005pg", ABP005PG },
0239     { "abp015pg", ABP015PG },
0240     { "abp030pg", ABP030PG },
0241     { "abp060pg", ABP060PG },
0242     { "abp100pg", ABP100PG },
0243     { "abp150pg", ABP150PG },
0244     /*    differential: */
0245     { "abp001pd", ABP001PD },
0246     { "abp005pd", ABP005PD },
0247     { "abp015pd", ABP015PD },
0248     { "abp030pd", ABP030PD },
0249     { "abp060pd", ABP060PD },
0250     { /* empty */ },
0251 };
0252 MODULE_DEVICE_TABLE(i2c, abp060mg_id_table);
0253 
0254 static struct i2c_driver abp060mg_driver = {
0255     .driver = {
0256         .name = "abp060mg",
0257     },
0258     .probe = abp060mg_probe,
0259     .id_table = abp060mg_id_table,
0260 };
0261 module_i2c_driver(abp060mg_driver);
0262 
0263 MODULE_AUTHOR("Marcin Malagowski <mrc@bourne.st>");
0264 MODULE_DESCRIPTION("Honeywell ABP pressure sensor driver");
0265 MODULE_LICENSE("GPL");