1 /* 2 * srf08.c - Support for Devantech SRF08 ultrasonic ranger 3 * 4 * Copyright (c) 2016 Andreas Klinger <ak@it-klinger.de> 5 * 6 * This file is subject to the terms and conditions of version 2 of 7 * the GNU General Public License. See the file COPYING in the main 8 * directory of this archive for more details. 9 * 10 * For details about the device see: 11 * http://www.robot-electronics.co.uk/htm/srf08tech.html 12 */ 13 14 #include <linux/err.h> 15 #include <linux/i2c.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 22 /* registers of SRF08 device */ 23 #define SRF08_WRITE_COMMAND 0x00 /* Command Register */ 24 #define SRF08_WRITE_MAX_GAIN 0x01 /* Max Gain Register: 0 .. 31 */ 25 #define SRF08_WRITE_RANGE 0x02 /* Range Register: 0 .. 255 */ 26 #define SRF08_READ_SW_REVISION 0x00 /* Software Revision */ 27 #define SRF08_READ_LIGHT 0x01 /* Light Sensor during last echo */ 28 #define SRF08_READ_ECHO_1_HIGH 0x02 /* Range of first echo received */ 29 #define SRF08_READ_ECHO_1_LOW 0x03 /* Range of first echo received */ 30 31 #define SRF08_CMD_RANGING_CM 0x51 /* Ranging Mode - Result in cm */ 32 33 #define SRF08_DEFAULT_GAIN 1025 /* default analogue value of Gain */ 34 #define SRF08_DEFAULT_RANGE 6020 /* default value of Range in mm */ 35 36 struct srf08_data { 37 struct i2c_client *client; 38 int sensitivity; /* Gain */ 39 int range_mm; /* max. Range in mm */ 40 struct mutex lock; 41 }; 42 43 /* 44 * in the documentation one can read about the "Gain" of the device 45 * which is used here for amplifying the signal and filtering out unwanted 46 * ones. 47 * But with ADC's this term is already used differently and that's why it 48 * is called "Sensitivity" here. 49 */ 50 static const int srf08_sensitivity[] = { 51 94, 97, 100, 103, 107, 110, 114, 118, 52 123, 128, 133, 139, 145, 152, 159, 168, 53 177, 187, 199, 212, 227, 245, 265, 288, 54 317, 352, 395, 450, 524, 626, 777, 1025 }; 55 56 static int srf08_read_ranging(struct srf08_data *data) 57 { 58 struct i2c_client *client = data->client; 59 int ret, i; 60 int waittime; 61 62 mutex_lock(&data->lock); 63 64 ret = i2c_smbus_write_byte_data(data->client, 65 SRF08_WRITE_COMMAND, SRF08_CMD_RANGING_CM); 66 if (ret < 0) { 67 dev_err(&client->dev, "write command - err: %d\n", ret); 68 mutex_unlock(&data->lock); 69 return ret; 70 } 71 72 /* 73 * we read here until a correct version number shows up as 74 * suggested by the documentation 75 * 76 * with an ultrasonic speed of 343 m/s and a roundtrip of it 77 * sleep the expected duration and try to read from the device 78 * if nothing useful is read try it in a shorter grid 79 * 80 * polling for not more than 20 ms should be enough 81 */ 82 waittime = 1 + data->range_mm / 172; 83 msleep(waittime); 84 for (i = 0; i < 4; i++) { 85 ret = i2c_smbus_read_byte_data(data->client, 86 SRF08_READ_SW_REVISION); 87 88 /* check if a valid version number is read */ 89 if (ret < 255 && ret > 0) 90 break; 91 msleep(5); 92 } 93 94 if (ret >= 255 || ret <= 0) { 95 dev_err(&client->dev, "device not ready\n"); 96 mutex_unlock(&data->lock); 97 return -EIO; 98 } 99 100 ret = i2c_smbus_read_word_swapped(data->client, 101 SRF08_READ_ECHO_1_HIGH); 102 if (ret < 0) { 103 dev_err(&client->dev, "cannot read distance: ret=%d\n", ret); 104 mutex_unlock(&data->lock); 105 return ret; 106 } 107 108 mutex_unlock(&data->lock); 109 110 return ret; 111 } 112 113 static int srf08_read_raw(struct iio_dev *indio_dev, 114 struct iio_chan_spec const *channel, int *val, 115 int *val2, long mask) 116 { 117 struct srf08_data *data = iio_priv(indio_dev); 118 int ret; 119 120 if (channel->type != IIO_DISTANCE) 121 return -EINVAL; 122 123 switch (mask) { 124 case IIO_CHAN_INFO_RAW: 125 ret = srf08_read_ranging(data); 126 if (ret < 0) 127 return ret; 128 *val = ret; 129 return IIO_VAL_INT; 130 case IIO_CHAN_INFO_SCALE: 131 /* 1 LSB is 1 cm */ 132 *val = 0; 133 *val2 = 10000; 134 return IIO_VAL_INT_PLUS_MICRO; 135 default: 136 return -EINVAL; 137 } 138 } 139 140 static ssize_t srf08_show_range_mm_available(struct device *dev, 141 struct device_attribute *attr, char *buf) 142 { 143 return sprintf(buf, "[0.043 0.043 11.008]\n"); 144 } 145 146 static IIO_DEVICE_ATTR(sensor_max_range_available, S_IRUGO, 147 srf08_show_range_mm_available, NULL, 0); 148 149 static ssize_t srf08_show_range_mm(struct device *dev, 150 struct device_attribute *attr, char *buf) 151 { 152 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 153 struct srf08_data *data = iio_priv(indio_dev); 154 155 return sprintf(buf, "%d.%03d\n", data->range_mm / 1000, 156 data->range_mm % 1000); 157 } 158 159 /* 160 * set the range of the sensor to an even multiple of 43 mm 161 * which corresponds to 1 LSB in the register 162 * 163 * register value corresponding range 164 * 0x00 43 mm 165 * 0x01 86 mm 166 * 0x02 129 mm 167 * ... 168 * 0xFF 11008 mm 169 */ 170 static ssize_t srf08_write_range_mm(struct srf08_data *data, unsigned int val) 171 { 172 int ret; 173 struct i2c_client *client = data->client; 174 unsigned int mod; 175 u8 regval; 176 177 ret = val / 43 - 1; 178 mod = val % 43; 179 180 if (mod || (ret < 0) || (ret > 255)) 181 return -EINVAL; 182 183 regval = ret; 184 185 mutex_lock(&data->lock); 186 187 ret = i2c_smbus_write_byte_data(client, SRF08_WRITE_RANGE, regval); 188 if (ret < 0) { 189 dev_err(&client->dev, "write_range - err: %d\n", ret); 190 mutex_unlock(&data->lock); 191 return ret; 192 } 193 194 data->range_mm = val; 195 196 mutex_unlock(&data->lock); 197 198 return 0; 199 } 200 201 static ssize_t srf08_store_range_mm(struct device *dev, 202 struct device_attribute *attr, 203 const char *buf, size_t len) 204 { 205 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 206 struct srf08_data *data = iio_priv(indio_dev); 207 int ret; 208 int integer, fract; 209 210 ret = iio_str_to_fixpoint(buf, 100, &integer, &fract); 211 if (ret) 212 return ret; 213 214 ret = srf08_write_range_mm(data, integer * 1000 + fract); 215 if (ret < 0) 216 return ret; 217 218 return len; 219 } 220 221 static IIO_DEVICE_ATTR(sensor_max_range, S_IRUGO | S_IWUSR, 222 srf08_show_range_mm, srf08_store_range_mm, 0); 223 224 static ssize_t srf08_show_sensitivity_available(struct device *dev, 225 struct device_attribute *attr, char *buf) 226 { 227 int i, len = 0; 228 229 for (i = 0; i < ARRAY_SIZE(srf08_sensitivity); i++) 230 len += sprintf(buf + len, "%d ", srf08_sensitivity[i]); 231 232 len += sprintf(buf + len, "\n"); 233 234 return len; 235 } 236 237 static IIO_DEVICE_ATTR(sensor_sensitivity_available, S_IRUGO, 238 srf08_show_sensitivity_available, NULL, 0); 239 240 static ssize_t srf08_show_sensitivity(struct device *dev, 241 struct device_attribute *attr, char *buf) 242 { 243 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 244 struct srf08_data *data = iio_priv(indio_dev); 245 int len; 246 247 len = sprintf(buf, "%d\n", data->sensitivity); 248 249 return len; 250 } 251 252 static ssize_t srf08_write_sensitivity(struct srf08_data *data, 253 unsigned int val) 254 { 255 struct i2c_client *client = data->client; 256 int ret, i; 257 u8 regval; 258 259 for (i = 0; i < ARRAY_SIZE(srf08_sensitivity); i++) 260 if (val == srf08_sensitivity[i]) { 261 regval = i; 262 break; 263 } 264 265 if (i >= ARRAY_SIZE(srf08_sensitivity)) 266 return -EINVAL; 267 268 mutex_lock(&data->lock); 269 270 ret = i2c_smbus_write_byte_data(client, 271 SRF08_WRITE_MAX_GAIN, regval); 272 if (ret < 0) { 273 dev_err(&client->dev, "write_sensitivity - err: %d\n", ret); 274 mutex_unlock(&data->lock); 275 return ret; 276 } 277 278 data->sensitivity = val; 279 280 mutex_unlock(&data->lock); 281 282 return 0; 283 } 284 285 static ssize_t srf08_store_sensitivity(struct device *dev, 286 struct device_attribute *attr, 287 const char *buf, size_t len) 288 { 289 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 290 struct srf08_data *data = iio_priv(indio_dev); 291 int ret; 292 unsigned int val; 293 294 ret = kstrtouint(buf, 10, &val); 295 if (ret) 296 return ret; 297 298 ret = srf08_write_sensitivity(data, val); 299 if (ret < 0) 300 return ret; 301 302 return len; 303 } 304 305 static IIO_DEVICE_ATTR(sensor_sensitivity, S_IRUGO | S_IWUSR, 306 srf08_show_sensitivity, srf08_store_sensitivity, 0); 307 308 static struct attribute *srf08_attributes[] = { 309 &iio_dev_attr_sensor_max_range.dev_attr.attr, 310 &iio_dev_attr_sensor_max_range_available.dev_attr.attr, 311 &iio_dev_attr_sensor_sensitivity.dev_attr.attr, 312 &iio_dev_attr_sensor_sensitivity_available.dev_attr.attr, 313 NULL, 314 }; 315 316 static const struct attribute_group srf08_attribute_group = { 317 .attrs = srf08_attributes, 318 }; 319 320 static const struct iio_chan_spec srf08_channels[] = { 321 { 322 .type = IIO_DISTANCE, 323 .info_mask_separate = 324 BIT(IIO_CHAN_INFO_RAW) | 325 BIT(IIO_CHAN_INFO_SCALE), 326 }, 327 }; 328 329 static const struct iio_info srf08_info = { 330 .read_raw = srf08_read_raw, 331 .attrs = &srf08_attribute_group, 332 .driver_module = THIS_MODULE, 333 }; 334 335 static int srf08_probe(struct i2c_client *client, 336 const struct i2c_device_id *id) 337 { 338 struct iio_dev *indio_dev; 339 struct srf08_data *data; 340 int ret; 341 342 if (!i2c_check_functionality(client->adapter, 343 I2C_FUNC_SMBUS_READ_BYTE_DATA | 344 I2C_FUNC_SMBUS_WRITE_BYTE_DATA | 345 I2C_FUNC_SMBUS_READ_WORD_DATA)) 346 return -ENODEV; 347 348 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 349 if (!indio_dev) 350 return -ENOMEM; 351 352 data = iio_priv(indio_dev); 353 i2c_set_clientdata(client, indio_dev); 354 data->client = client; 355 356 indio_dev->name = "srf08"; 357 indio_dev->dev.parent = &client->dev; 358 indio_dev->modes = INDIO_DIRECT_MODE; 359 indio_dev->info = &srf08_info; 360 indio_dev->channels = srf08_channels; 361 indio_dev->num_channels = ARRAY_SIZE(srf08_channels); 362 363 mutex_init(&data->lock); 364 365 /* 366 * set default values of device here 367 * these register values cannot be read from the hardware 368 * therefore set driver specific default values 369 */ 370 ret = srf08_write_range_mm(data, SRF08_DEFAULT_RANGE); 371 if (ret < 0) 372 return ret; 373 374 ret = srf08_write_sensitivity(data, SRF08_DEFAULT_GAIN); 375 if (ret < 0) 376 return ret; 377 378 return devm_iio_device_register(&client->dev, indio_dev); 379 } 380 381 static const struct i2c_device_id srf08_id[] = { 382 { "srf08", 0 }, 383 { } 384 }; 385 MODULE_DEVICE_TABLE(i2c, srf08_id); 386 387 static struct i2c_driver srf08_driver = { 388 .driver = { 389 .name = "srf08", 390 }, 391 .probe = srf08_probe, 392 .id_table = srf08_id, 393 }; 394 module_i2c_driver(srf08_driver); 395 396 MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>"); 397 MODULE_DESCRIPTION("Devantech SRF08 ultrasonic ranger driver"); 398 MODULE_LICENSE("GPL"); 399