linux/drivers/iio/proximity/mb1232.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * mb1232.c - Support for MaxBotix I2CXL-MaxSonar-EZ series ultrasonic
   4 *   ranger with i2c interface
   5 * actually tested with mb1232 type
   6 *
   7 * Copyright (c) 2019 Andreas Klinger <ak@it-klinger.de>
   8 *
   9 * For details about the device see:
  10 * https://www.maxbotix.com/documents/I2CXL-MaxSonar-EZ_Datasheet.pdf
  11 */
  12
  13#include <linux/err.h>
  14#include <linux/i2c.h>
  15#include <linux/of_irq.h>
  16#include <linux/delay.h>
  17#include <linux/module.h>
  18#include <linux/bitops.h>
  19#include <linux/iio/iio.h>
  20#include <linux/iio/sysfs.h>
  21#include <linux/iio/buffer.h>
  22#include <linux/iio/trigger_consumer.h>
  23#include <linux/iio/triggered_buffer.h>
  24
  25/* registers of MaxSonar device */
  26#define MB1232_RANGE_COMMAND    0x51    /* Command for reading range */
  27#define MB1232_ADDR_UNLOCK_1    0xAA    /* Command 1 for changing address */
  28#define MB1232_ADDR_UNLOCK_2    0xA5    /* Command 2 for changing address */
  29
  30struct mb1232_data {
  31        struct i2c_client       *client;
  32
  33        struct mutex            lock;
  34
  35        /*
  36         * optionally a gpio can be used to announce when ranging has
  37         * finished
  38         * since we are just using the falling trigger of it we request
  39         * only the interrupt for announcing when data is ready to be read
  40         */
  41        struct completion       ranging;
  42        int                     irqnr;
  43        /* Ensure correct alignment of data to push to IIO buffer */
  44        struct {
  45                s16 distance;
  46                s64 ts __aligned(8);
  47        } scan;
  48};
  49
  50static irqreturn_t mb1232_handle_irq(int irq, void *dev_id)
  51{
  52        struct iio_dev *indio_dev = dev_id;
  53        struct mb1232_data *data = iio_priv(indio_dev);
  54
  55        complete(&data->ranging);
  56
  57        return IRQ_HANDLED;
  58}
  59
  60static s16 mb1232_read_distance(struct mb1232_data *data)
  61{
  62        struct i2c_client *client = data->client;
  63        int ret;
  64        s16 distance;
  65        __be16 buf;
  66
  67        mutex_lock(&data->lock);
  68
  69        reinit_completion(&data->ranging);
  70
  71        ret = i2c_smbus_write_byte(client, MB1232_RANGE_COMMAND);
  72        if (ret < 0) {
  73                dev_err(&client->dev, "write command - err: %d\n", ret);
  74                goto error_unlock;
  75        }
  76
  77        if (data->irqnr >= 0) {
  78                /* it cannot take more than 100 ms */
  79                ret = wait_for_completion_killable_timeout(&data->ranging,
  80                                                                        HZ/10);
  81                if (ret < 0)
  82                        goto error_unlock;
  83                else if (ret == 0) {
  84                        ret = -ETIMEDOUT;
  85                        goto error_unlock;
  86                }
  87        } else {
  88                /* use simple sleep if announce irq is not connected */
  89                msleep(15);
  90        }
  91
  92        ret = i2c_master_recv(client, (char *)&buf, sizeof(buf));
  93        if (ret < 0) {
  94                dev_err(&client->dev, "i2c_master_recv: ret=%d\n", ret);
  95                goto error_unlock;
  96        }
  97
  98        distance = __be16_to_cpu(buf);
  99        /* check for not returning misleading error codes */
 100        if (distance < 0) {
 101                dev_err(&client->dev, "distance=%d\n", distance);
 102                ret = -EINVAL;
 103                goto error_unlock;
 104        }
 105
 106        mutex_unlock(&data->lock);
 107
 108        return distance;
 109
 110error_unlock:
 111        mutex_unlock(&data->lock);
 112
 113        return ret;
 114}
 115
 116static irqreturn_t mb1232_trigger_handler(int irq, void *p)
 117{
 118        struct iio_poll_func *pf = p;
 119        struct iio_dev *indio_dev = pf->indio_dev;
 120        struct mb1232_data *data = iio_priv(indio_dev);
 121
 122        data->scan.distance = mb1232_read_distance(data);
 123        if (data->scan.distance < 0)
 124                goto err;
 125
 126        iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 127                                           pf->timestamp);
 128
 129err:
 130        iio_trigger_notify_done(indio_dev->trig);
 131        return IRQ_HANDLED;
 132}
 133
 134static int mb1232_read_raw(struct iio_dev *indio_dev,
 135                            struct iio_chan_spec const *channel, int *val,
 136                            int *val2, long mask)
 137{
 138        struct mb1232_data *data = iio_priv(indio_dev);
 139        int ret;
 140
 141        if (channel->type != IIO_DISTANCE)
 142                return -EINVAL;
 143
 144        switch (mask) {
 145        case IIO_CHAN_INFO_RAW:
 146                ret = mb1232_read_distance(data);
 147                if (ret < 0)
 148                        return ret;
 149                *val = ret;
 150                return IIO_VAL_INT;
 151        case IIO_CHAN_INFO_SCALE:
 152                /* 1 LSB is 1 cm */
 153                *val = 0;
 154                *val2 = 10000;
 155                return IIO_VAL_INT_PLUS_MICRO;
 156        default:
 157                return -EINVAL;
 158        }
 159}
 160
 161static const struct iio_chan_spec mb1232_channels[] = {
 162        {
 163                .type = IIO_DISTANCE,
 164                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 165                                      BIT(IIO_CHAN_INFO_SCALE),
 166                .scan_index = 0,
 167                .scan_type = {
 168                        .sign = 's',
 169                        .realbits = 16,
 170                        .storagebits = 16,
 171                        .endianness = IIO_CPU,
 172                },
 173        },
 174        IIO_CHAN_SOFT_TIMESTAMP(1),
 175};
 176
 177static const struct iio_info mb1232_info = {
 178        .read_raw = mb1232_read_raw,
 179};
 180
 181static int mb1232_probe(struct i2c_client *client,
 182                                         const struct i2c_device_id *id)
 183{
 184        struct iio_dev *indio_dev;
 185        struct mb1232_data *data;
 186        int ret;
 187        struct device *dev = &client->dev;
 188
 189        if (!i2c_check_functionality(client->adapter,
 190                                        I2C_FUNC_SMBUS_READ_BYTE |
 191                                        I2C_FUNC_SMBUS_WRITE_BYTE))
 192                return -ENODEV;
 193
 194        indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
 195        if (!indio_dev)
 196                return -ENOMEM;
 197
 198        data = iio_priv(indio_dev);
 199        i2c_set_clientdata(client, indio_dev);
 200        data->client = client;
 201
 202        indio_dev->info = &mb1232_info;
 203        indio_dev->name = id->name;
 204        indio_dev->modes = INDIO_DIRECT_MODE;
 205        indio_dev->channels = mb1232_channels;
 206        indio_dev->num_channels = ARRAY_SIZE(mb1232_channels);
 207
 208        mutex_init(&data->lock);
 209
 210        init_completion(&data->ranging);
 211
 212        data->irqnr = irq_of_parse_and_map(dev->of_node, 0);
 213        if (data->irqnr <= 0) {
 214                /* usage of interrupt is optional */
 215                data->irqnr = -1;
 216        } else {
 217                ret = devm_request_irq(dev, data->irqnr, mb1232_handle_irq,
 218                                IRQF_TRIGGER_FALLING, id->name, indio_dev);
 219                if (ret < 0) {
 220                        dev_err(dev, "request_irq: %d\n", ret);
 221                        return ret;
 222                }
 223        }
 224
 225        ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
 226                        iio_pollfunc_store_time, mb1232_trigger_handler, NULL);
 227        if (ret < 0) {
 228                dev_err(dev, "setup of iio triggered buffer failed\n");
 229                return ret;
 230        }
 231
 232        return devm_iio_device_register(dev, indio_dev);
 233}
 234
 235static const struct of_device_id of_mb1232_match[] = {
 236        { .compatible = "maxbotix,mb1202", },
 237        { .compatible = "maxbotix,mb1212", },
 238        { .compatible = "maxbotix,mb1222", },
 239        { .compatible = "maxbotix,mb1232", },
 240        { .compatible = "maxbotix,mb1242", },
 241        { .compatible = "maxbotix,mb7040", },
 242        { .compatible = "maxbotix,mb7137", },
 243        {},
 244};
 245
 246MODULE_DEVICE_TABLE(of, of_mb1232_match);
 247
 248static const struct i2c_device_id mb1232_id[] = {
 249        { "maxbotix-mb1202", },
 250        { "maxbotix-mb1212", },
 251        { "maxbotix-mb1222", },
 252        { "maxbotix-mb1232", },
 253        { "maxbotix-mb1242", },
 254        { "maxbotix-mb7040", },
 255        { "maxbotix-mb7137", },
 256        { }
 257};
 258MODULE_DEVICE_TABLE(i2c, mb1232_id);
 259
 260static struct i2c_driver mb1232_driver = {
 261        .driver = {
 262                .name   = "maxbotix-mb1232",
 263                .of_match_table = of_mb1232_match,
 264        },
 265        .probe = mb1232_probe,
 266        .id_table = mb1232_id,
 267};
 268module_i2c_driver(mb1232_driver);
 269
 270MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
 271MODULE_DESCRIPTION("Maxbotix I2CXL-MaxSonar i2c ultrasonic ranger driver");
 272MODULE_LICENSE("GPL");
 273