linux/drivers/iio/proximity/srf08.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * srf08.c - Support for Devantech SRFxx ultrasonic ranger
   4 *           with i2c interface
   5 * actually supported are srf02, srf08, srf10
   6 *
   7 * Copyright (c) 2016, 2017 Andreas Klinger <ak@it-klinger.de>
   8 *
   9 * For details about the device see:
  10 * http://www.robot-electronics.co.uk/htm/srf08tech.html
  11 * http://www.robot-electronics.co.uk/htm/srf10tech.htm
  12 * http://www.robot-electronics.co.uk/htm/srf02tech.htm
  13 */
  14
  15#include <linux/err.h>
  16#include <linux/i2c.h>
  17#include <linux/delay.h>
  18#include <linux/module.h>
  19#include <linux/bitops.h>
  20#include <linux/iio/iio.h>
  21#include <linux/iio/sysfs.h>
  22#include <linux/iio/buffer.h>
  23#include <linux/iio/trigger_consumer.h>
  24#include <linux/iio/triggered_buffer.h>
  25
  26/* registers of SRF08 device */
  27#define SRF08_WRITE_COMMAND     0x00    /* Command Register */
  28#define SRF08_WRITE_MAX_GAIN    0x01    /* Max Gain Register: 0 .. 31 */
  29#define SRF08_WRITE_RANGE       0x02    /* Range Register: 0 .. 255 */
  30#define SRF08_READ_SW_REVISION  0x00    /* Software Revision */
  31#define SRF08_READ_LIGHT        0x01    /* Light Sensor during last echo */
  32#define SRF08_READ_ECHO_1_HIGH  0x02    /* Range of first echo received */
  33#define SRF08_READ_ECHO_1_LOW   0x03    /* Range of first echo received */
  34
  35#define SRF08_CMD_RANGING_CM    0x51    /* Ranging Mode - Result in cm */
  36
  37enum srf08_sensor_type {
  38        SRF02,
  39        SRF08,
  40        SRF10,
  41        SRF_MAX_TYPE
  42};
  43
  44struct srf08_chip_info {
  45        const int               *sensitivity_avail;
  46        int                     num_sensitivity_avail;
  47        int                     sensitivity_default;
  48
  49        /* default value of Range in mm */
  50        int                     range_default;
  51};
  52
  53struct srf08_data {
  54        struct i2c_client       *client;
  55
  56        /*
  57         * Gain in the datasheet is called sensitivity here to distinct it
  58         * from the gain used with amplifiers of adc's
  59         */
  60        int                     sensitivity;
  61
  62        /* max. Range in mm */
  63        int                     range_mm;
  64        struct mutex            lock;
  65
  66        /*
  67         * triggered buffer
  68         * 1x16-bit channel + 3x16 padding + 4x16 timestamp
  69         */
  70        s16                     buffer[8];
  71
  72        /* Sensor-Type */
  73        enum srf08_sensor_type  sensor_type;
  74
  75        /* Chip-specific information */
  76        const struct srf08_chip_info    *chip_info;
  77};
  78
  79/*
  80 * in the documentation one can read about the "Gain" of the device
  81 * which is used here for amplifying the signal and filtering out unwanted
  82 * ones.
  83 * But with ADC's this term is already used differently and that's why it
  84 * is called "Sensitivity" here.
  85 */
  86static const struct srf08_chip_info srf02_chip_info = {
  87        .sensitivity_avail      = NULL,
  88        .num_sensitivity_avail  = 0,
  89        .sensitivity_default    = 0,
  90
  91        .range_default          = 0,
  92};
  93
  94static const int srf08_sensitivity_avail[] = {
  95         94,  97, 100, 103, 107, 110, 114, 118,
  96        123, 128, 133, 139, 145, 152, 159, 168,
  97        177, 187, 199, 212, 227, 245, 265, 288,
  98        317, 352, 395, 450, 524, 626, 777, 1025
  99        };
 100
 101static const struct srf08_chip_info srf08_chip_info = {
 102        .sensitivity_avail      = srf08_sensitivity_avail,
 103        .num_sensitivity_avail  = ARRAY_SIZE(srf08_sensitivity_avail),
 104        .sensitivity_default    = 1025,
 105
 106        .range_default          = 6020,
 107};
 108
 109static const int srf10_sensitivity_avail[] = {
 110         40,  40,  50,  60,  70,  80, 100, 120,
 111        140, 200, 250, 300, 350, 400, 500, 600,
 112        700,
 113        };
 114
 115static const struct srf08_chip_info srf10_chip_info = {
 116        .sensitivity_avail      = srf10_sensitivity_avail,
 117        .num_sensitivity_avail  = ARRAY_SIZE(srf10_sensitivity_avail),
 118        .sensitivity_default    = 700,
 119
 120        .range_default          = 6020,
 121};
 122
 123static int srf08_read_ranging(struct srf08_data *data)
 124{
 125        struct i2c_client *client = data->client;
 126        int ret, i;
 127        int waittime;
 128
 129        mutex_lock(&data->lock);
 130
 131        ret = i2c_smbus_write_byte_data(data->client,
 132                        SRF08_WRITE_COMMAND, SRF08_CMD_RANGING_CM);
 133        if (ret < 0) {
 134                dev_err(&client->dev, "write command - err: %d\n", ret);
 135                mutex_unlock(&data->lock);
 136                return ret;
 137        }
 138
 139        /*
 140         * we read here until a correct version number shows up as
 141         * suggested by the documentation
 142         *
 143         * with an ultrasonic speed of 343 m/s and a roundtrip of it
 144         * sleep the expected duration and try to read from the device
 145         * if nothing useful is read try it in a shorter grid
 146         *
 147         * polling for not more than 20 ms should be enough
 148         */
 149        waittime = 1 + data->range_mm / 172;
 150        msleep(waittime);
 151        for (i = 0; i < 4; i++) {
 152                ret = i2c_smbus_read_byte_data(data->client,
 153                                                SRF08_READ_SW_REVISION);
 154
 155                /* check if a valid version number is read */
 156                if (ret < 255 && ret > 0)
 157                        break;
 158                msleep(5);
 159        }
 160
 161        if (ret >= 255 || ret <= 0) {
 162                dev_err(&client->dev, "device not ready\n");
 163                mutex_unlock(&data->lock);
 164                return -EIO;
 165        }
 166
 167        ret = i2c_smbus_read_word_swapped(data->client,
 168                                                SRF08_READ_ECHO_1_HIGH);
 169        if (ret < 0) {
 170                dev_err(&client->dev, "cannot read distance: ret=%d\n", ret);
 171                mutex_unlock(&data->lock);
 172                return ret;
 173        }
 174
 175        mutex_unlock(&data->lock);
 176
 177        return ret;
 178}
 179
 180static irqreturn_t srf08_trigger_handler(int irq, void *p)
 181{
 182        struct iio_poll_func *pf = p;
 183        struct iio_dev *indio_dev = pf->indio_dev;
 184        struct srf08_data *data = iio_priv(indio_dev);
 185        s16 sensor_data;
 186
 187        sensor_data = srf08_read_ranging(data);
 188        if (sensor_data < 0)
 189                goto err;
 190
 191        mutex_lock(&data->lock);
 192
 193        data->buffer[0] = sensor_data;
 194        iio_push_to_buffers_with_timestamp(indio_dev,
 195                                                data->buffer, pf->timestamp);
 196
 197        mutex_unlock(&data->lock);
 198err:
 199        iio_trigger_notify_done(indio_dev->trig);
 200        return IRQ_HANDLED;
 201}
 202
 203static int srf08_read_raw(struct iio_dev *indio_dev,
 204                            struct iio_chan_spec const *channel, int *val,
 205                            int *val2, long mask)
 206{
 207        struct srf08_data *data = iio_priv(indio_dev);
 208        int ret;
 209
 210        if (channel->type != IIO_DISTANCE)
 211                return -EINVAL;
 212
 213        switch (mask) {
 214        case IIO_CHAN_INFO_RAW:
 215                ret = srf08_read_ranging(data);
 216                if (ret < 0)
 217                        return ret;
 218                *val = ret;
 219                return IIO_VAL_INT;
 220        case IIO_CHAN_INFO_SCALE:
 221                /* 1 LSB is 1 cm */
 222                *val = 0;
 223                *val2 = 10000;
 224                return IIO_VAL_INT_PLUS_MICRO;
 225        default:
 226                return -EINVAL;
 227        }
 228}
 229
 230static ssize_t srf08_show_range_mm_available(struct device *dev,
 231                                struct device_attribute *attr, char *buf)
 232{
 233        return sprintf(buf, "[0.043 0.043 11.008]\n");
 234}
 235
 236static IIO_DEVICE_ATTR(sensor_max_range_available, S_IRUGO,
 237                                srf08_show_range_mm_available, NULL, 0);
 238
 239static ssize_t srf08_show_range_mm(struct device *dev,
 240                                struct device_attribute *attr, char *buf)
 241{
 242        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 243        struct srf08_data *data = iio_priv(indio_dev);
 244
 245        return sprintf(buf, "%d.%03d\n", data->range_mm / 1000,
 246                                                data->range_mm % 1000);
 247}
 248
 249/*
 250 * set the range of the sensor to an even multiple of 43 mm
 251 * which corresponds to 1 LSB in the register
 252 *
 253 * register value    corresponding range
 254 *         0x00             43 mm
 255 *         0x01             86 mm
 256 *         0x02            129 mm
 257 *         ...
 258 *         0xFF          11008 mm
 259 */
 260static ssize_t srf08_write_range_mm(struct srf08_data *data, unsigned int val)
 261{
 262        int ret;
 263        struct i2c_client *client = data->client;
 264        unsigned int mod;
 265        u8 regval;
 266
 267        ret = val / 43 - 1;
 268        mod = val % 43;
 269
 270        if (mod || (ret < 0) || (ret > 255))
 271                return -EINVAL;
 272
 273        regval = ret;
 274
 275        mutex_lock(&data->lock);
 276
 277        ret = i2c_smbus_write_byte_data(client, SRF08_WRITE_RANGE, regval);
 278        if (ret < 0) {
 279                dev_err(&client->dev, "write_range - err: %d\n", ret);
 280                mutex_unlock(&data->lock);
 281                return ret;
 282        }
 283
 284        data->range_mm = val;
 285
 286        mutex_unlock(&data->lock);
 287
 288        return 0;
 289}
 290
 291static ssize_t srf08_store_range_mm(struct device *dev,
 292                                        struct device_attribute *attr,
 293                                        const char *buf, size_t len)
 294{
 295        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 296        struct srf08_data *data = iio_priv(indio_dev);
 297        int ret;
 298        int integer, fract;
 299
 300        ret = iio_str_to_fixpoint(buf, 100, &integer, &fract);
 301        if (ret)
 302                return ret;
 303
 304        ret = srf08_write_range_mm(data, integer * 1000 + fract);
 305        if (ret < 0)
 306                return ret;
 307
 308        return len;
 309}
 310
 311static IIO_DEVICE_ATTR(sensor_max_range, S_IRUGO | S_IWUSR,
 312                        srf08_show_range_mm, srf08_store_range_mm, 0);
 313
 314static ssize_t srf08_show_sensitivity_available(struct device *dev,
 315                                struct device_attribute *attr, char *buf)
 316{
 317        int i, len = 0;
 318        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 319        struct srf08_data *data = iio_priv(indio_dev);
 320
 321        for (i = 0; i < data->chip_info->num_sensitivity_avail; i++)
 322                if (data->chip_info->sensitivity_avail[i])
 323                        len += sprintf(buf + len, "%d ",
 324                                data->chip_info->sensitivity_avail[i]);
 325
 326        len += sprintf(buf + len, "\n");
 327
 328        return len;
 329}
 330
 331static IIO_DEVICE_ATTR(sensor_sensitivity_available, S_IRUGO,
 332                                srf08_show_sensitivity_available, NULL, 0);
 333
 334static ssize_t srf08_show_sensitivity(struct device *dev,
 335                                struct device_attribute *attr, char *buf)
 336{
 337        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 338        struct srf08_data *data = iio_priv(indio_dev);
 339        int len;
 340
 341        len = sprintf(buf, "%d\n", data->sensitivity);
 342
 343        return len;
 344}
 345
 346static ssize_t srf08_write_sensitivity(struct srf08_data *data,
 347                                                        unsigned int val)
 348{
 349        struct i2c_client *client = data->client;
 350        int ret, i;
 351        u8 regval;
 352
 353        if (!val)
 354                return -EINVAL;
 355
 356        for (i = 0; i < data->chip_info->num_sensitivity_avail; i++)
 357                if (val && (val == data->chip_info->sensitivity_avail[i])) {
 358                        regval = i;
 359                        break;
 360                }
 361
 362        if (i >= data->chip_info->num_sensitivity_avail)
 363                return -EINVAL;
 364
 365        mutex_lock(&data->lock);
 366
 367        ret = i2c_smbus_write_byte_data(client, SRF08_WRITE_MAX_GAIN, regval);
 368        if (ret < 0) {
 369                dev_err(&client->dev, "write_sensitivity - err: %d\n", ret);
 370                mutex_unlock(&data->lock);
 371                return ret;
 372        }
 373
 374        data->sensitivity = val;
 375
 376        mutex_unlock(&data->lock);
 377
 378        return 0;
 379}
 380
 381static ssize_t srf08_store_sensitivity(struct device *dev,
 382                                                struct device_attribute *attr,
 383                                                const char *buf, size_t len)
 384{
 385        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 386        struct srf08_data *data = iio_priv(indio_dev);
 387        int ret;
 388        unsigned int val;
 389
 390        ret = kstrtouint(buf, 10, &val);
 391        if (ret)
 392                return ret;
 393
 394        ret = srf08_write_sensitivity(data, val);
 395        if (ret < 0)
 396                return ret;
 397
 398        return len;
 399}
 400
 401static IIO_DEVICE_ATTR(sensor_sensitivity, S_IRUGO | S_IWUSR,
 402                        srf08_show_sensitivity, srf08_store_sensitivity, 0);
 403
 404static struct attribute *srf08_attributes[] = {
 405        &iio_dev_attr_sensor_max_range.dev_attr.attr,
 406        &iio_dev_attr_sensor_max_range_available.dev_attr.attr,
 407        &iio_dev_attr_sensor_sensitivity.dev_attr.attr,
 408        &iio_dev_attr_sensor_sensitivity_available.dev_attr.attr,
 409        NULL,
 410};
 411
 412static const struct attribute_group srf08_attribute_group = {
 413        .attrs = srf08_attributes,
 414};
 415
 416static const struct iio_chan_spec srf08_channels[] = {
 417        {
 418                .type = IIO_DISTANCE,
 419                .info_mask_separate =
 420                                BIT(IIO_CHAN_INFO_RAW) |
 421                                BIT(IIO_CHAN_INFO_SCALE),
 422                .scan_index = 0,
 423                .scan_type = {
 424                        .sign = 's',
 425                        .realbits = 16,
 426                        .storagebits = 16,
 427                        .endianness = IIO_CPU,
 428                },
 429        },
 430        IIO_CHAN_SOFT_TIMESTAMP(1),
 431};
 432
 433static const struct iio_info srf08_info = {
 434        .read_raw = srf08_read_raw,
 435        .attrs = &srf08_attribute_group,
 436};
 437
 438/*
 439 * srf02 don't have an adjustable range or sensitivity,
 440 * so we don't need attributes at all
 441 */
 442static const struct iio_info srf02_info = {
 443        .read_raw = srf08_read_raw,
 444};
 445
 446static int srf08_probe(struct i2c_client *client,
 447                                         const struct i2c_device_id *id)
 448{
 449        struct iio_dev *indio_dev;
 450        struct srf08_data *data;
 451        int ret;
 452
 453        if (!i2c_check_functionality(client->adapter,
 454                                        I2C_FUNC_SMBUS_READ_BYTE_DATA |
 455                                        I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
 456                                        I2C_FUNC_SMBUS_READ_WORD_DATA))
 457                return -ENODEV;
 458
 459        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 460        if (!indio_dev)
 461                return -ENOMEM;
 462
 463        data = iio_priv(indio_dev);
 464        i2c_set_clientdata(client, indio_dev);
 465        data->client = client;
 466        data->sensor_type = (enum srf08_sensor_type)id->driver_data;
 467
 468        switch (data->sensor_type) {
 469        case SRF02:
 470                data->chip_info = &srf02_chip_info;
 471                indio_dev->info = &srf02_info;
 472                break;
 473        case SRF08:
 474                data->chip_info = &srf08_chip_info;
 475                indio_dev->info = &srf08_info;
 476                break;
 477        case SRF10:
 478                data->chip_info = &srf10_chip_info;
 479                indio_dev->info = &srf08_info;
 480                break;
 481        default:
 482                return -EINVAL;
 483        }
 484
 485        indio_dev->name = id->name;
 486        indio_dev->dev.parent = &client->dev;
 487        indio_dev->modes = INDIO_DIRECT_MODE;
 488        indio_dev->channels = srf08_channels;
 489        indio_dev->num_channels = ARRAY_SIZE(srf08_channels);
 490
 491        mutex_init(&data->lock);
 492
 493        ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
 494                        iio_pollfunc_store_time, srf08_trigger_handler, NULL);
 495        if (ret < 0) {
 496                dev_err(&client->dev, "setup of iio triggered buffer failed\n");
 497                return ret;
 498        }
 499
 500        if (data->chip_info->range_default) {
 501                /*
 502                 * set default range of device in mm here
 503                 * these register values cannot be read from the hardware
 504                 * therefore set driver specific default values
 505                 *
 506                 * srf02 don't have a default value so it'll be omitted
 507                 */
 508                ret = srf08_write_range_mm(data,
 509                                        data->chip_info->range_default);
 510                if (ret < 0)
 511                        return ret;
 512        }
 513
 514        if (data->chip_info->sensitivity_default) {
 515                /*
 516                 * set default sensitivity of device here
 517                 * these register values cannot be read from the hardware
 518                 * therefore set driver specific default values
 519                 *
 520                 * srf02 don't have a default value so it'll be omitted
 521                 */
 522                ret = srf08_write_sensitivity(data,
 523                                data->chip_info->sensitivity_default);
 524                if (ret < 0)
 525                        return ret;
 526        }
 527
 528        return devm_iio_device_register(&client->dev, indio_dev);
 529}
 530
 531static const struct of_device_id of_srf08_match[] = {
 532        { .compatible = "devantech,srf02", (void *)SRF02},
 533        { .compatible = "devantech,srf08", (void *)SRF08},
 534        { .compatible = "devantech,srf10", (void *)SRF10},
 535        {},
 536};
 537
 538MODULE_DEVICE_TABLE(of, of_srf08_match);
 539
 540static const struct i2c_device_id srf08_id[] = {
 541        { "srf02", SRF02 },
 542        { "srf08", SRF08 },
 543        { "srf10", SRF10 },
 544        { }
 545};
 546MODULE_DEVICE_TABLE(i2c, srf08_id);
 547
 548static struct i2c_driver srf08_driver = {
 549        .driver = {
 550                .name   = "srf08",
 551                .of_match_table = of_srf08_match,
 552        },
 553        .probe = srf08_probe,
 554        .id_table = srf08_id,
 555};
 556module_i2c_driver(srf08_driver);
 557
 558MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
 559MODULE_DESCRIPTION("Devantech SRF02/SRF08/SRF10 i2c ultrasonic ranger driver");
 560MODULE_LICENSE("GPL");
 561