1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * STMicroelectronics sensors core library driver 4 * 5 * Copyright 2012-2013 STMicroelectronics Inc. 6 * 7 * Denis Ciocca <denis.ciocca@st.com> 8 */ 9 10 #include <linux/kernel.h> 11 #include <linux/module.h> 12 #include <linux/slab.h> 13 #include <linux/delay.h> 14 #include <linux/iio/iio.h> 15 #include <linux/property.h> 16 #include <linux/regulator/consumer.h> 17 #include <linux/regmap.h> 18 #include <asm/unaligned.h> 19 #include <linux/iio/common/st_sensors.h> 20 21 #include "st_sensors_core.h" 22 23 static inline u32 st_sensors_get_unaligned_le24(const u8 *p) 24 { 25 return (s32)((p[0] | p[1] << 8 | p[2] << 16) << 8) >> 8; 26 } 27 28 int st_sensors_write_data_with_mask(struct iio_dev *indio_dev, 29 u8 reg_addr, u8 mask, u8 data) 30 { 31 struct st_sensor_data *sdata = iio_priv(indio_dev); 32 33 return regmap_update_bits(sdata->regmap, 34 reg_addr, mask, data << __ffs(mask)); 35 } 36 37 int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev, 38 unsigned reg, unsigned writeval, 39 unsigned *readval) 40 { 41 struct st_sensor_data *sdata = iio_priv(indio_dev); 42 int err; 43 44 if (!readval) 45 return regmap_write(sdata->regmap, reg, writeval); 46 47 err = regmap_read(sdata->regmap, reg, readval); 48 if (err < 0) 49 return err; 50 51 return 0; 52 } 53 EXPORT_SYMBOL(st_sensors_debugfs_reg_access); 54 55 static int st_sensors_match_odr(struct st_sensor_settings *sensor_settings, 56 unsigned int odr, struct st_sensor_odr_avl *odr_out) 57 { 58 int i, ret = -EINVAL; 59 60 for (i = 0; i < ST_SENSORS_ODR_LIST_MAX; i++) { 61 if (sensor_settings->odr.odr_avl[i].hz == 0) 62 goto st_sensors_match_odr_error; 63 64 if (sensor_settings->odr.odr_avl[i].hz == odr) { 65 odr_out->hz = sensor_settings->odr.odr_avl[i].hz; 66 odr_out->value = sensor_settings->odr.odr_avl[i].value; 67 ret = 0; 68 break; 69 } 70 } 71 72 st_sensors_match_odr_error: 73 return ret; 74 } 75 76 int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr) 77 { 78 int err; 79 struct st_sensor_odr_avl odr_out = {0, 0}; 80 struct st_sensor_data *sdata = iio_priv(indio_dev); 81 82 if (!sdata->sensor_settings->odr.addr) 83 return 0; 84 85 err = st_sensors_match_odr(sdata->sensor_settings, odr, &odr_out); 86 if (err < 0) 87 goto st_sensors_match_odr_error; 88 89 if ((sdata->sensor_settings->odr.addr == 90 sdata->sensor_settings->pw.addr) && 91 (sdata->sensor_settings->odr.mask == 92 sdata->sensor_settings->pw.mask)) { 93 if (sdata->enabled == true) { 94 err = st_sensors_write_data_with_mask(indio_dev, 95 sdata->sensor_settings->odr.addr, 96 sdata->sensor_settings->odr.mask, 97 odr_out.value); 98 } else { 99 err = 0; 100 } 101 } else { 102 err = st_sensors_write_data_with_mask(indio_dev, 103 sdata->sensor_settings->odr.addr, 104 sdata->sensor_settings->odr.mask, 105 odr_out.value); 106 } 107 if (err >= 0) 108 sdata->odr = odr_out.hz; 109 110 st_sensors_match_odr_error: 111 return err; 112 } 113 EXPORT_SYMBOL(st_sensors_set_odr); 114 115 static int st_sensors_match_fs(struct st_sensor_settings *sensor_settings, 116 unsigned int fs, int *index_fs_avl) 117 { 118 int i, ret = -EINVAL; 119 120 for (i = 0; i < ST_SENSORS_FULLSCALE_AVL_MAX; i++) { 121 if (sensor_settings->fs.fs_avl[i].num == 0) 122 return ret; 123 124 if (sensor_settings->fs.fs_avl[i].num == fs) { 125 *index_fs_avl = i; 126 ret = 0; 127 break; 128 } 129 } 130 131 return ret; 132 } 133 134 static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs) 135 { 136 int err, i = 0; 137 struct st_sensor_data *sdata = iio_priv(indio_dev); 138 139 if (sdata->sensor_settings->fs.addr == 0) 140 return 0; 141 142 err = st_sensors_match_fs(sdata->sensor_settings, fs, &i); 143 if (err < 0) 144 goto st_accel_set_fullscale_error; 145 146 err = st_sensors_write_data_with_mask(indio_dev, 147 sdata->sensor_settings->fs.addr, 148 sdata->sensor_settings->fs.mask, 149 sdata->sensor_settings->fs.fs_avl[i].value); 150 if (err < 0) 151 goto st_accel_set_fullscale_error; 152 153 sdata->current_fullscale = (struct st_sensor_fullscale_avl *) 154 &sdata->sensor_settings->fs.fs_avl[i]; 155 return err; 156 157 st_accel_set_fullscale_error: 158 dev_err(&indio_dev->dev, "failed to set new fullscale.\n"); 159 return err; 160 } 161 162 int st_sensors_set_enable(struct iio_dev *indio_dev, bool enable) 163 { 164 u8 tmp_value; 165 int err = -EINVAL; 166 bool found = false; 167 struct st_sensor_odr_avl odr_out = {0, 0}; 168 struct st_sensor_data *sdata = iio_priv(indio_dev); 169 170 if (enable) { 171 tmp_value = sdata->sensor_settings->pw.value_on; 172 if ((sdata->sensor_settings->odr.addr == 173 sdata->sensor_settings->pw.addr) && 174 (sdata->sensor_settings->odr.mask == 175 sdata->sensor_settings->pw.mask)) { 176 err = st_sensors_match_odr(sdata->sensor_settings, 177 sdata->odr, &odr_out); 178 if (err < 0) 179 goto set_enable_error; 180 tmp_value = odr_out.value; 181 found = true; 182 } 183 err = st_sensors_write_data_with_mask(indio_dev, 184 sdata->sensor_settings->pw.addr, 185 sdata->sensor_settings->pw.mask, tmp_value); 186 if (err < 0) 187 goto set_enable_error; 188 189 sdata->enabled = true; 190 191 if (found) 192 sdata->odr = odr_out.hz; 193 } else { 194 err = st_sensors_write_data_with_mask(indio_dev, 195 sdata->sensor_settings->pw.addr, 196 sdata->sensor_settings->pw.mask, 197 sdata->sensor_settings->pw.value_off); 198 if (err < 0) 199 goto set_enable_error; 200 201 sdata->enabled = false; 202 } 203 204 set_enable_error: 205 return err; 206 } 207 EXPORT_SYMBOL(st_sensors_set_enable); 208 209 int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable) 210 { 211 struct st_sensor_data *sdata = iio_priv(indio_dev); 212 int err = 0; 213 214 if (sdata->sensor_settings->enable_axis.addr) 215 err = st_sensors_write_data_with_mask(indio_dev, 216 sdata->sensor_settings->enable_axis.addr, 217 sdata->sensor_settings->enable_axis.mask, 218 axis_enable); 219 return err; 220 } 221 EXPORT_SYMBOL(st_sensors_set_axis_enable); 222 223 int st_sensors_power_enable(struct iio_dev *indio_dev) 224 { 225 struct st_sensor_data *pdata = iio_priv(indio_dev); 226 int err; 227 228 /* Regulators not mandatory, but if requested we should enable them. */ 229 pdata->vdd = devm_regulator_get(indio_dev->dev.parent, "vdd"); 230 if (IS_ERR(pdata->vdd)) { 231 dev_err(&indio_dev->dev, "unable to get Vdd supply\n"); 232 return PTR_ERR(pdata->vdd); 233 } 234 err = regulator_enable(pdata->vdd); 235 if (err != 0) { 236 dev_warn(&indio_dev->dev, 237 "Failed to enable specified Vdd supply\n"); 238 return err; 239 } 240 241 pdata->vdd_io = devm_regulator_get(indio_dev->dev.parent, "vddio"); 242 if (IS_ERR(pdata->vdd_io)) { 243 dev_err(&indio_dev->dev, "unable to get Vdd_IO supply\n"); 244 err = PTR_ERR(pdata->vdd_io); 245 goto st_sensors_disable_vdd; 246 } 247 err = regulator_enable(pdata->vdd_io); 248 if (err != 0) { 249 dev_warn(&indio_dev->dev, 250 "Failed to enable specified Vdd_IO supply\n"); 251 goto st_sensors_disable_vdd; 252 } 253 254 return 0; 255 256 st_sensors_disable_vdd: 257 regulator_disable(pdata->vdd); 258 return err; 259 } 260 EXPORT_SYMBOL(st_sensors_power_enable); 261 262 void st_sensors_power_disable(struct iio_dev *indio_dev) 263 { 264 struct st_sensor_data *pdata = iio_priv(indio_dev); 265 266 regulator_disable(pdata->vdd); 267 regulator_disable(pdata->vdd_io); 268 } 269 EXPORT_SYMBOL(st_sensors_power_disable); 270 271 static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev, 272 struct st_sensors_platform_data *pdata) 273 { 274 struct st_sensor_data *sdata = iio_priv(indio_dev); 275 276 /* Sensor does not support interrupts */ 277 if (!sdata->sensor_settings->drdy_irq.int1.addr && 278 !sdata->sensor_settings->drdy_irq.int2.addr) { 279 if (pdata->drdy_int_pin) 280 dev_info(&indio_dev->dev, 281 "DRDY on pin INT%d specified, but sensor " 282 "does not support interrupts\n", 283 pdata->drdy_int_pin); 284 return 0; 285 } 286 287 switch (pdata->drdy_int_pin) { 288 case 1: 289 if (!sdata->sensor_settings->drdy_irq.int1.mask) { 290 dev_err(&indio_dev->dev, 291 "DRDY on INT1 not available.\n"); 292 return -EINVAL; 293 } 294 sdata->drdy_int_pin = 1; 295 break; 296 case 2: 297 if (!sdata->sensor_settings->drdy_irq.int2.mask) { 298 dev_err(&indio_dev->dev, 299 "DRDY on INT2 not available.\n"); 300 return -EINVAL; 301 } 302 sdata->drdy_int_pin = 2; 303 break; 304 default: 305 dev_err(&indio_dev->dev, "DRDY on pdata not valid.\n"); 306 return -EINVAL; 307 } 308 309 if (pdata->open_drain) { 310 if (!sdata->sensor_settings->drdy_irq.int1.addr_od && 311 !sdata->sensor_settings->drdy_irq.int2.addr_od) 312 dev_err(&indio_dev->dev, 313 "open drain requested but unsupported.\n"); 314 else 315 sdata->int_pin_open_drain = true; 316 } 317 318 return 0; 319 } 320 321 static struct st_sensors_platform_data *st_sensors_dev_probe(struct device *dev, 322 struct st_sensors_platform_data *defdata) 323 { 324 struct st_sensors_platform_data *pdata; 325 u32 val; 326 327 if (!dev_fwnode(dev)) 328 return NULL; 329 330 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 331 if (!device_property_read_u32(dev, "st,drdy-int-pin", &val) && (val <= 2)) 332 pdata->drdy_int_pin = (u8) val; 333 else 334 pdata->drdy_int_pin = defdata ? defdata->drdy_int_pin : 0; 335 336 pdata->open_drain = device_property_read_bool(dev, "drive-open-drain"); 337 338 return pdata; 339 } 340 341 /** 342 * st_sensors_dev_name_probe() - device probe for ST sensor name 343 * @dev: driver model representation of the device. 344 * @name: device name buffer reference. 345 * @len: device name buffer length. 346 * 347 * In effect this function matches an ID to an internal kernel 348 * name for a certain sensor device, so that the rest of the autodetection can 349 * rely on that name from this point on. I2C/SPI devices will be renamed 350 * to match the internal kernel convention. 351 */ 352 void st_sensors_dev_name_probe(struct device *dev, char *name, int len) 353 { 354 const void *match; 355 356 match = device_get_match_data(dev); 357 if (!match) 358 return; 359 360 /* The name from the match takes precedence if present */ 361 strlcpy(name, match, len); 362 } 363 EXPORT_SYMBOL(st_sensors_dev_name_probe); 364 365 int st_sensors_init_sensor(struct iio_dev *indio_dev, 366 struct st_sensors_platform_data *pdata) 367 { 368 struct st_sensor_data *sdata = iio_priv(indio_dev); 369 struct st_sensors_platform_data *of_pdata; 370 int err = 0; 371 372 /* If OF/DT pdata exists, it will take precedence of anything else */ 373 of_pdata = st_sensors_dev_probe(indio_dev->dev.parent, pdata); 374 if (of_pdata) 375 pdata = of_pdata; 376 377 if (pdata) { 378 err = st_sensors_set_drdy_int_pin(indio_dev, pdata); 379 if (err < 0) 380 return err; 381 } 382 383 err = st_sensors_set_enable(indio_dev, false); 384 if (err < 0) 385 return err; 386 387 /* Disable DRDY, this might be still be enabled after reboot. */ 388 err = st_sensors_set_dataready_irq(indio_dev, false); 389 if (err < 0) 390 return err; 391 392 if (sdata->current_fullscale) { 393 err = st_sensors_set_fullscale(indio_dev, 394 sdata->current_fullscale->num); 395 if (err < 0) 396 return err; 397 } else 398 dev_info(&indio_dev->dev, "Full-scale not possible\n"); 399 400 err = st_sensors_set_odr(indio_dev, sdata->odr); 401 if (err < 0) 402 return err; 403 404 /* set BDU */ 405 if (sdata->sensor_settings->bdu.addr) { 406 err = st_sensors_write_data_with_mask(indio_dev, 407 sdata->sensor_settings->bdu.addr, 408 sdata->sensor_settings->bdu.mask, true); 409 if (err < 0) 410 return err; 411 } 412 413 /* set DAS */ 414 if (sdata->sensor_settings->das.addr) { 415 err = st_sensors_write_data_with_mask(indio_dev, 416 sdata->sensor_settings->das.addr, 417 sdata->sensor_settings->das.mask, 1); 418 if (err < 0) 419 return err; 420 } 421 422 if (sdata->int_pin_open_drain) { 423 u8 addr, mask; 424 425 if (sdata->drdy_int_pin == 1) { 426 addr = sdata->sensor_settings->drdy_irq.int1.addr_od; 427 mask = sdata->sensor_settings->drdy_irq.int1.mask_od; 428 } else { 429 addr = sdata->sensor_settings->drdy_irq.int2.addr_od; 430 mask = sdata->sensor_settings->drdy_irq.int2.mask_od; 431 } 432 433 dev_info(&indio_dev->dev, 434 "set interrupt line to open drain mode on pin %d\n", 435 sdata->drdy_int_pin); 436 err = st_sensors_write_data_with_mask(indio_dev, addr, 437 mask, 1); 438 if (err < 0) 439 return err; 440 } 441 442 err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); 443 444 return err; 445 } 446 EXPORT_SYMBOL(st_sensors_init_sensor); 447 448 int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable) 449 { 450 int err; 451 u8 drdy_addr, drdy_mask; 452 struct st_sensor_data *sdata = iio_priv(indio_dev); 453 454 if (!sdata->sensor_settings->drdy_irq.int1.addr && 455 !sdata->sensor_settings->drdy_irq.int2.addr) { 456 /* 457 * there are some devices (e.g. LIS3MDL) where drdy line is 458 * routed to a given pin and it is not possible to select a 459 * different one. Take into account irq status register 460 * to understand if irq trigger can be properly supported 461 */ 462 if (sdata->sensor_settings->drdy_irq.stat_drdy.addr) 463 sdata->hw_irq_trigger = enable; 464 return 0; 465 } 466 467 /* Enable/Disable the interrupt generator 1. */ 468 if (sdata->sensor_settings->drdy_irq.ig1.en_addr > 0) { 469 err = st_sensors_write_data_with_mask(indio_dev, 470 sdata->sensor_settings->drdy_irq.ig1.en_addr, 471 sdata->sensor_settings->drdy_irq.ig1.en_mask, 472 (int)enable); 473 if (err < 0) 474 goto st_accel_set_dataready_irq_error; 475 } 476 477 if (sdata->drdy_int_pin == 1) { 478 drdy_addr = sdata->sensor_settings->drdy_irq.int1.addr; 479 drdy_mask = sdata->sensor_settings->drdy_irq.int1.mask; 480 } else { 481 drdy_addr = sdata->sensor_settings->drdy_irq.int2.addr; 482 drdy_mask = sdata->sensor_settings->drdy_irq.int2.mask; 483 } 484 485 /* Flag to the poll function that the hardware trigger is in use */ 486 sdata->hw_irq_trigger = enable; 487 488 /* Enable/Disable the interrupt generator for data ready. */ 489 err = st_sensors_write_data_with_mask(indio_dev, drdy_addr, 490 drdy_mask, (int)enable); 491 492 st_accel_set_dataready_irq_error: 493 return err; 494 } 495 EXPORT_SYMBOL(st_sensors_set_dataready_irq); 496 497 int st_sensors_set_fullscale_by_gain(struct iio_dev *indio_dev, int scale) 498 { 499 int err = -EINVAL, i; 500 struct st_sensor_data *sdata = iio_priv(indio_dev); 501 502 for (i = 0; i < ST_SENSORS_FULLSCALE_AVL_MAX; i++) { 503 if ((sdata->sensor_settings->fs.fs_avl[i].gain == scale) && 504 (sdata->sensor_settings->fs.fs_avl[i].gain != 0)) { 505 err = 0; 506 break; 507 } 508 } 509 if (err < 0) 510 goto st_sensors_match_scale_error; 511 512 err = st_sensors_set_fullscale(indio_dev, 513 sdata->sensor_settings->fs.fs_avl[i].num); 514 515 st_sensors_match_scale_error: 516 return err; 517 } 518 EXPORT_SYMBOL(st_sensors_set_fullscale_by_gain); 519 520 static int st_sensors_read_axis_data(struct iio_dev *indio_dev, 521 struct iio_chan_spec const *ch, int *data) 522 { 523 int err; 524 u8 *outdata; 525 struct st_sensor_data *sdata = iio_priv(indio_dev); 526 unsigned int byte_for_channel; 527 528 byte_for_channel = DIV_ROUND_UP(ch->scan_type.realbits + 529 ch->scan_type.shift, 8); 530 outdata = kmalloc(byte_for_channel, GFP_DMA | GFP_KERNEL); 531 if (!outdata) 532 return -ENOMEM; 533 534 err = regmap_bulk_read(sdata->regmap, ch->address, 535 outdata, byte_for_channel); 536 if (err < 0) 537 goto st_sensors_free_memory; 538 539 if (byte_for_channel == 1) 540 *data = (s8)*outdata; 541 else if (byte_for_channel == 2) 542 *data = (s16)get_unaligned_le16(outdata); 543 else if (byte_for_channel == 3) 544 *data = (s32)st_sensors_get_unaligned_le24(outdata); 545 546 st_sensors_free_memory: 547 kfree(outdata); 548 549 return err; 550 } 551 552 int st_sensors_read_info_raw(struct iio_dev *indio_dev, 553 struct iio_chan_spec const *ch, int *val) 554 { 555 int err; 556 struct st_sensor_data *sdata = iio_priv(indio_dev); 557 558 mutex_lock(&indio_dev->mlock); 559 if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { 560 err = -EBUSY; 561 goto out; 562 } else { 563 err = st_sensors_set_enable(indio_dev, true); 564 if (err < 0) 565 goto out; 566 567 msleep((sdata->sensor_settings->bootime * 1000) / sdata->odr); 568 err = st_sensors_read_axis_data(indio_dev, ch, val); 569 if (err < 0) 570 goto out; 571 572 *val = *val >> ch->scan_type.shift; 573 574 err = st_sensors_set_enable(indio_dev, false); 575 } 576 out: 577 mutex_unlock(&indio_dev->mlock); 578 579 return err; 580 } 581 EXPORT_SYMBOL(st_sensors_read_info_raw); 582 583 /* 584 * st_sensors_get_settings_index() - get index of the sensor settings for a 585 * specific device from list of settings 586 * @name: device name buffer reference. 587 * @list: sensor settings list. 588 * @list_length: length of sensor settings list. 589 * 590 * Return: non negative number on success (valid index), 591 * negative error code otherwise. 592 */ 593 int st_sensors_get_settings_index(const char *name, 594 const struct st_sensor_settings *list, 595 const int list_length) 596 { 597 int i, n; 598 599 for (i = 0; i < list_length; i++) { 600 for (n = 0; n < ST_SENSORS_MAX_4WAI; n++) { 601 if (strcmp(name, list[i].sensors_supported[n]) == 0) 602 return i; 603 } 604 } 605 606 return -ENODEV; 607 } 608 EXPORT_SYMBOL(st_sensors_get_settings_index); 609 610 /* 611 * st_sensors_verify_id() - verify sensor ID (WhoAmI) is matching with the 612 * expected value 613 * @indio_dev: IIO device reference. 614 * 615 * Return: 0 on success (valid sensor ID), else a negative error code. 616 */ 617 int st_sensors_verify_id(struct iio_dev *indio_dev) 618 { 619 struct st_sensor_data *sdata = iio_priv(indio_dev); 620 int wai, err; 621 622 if (sdata->sensor_settings->wai_addr) { 623 err = regmap_read(sdata->regmap, 624 sdata->sensor_settings->wai_addr, &wai); 625 if (err < 0) { 626 dev_err(&indio_dev->dev, 627 "failed to read Who-Am-I register.\n"); 628 return err; 629 } 630 631 if (sdata->sensor_settings->wai != wai) { 632 dev_err(&indio_dev->dev, 633 "%s: WhoAmI mismatch (0x%x).\n", 634 indio_dev->name, wai); 635 return -EINVAL; 636 } 637 } 638 639 return 0; 640 } 641 EXPORT_SYMBOL(st_sensors_verify_id); 642 643 ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev, 644 struct device_attribute *attr, char *buf) 645 { 646 int i, len = 0; 647 struct iio_dev *indio_dev = dev_get_drvdata(dev); 648 struct st_sensor_data *sdata = iio_priv(indio_dev); 649 650 mutex_lock(&indio_dev->mlock); 651 for (i = 0; i < ST_SENSORS_ODR_LIST_MAX; i++) { 652 if (sdata->sensor_settings->odr.odr_avl[i].hz == 0) 653 break; 654 655 len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", 656 sdata->sensor_settings->odr.odr_avl[i].hz); 657 } 658 mutex_unlock(&indio_dev->mlock); 659 buf[len - 1] = '\n'; 660 661 return len; 662 } 663 EXPORT_SYMBOL(st_sensors_sysfs_sampling_frequency_avail); 664 665 ssize_t st_sensors_sysfs_scale_avail(struct device *dev, 666 struct device_attribute *attr, char *buf) 667 { 668 int i, len = 0, q, r; 669 struct iio_dev *indio_dev = dev_get_drvdata(dev); 670 struct st_sensor_data *sdata = iio_priv(indio_dev); 671 672 mutex_lock(&indio_dev->mlock); 673 for (i = 0; i < ST_SENSORS_FULLSCALE_AVL_MAX; i++) { 674 if (sdata->sensor_settings->fs.fs_avl[i].num == 0) 675 break; 676 677 q = sdata->sensor_settings->fs.fs_avl[i].gain / 1000000; 678 r = sdata->sensor_settings->fs.fs_avl[i].gain % 1000000; 679 680 len += scnprintf(buf + len, PAGE_SIZE - len, "%u.%06u ", q, r); 681 } 682 mutex_unlock(&indio_dev->mlock); 683 buf[len - 1] = '\n'; 684 685 return len; 686 } 687 EXPORT_SYMBOL(st_sensors_sysfs_scale_avail); 688 689 MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>"); 690 MODULE_DESCRIPTION("STMicroelectronics ST-sensors core"); 691 MODULE_LICENSE("GPL v2"); 692