root/drivers/iio/proximity/srf08.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. srf08_read_ranging
  2. srf08_trigger_handler
  3. srf08_read_raw
  4. srf08_show_range_mm_available
  5. srf08_show_range_mm
  6. srf08_write_range_mm
  7. srf08_store_range_mm
  8. srf08_show_sensitivity_available
  9. srf08_show_sensitivity
  10. srf08_write_sensitivity
  11. srf08_store_sensitivity
  12. srf08_probe

   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 
  37 enum srf08_sensor_type {
  38         SRF02,
  39         SRF08,
  40         SRF10,
  41         SRF_MAX_TYPE
  42 };
  43 
  44 struct 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 
  53 struct 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  */
  86 static 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 
  94 static 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 
 101 static 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 
 109 static 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 
 115 static 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 
 123 static 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 
 180 static 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);
 198 err:
 199         iio_trigger_notify_done(indio_dev->trig);
 200         return IRQ_HANDLED;
 201 }
 202 
 203 static 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 
 230 static 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 
 236 static IIO_DEVICE_ATTR(sensor_max_range_available, S_IRUGO,
 237                                 srf08_show_range_mm_available, NULL, 0);
 238 
 239 static 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  */
 260 static 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 
 291 static 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 
 311 static IIO_DEVICE_ATTR(sensor_max_range, S_IRUGO | S_IWUSR,
 312                         srf08_show_range_mm, srf08_store_range_mm, 0);
 313 
 314 static 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 
 331 static IIO_DEVICE_ATTR(sensor_sensitivity_available, S_IRUGO,
 332                                 srf08_show_sensitivity_available, NULL, 0);
 333 
 334 static 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 
 346 static 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 
 381 static 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 
 401 static IIO_DEVICE_ATTR(sensor_sensitivity, S_IRUGO | S_IWUSR,
 402                         srf08_show_sensitivity, srf08_store_sensitivity, 0);
 403 
 404 static 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 
 412 static const struct attribute_group srf08_attribute_group = {
 413         .attrs = srf08_attributes,
 414 };
 415 
 416 static 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 
 433 static 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  */
 442 static const struct iio_info srf02_info = {
 443         .read_raw = srf08_read_raw,
 444 };
 445 
 446 static 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 
 531 static 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 
 538 MODULE_DEVICE_TABLE(of, of_srf08_match);
 539 
 540 static const struct i2c_device_id srf08_id[] = {
 541         { "srf02", SRF02 },
 542         { "srf08", SRF08 },
 543         { "srf10", SRF10 },
 544         { }
 545 };
 546 MODULE_DEVICE_TABLE(i2c, srf08_id);
 547 
 548 static 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 };
 556 module_i2c_driver(srf08_driver);
 557 
 558 MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
 559 MODULE_DESCRIPTION("Devantech SRF02/SRF08/SRF10 i2c ultrasonic ranger driver");
 560 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */