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