1fda8d26eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
223491b51SDenis Ciocca /*
323491b51SDenis Ciocca  * STMicroelectronics sensors core library driver
423491b51SDenis Ciocca  *
523491b51SDenis Ciocca  * Copyright 2012-2013 STMicroelectronics Inc.
623491b51SDenis Ciocca  *
723491b51SDenis Ciocca  * Denis Ciocca <denis.ciocca@st.com>
823491b51SDenis Ciocca  */
923491b51SDenis Ciocca 
1023491b51SDenis Ciocca #include <linux/kernel.h>
1123491b51SDenis Ciocca #include <linux/module.h>
1223491b51SDenis Ciocca #include <linux/slab.h>
1323491b51SDenis Ciocca #include <linux/delay.h>
1423491b51SDenis Ciocca #include <linux/iio/iio.h>
159c6cd755SJonathan Cameron #include <linux/mutex.h>
16efc78983SAndy Shevchenko #include <linux/property.h>
17ea7e586bSLinus Walleij #include <linux/regulator/consumer.h>
18062809efSDenis Ciocca #include <linux/regmap.h>
1923491b51SDenis Ciocca #include <asm/unaligned.h>
2023491b51SDenis Ciocca #include <linux/iio/common/st_sensors.h>
2123491b51SDenis Ciocca 
22a9fd053bSLinus Walleij #include "st_sensors_core.h"
23a9fd053bSLinus Walleij 
st_sensors_write_data_with_mask(struct iio_dev * indio_dev,u8 reg_addr,u8 mask,u8 data)24a9fd053bSLinus Walleij int st_sensors_write_data_with_mask(struct iio_dev *indio_dev,
2523491b51SDenis Ciocca 				    u8 reg_addr, u8 mask, u8 data)
2623491b51SDenis Ciocca {
2723491b51SDenis Ciocca 	struct st_sensor_data *sdata = iio_priv(indio_dev);
2823491b51SDenis Ciocca 
29062809efSDenis Ciocca 	return regmap_update_bits(sdata->regmap,
30062809efSDenis Ciocca 				  reg_addr, mask, data << __ffs(mask));
3123491b51SDenis Ciocca }
3223491b51SDenis Ciocca 
st_sensors_debugfs_reg_access(struct iio_dev * indio_dev,unsigned reg,unsigned writeval,unsigned * readval)33a0175b9cSLinus Walleij int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev,
34a0175b9cSLinus Walleij 				  unsigned reg, unsigned writeval,
35a0175b9cSLinus Walleij 				  unsigned *readval)
36a0175b9cSLinus Walleij {
37a0175b9cSLinus Walleij 	struct st_sensor_data *sdata = iio_priv(indio_dev);
38a0175b9cSLinus Walleij 	int err;
39a0175b9cSLinus Walleij 
40a0175b9cSLinus Walleij 	if (!readval)
41062809efSDenis Ciocca 		return regmap_write(sdata->regmap, reg, writeval);
42a0175b9cSLinus Walleij 
43062809efSDenis Ciocca 	err = regmap_read(sdata->regmap, reg, readval);
44a0175b9cSLinus Walleij 	if (err < 0)
45a0175b9cSLinus Walleij 		return err;
46a0175b9cSLinus Walleij 
47a0175b9cSLinus Walleij 	return 0;
48a0175b9cSLinus Walleij }
490805b512SJonathan Cameron EXPORT_SYMBOL_NS(st_sensors_debugfs_reg_access, IIO_ST_SENSORS);
50a0175b9cSLinus Walleij 
st_sensors_match_odr(struct st_sensor_settings * sensor_settings,unsigned int odr,struct st_sensor_odr_avl * odr_out)51a7ee8839SDenis CIOCCA static int st_sensors_match_odr(struct st_sensor_settings *sensor_settings,
5223491b51SDenis Ciocca 			unsigned int odr, struct st_sensor_odr_avl *odr_out)
5323491b51SDenis Ciocca {
5423491b51SDenis Ciocca 	int i, ret = -EINVAL;
5523491b51SDenis Ciocca 
5623491b51SDenis Ciocca 	for (i = 0; i < ST_SENSORS_ODR_LIST_MAX; i++) {
57a7ee8839SDenis CIOCCA 		if (sensor_settings->odr.odr_avl[i].hz == 0)
5823491b51SDenis Ciocca 			goto st_sensors_match_odr_error;
5923491b51SDenis Ciocca 
60a7ee8839SDenis CIOCCA 		if (sensor_settings->odr.odr_avl[i].hz == odr) {
61a7ee8839SDenis CIOCCA 			odr_out->hz = sensor_settings->odr.odr_avl[i].hz;
62a7ee8839SDenis CIOCCA 			odr_out->value = sensor_settings->odr.odr_avl[i].value;
6323491b51SDenis Ciocca 			ret = 0;
6423491b51SDenis Ciocca 			break;
6523491b51SDenis Ciocca 		}
6623491b51SDenis Ciocca 	}
6723491b51SDenis Ciocca 
6823491b51SDenis Ciocca st_sensors_match_odr_error:
6923491b51SDenis Ciocca 	return ret;
7023491b51SDenis Ciocca }
7123491b51SDenis Ciocca 
st_sensors_set_odr(struct iio_dev * indio_dev,unsigned int odr)7223491b51SDenis Ciocca int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr)
7323491b51SDenis Ciocca {
7447401012SMiquel Raynal 	int err = 0;
75852afe99SDenis CIOCCA 	struct st_sensor_odr_avl odr_out = {0, 0};
7623491b51SDenis Ciocca 	struct st_sensor_data *sdata = iio_priv(indio_dev);
7723491b51SDenis Ciocca 
7847401012SMiquel Raynal 	mutex_lock(&sdata->odr_lock);
7947401012SMiquel Raynal 
80e450e07cSLary Gibaud 	if (!sdata->sensor_settings->odr.mask)
8147401012SMiquel Raynal 		goto unlock_mutex;
827d245172SLorenzo Bianconi 
83a7ee8839SDenis CIOCCA 	err = st_sensors_match_odr(sdata->sensor_settings, odr, &odr_out);
8423491b51SDenis Ciocca 	if (err < 0)
8547401012SMiquel Raynal 		goto unlock_mutex;
8623491b51SDenis Ciocca 
87a7ee8839SDenis CIOCCA 	if ((sdata->sensor_settings->odr.addr ==
88a7ee8839SDenis CIOCCA 					sdata->sensor_settings->pw.addr) &&
89a7ee8839SDenis CIOCCA 				(sdata->sensor_settings->odr.mask ==
90a7ee8839SDenis CIOCCA 					sdata->sensor_settings->pw.mask)) {
9123491b51SDenis Ciocca 		if (sdata->enabled == true) {
9223491b51SDenis Ciocca 			err = st_sensors_write_data_with_mask(indio_dev,
93a7ee8839SDenis CIOCCA 				sdata->sensor_settings->odr.addr,
94a7ee8839SDenis CIOCCA 				sdata->sensor_settings->odr.mask,
9523491b51SDenis Ciocca 				odr_out.value);
9623491b51SDenis Ciocca 		} else {
9723491b51SDenis Ciocca 			err = 0;
9823491b51SDenis Ciocca 		}
9923491b51SDenis Ciocca 	} else {
10023491b51SDenis Ciocca 		err = st_sensors_write_data_with_mask(indio_dev,
101a7ee8839SDenis CIOCCA 			sdata->sensor_settings->odr.addr,
102a7ee8839SDenis CIOCCA 			sdata->sensor_settings->odr.mask,
10323491b51SDenis Ciocca 			odr_out.value);
10423491b51SDenis Ciocca 	}
10523491b51SDenis Ciocca 	if (err >= 0)
10623491b51SDenis Ciocca 		sdata->odr = odr_out.hz;
10723491b51SDenis Ciocca 
10847401012SMiquel Raynal unlock_mutex:
10947401012SMiquel Raynal 	mutex_unlock(&sdata->odr_lock);
11047401012SMiquel Raynal 
11123491b51SDenis Ciocca 	return err;
11223491b51SDenis Ciocca }
1130805b512SJonathan Cameron EXPORT_SYMBOL_NS(st_sensors_set_odr, IIO_ST_SENSORS);
11423491b51SDenis Ciocca 
st_sensors_match_fs(struct st_sensor_settings * sensor_settings,unsigned int fs,int * index_fs_avl)115a7ee8839SDenis CIOCCA static int st_sensors_match_fs(struct st_sensor_settings *sensor_settings,
11623491b51SDenis Ciocca 					unsigned int fs, int *index_fs_avl)
11723491b51SDenis Ciocca {
11823491b51SDenis Ciocca 	int i, ret = -EINVAL;
11923491b51SDenis Ciocca 
12023491b51SDenis Ciocca 	for (i = 0; i < ST_SENSORS_FULLSCALE_AVL_MAX; i++) {
121a7ee8839SDenis CIOCCA 		if (sensor_settings->fs.fs_avl[i].num == 0)
1222019738cSMartin Kelly 			return ret;
12323491b51SDenis Ciocca 
124a7ee8839SDenis CIOCCA 		if (sensor_settings->fs.fs_avl[i].num == fs) {
12523491b51SDenis Ciocca 			*index_fs_avl = i;
12623491b51SDenis Ciocca 			ret = 0;
12723491b51SDenis Ciocca 			break;
12823491b51SDenis Ciocca 		}
12923491b51SDenis Ciocca 	}
13023491b51SDenis Ciocca 
13123491b51SDenis Ciocca 	return ret;
13223491b51SDenis Ciocca }
13323491b51SDenis Ciocca 
st_sensors_set_fullscale(struct iio_dev * indio_dev,unsigned int fs)134a7ee8839SDenis CIOCCA static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs)
13523491b51SDenis Ciocca {
136852afe99SDenis CIOCCA 	int err, i = 0;
13723491b51SDenis Ciocca 	struct st_sensor_data *sdata = iio_priv(indio_dev);
13823491b51SDenis Ciocca 
139bb602f8cSGiuseppe Barba 	if (sdata->sensor_settings->fs.addr == 0)
140bb602f8cSGiuseppe Barba 		return 0;
141bb602f8cSGiuseppe Barba 
142a7ee8839SDenis CIOCCA 	err = st_sensors_match_fs(sdata->sensor_settings, fs, &i);
14323491b51SDenis Ciocca 	if (err < 0)
14423491b51SDenis Ciocca 		goto st_accel_set_fullscale_error;
14523491b51SDenis Ciocca 
14623491b51SDenis Ciocca 	err = st_sensors_write_data_with_mask(indio_dev,
147a7ee8839SDenis CIOCCA 				sdata->sensor_settings->fs.addr,
148a7ee8839SDenis CIOCCA 				sdata->sensor_settings->fs.mask,
149a7ee8839SDenis CIOCCA 				sdata->sensor_settings->fs.fs_avl[i].value);
15023491b51SDenis Ciocca 	if (err < 0)
15123491b51SDenis Ciocca 		goto st_accel_set_fullscale_error;
15223491b51SDenis Ciocca 
1531f38527dSAndy Shevchenko 	sdata->current_fullscale = &sdata->sensor_settings->fs.fs_avl[i];
15423491b51SDenis Ciocca 	return err;
15523491b51SDenis Ciocca 
15623491b51SDenis Ciocca st_accel_set_fullscale_error:
15723491b51SDenis Ciocca 	dev_err(&indio_dev->dev, "failed to set new fullscale.\n");
15823491b51SDenis Ciocca 	return err;
15923491b51SDenis Ciocca }
16023491b51SDenis Ciocca 
st_sensors_set_enable(struct iio_dev * indio_dev,bool enable)16123491b51SDenis Ciocca int st_sensors_set_enable(struct iio_dev *indio_dev, bool enable)
16223491b51SDenis Ciocca {
16323491b51SDenis Ciocca 	u8 tmp_value;
16423491b51SDenis Ciocca 	int err = -EINVAL;
165852afe99SDenis CIOCCA 	bool found = false;
166852afe99SDenis CIOCCA 	struct st_sensor_odr_avl odr_out = {0, 0};
16723491b51SDenis Ciocca 	struct st_sensor_data *sdata = iio_priv(indio_dev);
16823491b51SDenis Ciocca 
16923491b51SDenis Ciocca 	if (enable) {
170a7ee8839SDenis CIOCCA 		tmp_value = sdata->sensor_settings->pw.value_on;
171a7ee8839SDenis CIOCCA 		if ((sdata->sensor_settings->odr.addr ==
172a7ee8839SDenis CIOCCA 					sdata->sensor_settings->pw.addr) &&
173a7ee8839SDenis CIOCCA 				(sdata->sensor_settings->odr.mask ==
174a7ee8839SDenis CIOCCA 					sdata->sensor_settings->pw.mask)) {
175a7ee8839SDenis CIOCCA 			err = st_sensors_match_odr(sdata->sensor_settings,
17623491b51SDenis Ciocca 							sdata->odr, &odr_out);
17723491b51SDenis Ciocca 			if (err < 0)
17823491b51SDenis Ciocca 				goto set_enable_error;
17923491b51SDenis Ciocca 			tmp_value = odr_out.value;
18023491b51SDenis Ciocca 			found = true;
18123491b51SDenis Ciocca 		}
18223491b51SDenis Ciocca 		err = st_sensors_write_data_with_mask(indio_dev,
183a7ee8839SDenis CIOCCA 				sdata->sensor_settings->pw.addr,
184a7ee8839SDenis CIOCCA 				sdata->sensor_settings->pw.mask, tmp_value);
18523491b51SDenis Ciocca 		if (err < 0)
18623491b51SDenis Ciocca 			goto set_enable_error;
18723491b51SDenis Ciocca 
18823491b51SDenis Ciocca 		sdata->enabled = true;
18923491b51SDenis Ciocca 
19023491b51SDenis Ciocca 		if (found)
19123491b51SDenis Ciocca 			sdata->odr = odr_out.hz;
19223491b51SDenis Ciocca 	} else {
19323491b51SDenis Ciocca 		err = st_sensors_write_data_with_mask(indio_dev,
194a7ee8839SDenis CIOCCA 				sdata->sensor_settings->pw.addr,
195a7ee8839SDenis CIOCCA 				sdata->sensor_settings->pw.mask,
196a7ee8839SDenis CIOCCA 				sdata->sensor_settings->pw.value_off);
19723491b51SDenis Ciocca 		if (err < 0)
19823491b51SDenis Ciocca 			goto set_enable_error;
19923491b51SDenis Ciocca 
20023491b51SDenis Ciocca 		sdata->enabled = false;
20123491b51SDenis Ciocca 	}
20223491b51SDenis Ciocca 
20323491b51SDenis Ciocca set_enable_error:
20423491b51SDenis Ciocca 	return err;
20523491b51SDenis Ciocca }
2060805b512SJonathan Cameron EXPORT_SYMBOL_NS(st_sensors_set_enable, IIO_ST_SENSORS);
20723491b51SDenis Ciocca 
st_sensors_set_axis_enable(struct iio_dev * indio_dev,u8 axis_enable)20823491b51SDenis Ciocca int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable)
20923491b51SDenis Ciocca {
21023491b51SDenis Ciocca 	struct st_sensor_data *sdata = iio_priv(indio_dev);
2112e8325f4SLorenzo Bianconi 	int err = 0;
21223491b51SDenis Ciocca 
2132e8325f4SLorenzo Bianconi 	if (sdata->sensor_settings->enable_axis.addr)
2142e8325f4SLorenzo Bianconi 		err = st_sensors_write_data_with_mask(indio_dev,
215a7ee8839SDenis CIOCCA 				sdata->sensor_settings->enable_axis.addr,
216a7ee8839SDenis CIOCCA 				sdata->sensor_settings->enable_axis.mask,
217a7ee8839SDenis CIOCCA 				axis_enable);
2182e8325f4SLorenzo Bianconi 	return err;
21923491b51SDenis Ciocca }
2200805b512SJonathan Cameron EXPORT_SYMBOL_NS(st_sensors_set_axis_enable, IIO_ST_SENSORS);
22123491b51SDenis Ciocca 
2225363c6c1SAlexandru Ardelean 
st_sensors_power_enable(struct iio_dev * indio_dev)22314f295c8SGregor Boirie int st_sensors_power_enable(struct iio_dev *indio_dev)
224ea7e586bSLinus Walleij {
225*9e855d77SJonathan Cameron 	static const char * const regulator_names[] = { "vdd", "vddio" };
2265363c6c1SAlexandru Ardelean 	struct device *parent = indio_dev->dev.parent;
227ea7e586bSLinus Walleij 	int err;
228ea7e586bSLinus Walleij 
229ea7e586bSLinus Walleij 	/* Regulators not mandatory, but if requested we should enable them. */
230*9e855d77SJonathan Cameron 	err = devm_regulator_bulk_get_enable(parent,
231*9e855d77SJonathan Cameron 					     ARRAY_SIZE(regulator_names),
232*9e855d77SJonathan Cameron 					     regulator_names);
2335363c6c1SAlexandru Ardelean 	if (err)
234*9e855d77SJonathan Cameron 		return dev_err_probe(&indio_dev->dev, err,
235*9e855d77SJonathan Cameron 				     "unable to enable supplies\n");
2365363c6c1SAlexandru Ardelean 
237*9e855d77SJonathan Cameron 	return 0;
238ea7e586bSLinus Walleij }
2390805b512SJonathan Cameron EXPORT_SYMBOL_NS(st_sensors_power_enable, IIO_ST_SENSORS);
240ea7e586bSLinus Walleij 
st_sensors_set_drdy_int_pin(struct iio_dev * indio_dev,struct st_sensors_platform_data * pdata)24138d1c6a9SLee Jones static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev,
24223cde4d6SDenis CIOCCA 					struct st_sensors_platform_data *pdata)
24323491b51SDenis Ciocca {
24423491b51SDenis Ciocca 	struct st_sensor_data *sdata = iio_priv(indio_dev);
24523491b51SDenis Ciocca 
246d2bc4318SLinus Walleij 	/* Sensor does not support interrupts */
24775d4c6d2SLorenzo Bianconi 	if (!sdata->sensor_settings->drdy_irq.int1.addr &&
24875d4c6d2SLorenzo Bianconi 	    !sdata->sensor_settings->drdy_irq.int2.addr) {
249d2bc4318SLinus Walleij 		if (pdata->drdy_int_pin)
250d2bc4318SLinus Walleij 			dev_info(&indio_dev->dev,
25138bc8015SAndy Shevchenko 				 "DRDY on pin INT%d specified, but sensor does not support interrupts\n",
252d2bc4318SLinus Walleij 				 pdata->drdy_int_pin);
253d2bc4318SLinus Walleij 		return 0;
254d2bc4318SLinus Walleij 	}
255d2bc4318SLinus Walleij 
25623cde4d6SDenis CIOCCA 	switch (pdata->drdy_int_pin) {
25723cde4d6SDenis CIOCCA 	case 1:
25875d4c6d2SLorenzo Bianconi 		if (!sdata->sensor_settings->drdy_irq.int1.mask) {
25923cde4d6SDenis CIOCCA 			dev_err(&indio_dev->dev,
26023cde4d6SDenis CIOCCA 					"DRDY on INT1 not available.\n");
26138d1c6a9SLee Jones 			return -EINVAL;
26223cde4d6SDenis CIOCCA 		}
26323cde4d6SDenis CIOCCA 		sdata->drdy_int_pin = 1;
26423cde4d6SDenis CIOCCA 		break;
26523cde4d6SDenis CIOCCA 	case 2:
26675d4c6d2SLorenzo Bianconi 		if (!sdata->sensor_settings->drdy_irq.int2.mask) {
26723cde4d6SDenis CIOCCA 			dev_err(&indio_dev->dev,
26823cde4d6SDenis CIOCCA 					"DRDY on INT2 not available.\n");
26938d1c6a9SLee Jones 			return -EINVAL;
27023cde4d6SDenis CIOCCA 		}
27123cde4d6SDenis CIOCCA 		sdata->drdy_int_pin = 2;
27223cde4d6SDenis CIOCCA 		break;
27323cde4d6SDenis CIOCCA 	default:
27423cde4d6SDenis CIOCCA 		dev_err(&indio_dev->dev, "DRDY on pdata not valid.\n");
27538d1c6a9SLee Jones 		return -EINVAL;
27623cde4d6SDenis CIOCCA 	}
27723cde4d6SDenis CIOCCA 
2780e6f6871SLinus Walleij 	if (pdata->open_drain) {
279a542f9a0SLorenzo Bianconi 		if (!sdata->sensor_settings->drdy_irq.int1.addr_od &&
280a542f9a0SLorenzo Bianconi 		    !sdata->sensor_settings->drdy_irq.int2.addr_od)
2810e6f6871SLinus Walleij 			dev_err(&indio_dev->dev,
2820e6f6871SLinus Walleij 				"open drain requested but unsupported.\n");
2830e6f6871SLinus Walleij 		else
2840e6f6871SLinus Walleij 			sdata->int_pin_open_drain = true;
2850e6f6871SLinus Walleij 	}
2860e6f6871SLinus Walleij 
28738d1c6a9SLee Jones 	return 0;
28838d1c6a9SLee Jones }
28938d1c6a9SLee Jones 
st_sensors_dev_probe(struct device * dev,struct st_sensors_platform_data * defdata)290ecb27c5eSAndy Shevchenko static struct st_sensors_platform_data *st_sensors_dev_probe(struct device *dev,
2913ce85cc4SLinus Walleij 		struct st_sensors_platform_data *defdata)
2923ce85cc4SLinus Walleij {
2933ce85cc4SLinus Walleij 	struct st_sensors_platform_data *pdata;
2943ce85cc4SLinus Walleij 	u32 val;
2953ce85cc4SLinus Walleij 
296ecb27c5eSAndy Shevchenko 	if (!dev_fwnode(dev))
2973ce85cc4SLinus Walleij 		return NULL;
2983ce85cc4SLinus Walleij 
2993ce85cc4SLinus Walleij 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
3009960c709SColin Ian King 	if (!pdata)
3019960c709SColin Ian King 		return ERR_PTR(-ENOMEM);
302ecb27c5eSAndy Shevchenko 	if (!device_property_read_u32(dev, "st,drdy-int-pin", &val) && (val <= 2))
3033ce85cc4SLinus Walleij 		pdata->drdy_int_pin = (u8) val;
3043ce85cc4SLinus Walleij 	else
305d2bc4318SLinus Walleij 		pdata->drdy_int_pin = defdata ? defdata->drdy_int_pin : 0;
3063ce85cc4SLinus Walleij 
307ecb27c5eSAndy Shevchenko 	pdata->open_drain = device_property_read_bool(dev, "drive-open-drain");
3080e6f6871SLinus Walleij 
3093ce85cc4SLinus Walleij 	return pdata;
3103ce85cc4SLinus Walleij }
3113ce85cc4SLinus Walleij 
312efc78983SAndy Shevchenko /**
313efc78983SAndy Shevchenko  * st_sensors_dev_name_probe() - device probe for ST sensor name
314efc78983SAndy Shevchenko  * @dev: driver model representation of the device.
315efc78983SAndy Shevchenko  * @name: device name buffer reference.
316efc78983SAndy Shevchenko  * @len: device name buffer length.
317efc78983SAndy Shevchenko  *
318efc78983SAndy Shevchenko  * In effect this function matches an ID to an internal kernel
319efc78983SAndy Shevchenko  * name for a certain sensor device, so that the rest of the autodetection can
320efc78983SAndy Shevchenko  * rely on that name from this point on. I2C/SPI devices will be renamed
321efc78983SAndy Shevchenko  * to match the internal kernel convention.
322efc78983SAndy Shevchenko  */
st_sensors_dev_name_probe(struct device * dev,char * name,int len)323efc78983SAndy Shevchenko void st_sensors_dev_name_probe(struct device *dev, char *name, int len)
324efc78983SAndy Shevchenko {
325efc78983SAndy Shevchenko 	const void *match;
326efc78983SAndy Shevchenko 
327efc78983SAndy Shevchenko 	match = device_get_match_data(dev);
328efc78983SAndy Shevchenko 	if (!match)
329efc78983SAndy Shevchenko 		return;
330efc78983SAndy Shevchenko 
331efc78983SAndy Shevchenko 	/* The name from the match takes precedence if present */
332ae2c9cf1SWolfram Sang 	strscpy(name, match, len);
333efc78983SAndy Shevchenko }
3340805b512SJonathan Cameron EXPORT_SYMBOL_NS(st_sensors_dev_name_probe, IIO_ST_SENSORS);
335efc78983SAndy Shevchenko 
st_sensors_init_sensor(struct iio_dev * indio_dev,struct st_sensors_platform_data * pdata)33638d1c6a9SLee Jones int st_sensors_init_sensor(struct iio_dev *indio_dev,
33738d1c6a9SLee Jones 					struct st_sensors_platform_data *pdata)
33838d1c6a9SLee Jones {
33938d1c6a9SLee Jones 	struct st_sensor_data *sdata = iio_priv(indio_dev);
3403ce85cc4SLinus Walleij 	struct st_sensors_platform_data *of_pdata;
34138d1c6a9SLee Jones 	int err = 0;
34238d1c6a9SLee Jones 
34347401012SMiquel Raynal 	mutex_init(&sdata->odr_lock);
34447401012SMiquel Raynal 
3453ce85cc4SLinus Walleij 	/* If OF/DT pdata exists, it will take precedence of anything else */
346ecb27c5eSAndy Shevchenko 	of_pdata = st_sensors_dev_probe(indio_dev->dev.parent, pdata);
3479960c709SColin Ian King 	if (IS_ERR(of_pdata))
3489960c709SColin Ian King 		return PTR_ERR(of_pdata);
3493ce85cc4SLinus Walleij 	if (of_pdata)
3503ce85cc4SLinus Walleij 		pdata = of_pdata;
3513ce85cc4SLinus Walleij 
3523c8bf223SLee Jones 	if (pdata) {
35338d1c6a9SLee Jones 		err = st_sensors_set_drdy_int_pin(indio_dev, pdata);
3543c8bf223SLee Jones 		if (err < 0)
3553c8bf223SLee Jones 			return err;
3563c8bf223SLee Jones 	}
35738d1c6a9SLee Jones 
35823491b51SDenis Ciocca 	err = st_sensors_set_enable(indio_dev, false);
35923491b51SDenis Ciocca 	if (err < 0)
360efd9566fSLee Jones 		return err;
36123491b51SDenis Ciocca 
36299147606SCrestez Dan Leonard 	/* Disable DRDY, this might be still be enabled after reboot. */
36399147606SCrestez Dan Leonard 	err = st_sensors_set_dataready_irq(indio_dev, false);
36499147606SCrestez Dan Leonard 	if (err < 0)
36599147606SCrestez Dan Leonard 		return err;
36699147606SCrestez Dan Leonard 
367362f2f86SLee Jones 	if (sdata->current_fullscale) {
36823491b51SDenis Ciocca 		err = st_sensors_set_fullscale(indio_dev,
36923491b51SDenis Ciocca 						sdata->current_fullscale->num);
37023491b51SDenis Ciocca 		if (err < 0)
371efd9566fSLee Jones 			return err;
372362f2f86SLee Jones 	} else
373362f2f86SLee Jones 		dev_info(&indio_dev->dev, "Full-scale not possible\n");
37423491b51SDenis Ciocca 
37523491b51SDenis Ciocca 	err = st_sensors_set_odr(indio_dev, sdata->odr);
37623491b51SDenis Ciocca 	if (err < 0)
377efd9566fSLee Jones 		return err;
37823491b51SDenis Ciocca 
37923491b51SDenis Ciocca 	/* set BDU */
380bb60646cSLinus Walleij 	if (sdata->sensor_settings->bdu.addr) {
38123491b51SDenis Ciocca 		err = st_sensors_write_data_with_mask(indio_dev,
382a7ee8839SDenis CIOCCA 					sdata->sensor_settings->bdu.addr,
383a7ee8839SDenis CIOCCA 					sdata->sensor_settings->bdu.mask, true);
38423491b51SDenis Ciocca 		if (err < 0)
385efd9566fSLee Jones 			return err;
386bb60646cSLinus Walleij 	}
38723491b51SDenis Ciocca 
38865e4345cSLinus Walleij 	/* set DAS */
38965e4345cSLinus Walleij 	if (sdata->sensor_settings->das.addr) {
39065e4345cSLinus Walleij 		err = st_sensors_write_data_with_mask(indio_dev,
39165e4345cSLinus Walleij 					sdata->sensor_settings->das.addr,
39265e4345cSLinus Walleij 					sdata->sensor_settings->das.mask, 1);
39365e4345cSLinus Walleij 		if (err < 0)
39465e4345cSLinus Walleij 			return err;
39565e4345cSLinus Walleij 	}
39665e4345cSLinus Walleij 
3970e6f6871SLinus Walleij 	if (sdata->int_pin_open_drain) {
398a542f9a0SLorenzo Bianconi 		u8 addr, mask;
399a542f9a0SLorenzo Bianconi 
400a542f9a0SLorenzo Bianconi 		if (sdata->drdy_int_pin == 1) {
401a542f9a0SLorenzo Bianconi 			addr = sdata->sensor_settings->drdy_irq.int1.addr_od;
402a542f9a0SLorenzo Bianconi 			mask = sdata->sensor_settings->drdy_irq.int1.mask_od;
403a542f9a0SLorenzo Bianconi 		} else {
404a542f9a0SLorenzo Bianconi 			addr = sdata->sensor_settings->drdy_irq.int2.addr_od;
405a542f9a0SLorenzo Bianconi 			mask = sdata->sensor_settings->drdy_irq.int2.mask_od;
406a542f9a0SLorenzo Bianconi 		}
407a542f9a0SLorenzo Bianconi 
4080e6f6871SLinus Walleij 		dev_info(&indio_dev->dev,
409a542f9a0SLorenzo Bianconi 			 "set interrupt line to open drain mode on pin %d\n",
410a542f9a0SLorenzo Bianconi 			 sdata->drdy_int_pin);
411a542f9a0SLorenzo Bianconi 		err = st_sensors_write_data_with_mask(indio_dev, addr,
412a542f9a0SLorenzo Bianconi 						      mask, 1);
4130e6f6871SLinus Walleij 		if (err < 0)
4140e6f6871SLinus Walleij 			return err;
4150e6f6871SLinus Walleij 	}
4160e6f6871SLinus Walleij 
41723491b51SDenis Ciocca 	err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
41823491b51SDenis Ciocca 
41923491b51SDenis Ciocca 	return err;
42023491b51SDenis Ciocca }
4210805b512SJonathan Cameron EXPORT_SYMBOL_NS(st_sensors_init_sensor, IIO_ST_SENSORS);
42223491b51SDenis Ciocca 
st_sensors_set_dataready_irq(struct iio_dev * indio_dev,bool enable)42323491b51SDenis Ciocca int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable)
42423491b51SDenis Ciocca {
42523491b51SDenis Ciocca 	int err;
42675d4c6d2SLorenzo Bianconi 	u8 drdy_addr, drdy_mask;
42723491b51SDenis Ciocca 	struct st_sensor_data *sdata = iio_priv(indio_dev);
42823491b51SDenis Ciocca 
42975d4c6d2SLorenzo Bianconi 	if (!sdata->sensor_settings->drdy_irq.int1.addr &&
43075d4c6d2SLorenzo Bianconi 	    !sdata->sensor_settings->drdy_irq.int2.addr) {
431c65e3d6eSLorenzo Bianconi 		/*
432c65e3d6eSLorenzo Bianconi 		 * there are some devices (e.g. LIS3MDL) where drdy line is
433c65e3d6eSLorenzo Bianconi 		 * routed to a given pin and it is not possible to select a
434c65e3d6eSLorenzo Bianconi 		 * different one. Take into account irq status register
435c65e3d6eSLorenzo Bianconi 		 * to understand if irq trigger can be properly supported
436c65e3d6eSLorenzo Bianconi 		 */
437e72a0601SLorenzo Bianconi 		if (sdata->sensor_settings->drdy_irq.stat_drdy.addr)
438c65e3d6eSLorenzo Bianconi 			sdata->hw_irq_trigger = enable;
43938d1c6a9SLee Jones 		return 0;
440c65e3d6eSLorenzo Bianconi 	}
44138d1c6a9SLee Jones 
44223491b51SDenis Ciocca 	/* Enable/Disable the interrupt generator 1. */
443a7ee8839SDenis CIOCCA 	if (sdata->sensor_settings->drdy_irq.ig1.en_addr > 0) {
44423491b51SDenis Ciocca 		err = st_sensors_write_data_with_mask(indio_dev,
445a7ee8839SDenis CIOCCA 				sdata->sensor_settings->drdy_irq.ig1.en_addr,
446a7ee8839SDenis CIOCCA 				sdata->sensor_settings->drdy_irq.ig1.en_mask,
447a7ee8839SDenis CIOCCA 				(int)enable);
44823491b51SDenis Ciocca 		if (err < 0)
44923491b51SDenis Ciocca 			goto st_accel_set_dataready_irq_error;
45023491b51SDenis Ciocca 	}
45123491b51SDenis Ciocca 
45275d4c6d2SLorenzo Bianconi 	if (sdata->drdy_int_pin == 1) {
45375d4c6d2SLorenzo Bianconi 		drdy_addr = sdata->sensor_settings->drdy_irq.int1.addr;
45475d4c6d2SLorenzo Bianconi 		drdy_mask = sdata->sensor_settings->drdy_irq.int1.mask;
45575d4c6d2SLorenzo Bianconi 	} else {
45675d4c6d2SLorenzo Bianconi 		drdy_addr = sdata->sensor_settings->drdy_irq.int2.addr;
45775d4c6d2SLorenzo Bianconi 		drdy_mask = sdata->sensor_settings->drdy_irq.int2.mask;
45875d4c6d2SLorenzo Bianconi 	}
45923cde4d6SDenis CIOCCA 
46065925b65SLinus Walleij 	/* Flag to the poll function that the hardware trigger is in use */
46165925b65SLinus Walleij 	sdata->hw_irq_trigger = enable;
46265925b65SLinus Walleij 
46323491b51SDenis Ciocca 	/* Enable/Disable the interrupt generator for data ready. */
46475d4c6d2SLorenzo Bianconi 	err = st_sensors_write_data_with_mask(indio_dev, drdy_addr,
465a7ee8839SDenis CIOCCA 					      drdy_mask, (int)enable);
46623491b51SDenis Ciocca 
46723491b51SDenis Ciocca st_accel_set_dataready_irq_error:
46823491b51SDenis Ciocca 	return err;
46923491b51SDenis Ciocca }
4700805b512SJonathan Cameron EXPORT_SYMBOL_NS(st_sensors_set_dataready_irq, IIO_ST_SENSORS);
47123491b51SDenis Ciocca 
st_sensors_set_fullscale_by_gain(struct iio_dev * indio_dev,int scale)47223491b51SDenis Ciocca int st_sensors_set_fullscale_by_gain(struct iio_dev *indio_dev, int scale)
47323491b51SDenis Ciocca {
47423491b51SDenis Ciocca 	int err = -EINVAL, i;
47523491b51SDenis Ciocca 	struct st_sensor_data *sdata = iio_priv(indio_dev);
47623491b51SDenis Ciocca 
47723491b51SDenis Ciocca 	for (i = 0; i < ST_SENSORS_FULLSCALE_AVL_MAX; i++) {
478a7ee8839SDenis CIOCCA 		if ((sdata->sensor_settings->fs.fs_avl[i].gain == scale) &&
479a7ee8839SDenis CIOCCA 				(sdata->sensor_settings->fs.fs_avl[i].gain != 0)) {
48023491b51SDenis Ciocca 			err = 0;
48123491b51SDenis Ciocca 			break;
48223491b51SDenis Ciocca 		}
48323491b51SDenis Ciocca 	}
48423491b51SDenis Ciocca 	if (err < 0)
48523491b51SDenis Ciocca 		goto st_sensors_match_scale_error;
48623491b51SDenis Ciocca 
48723491b51SDenis Ciocca 	err = st_sensors_set_fullscale(indio_dev,
488a7ee8839SDenis CIOCCA 				sdata->sensor_settings->fs.fs_avl[i].num);
48923491b51SDenis Ciocca 
49023491b51SDenis Ciocca st_sensors_match_scale_error:
49123491b51SDenis Ciocca 	return err;
49223491b51SDenis Ciocca }
4930805b512SJonathan Cameron EXPORT_SYMBOL_NS(st_sensors_set_fullscale_by_gain, IIO_ST_SENSORS);
49423491b51SDenis Ciocca 
st_sensors_read_axis_data(struct iio_dev * indio_dev,struct iio_chan_spec const * ch,int * data)49523491b51SDenis Ciocca static int st_sensors_read_axis_data(struct iio_dev *indio_dev,
496607a568aSDenis CIOCCA 				     struct iio_chan_spec const *ch, int *data)
49723491b51SDenis Ciocca {
49823491b51SDenis Ciocca 	int err;
499607a568aSDenis CIOCCA 	u8 *outdata;
50023491b51SDenis Ciocca 	struct st_sensor_data *sdata = iio_priv(indio_dev);
50165c8aea0SLorenzo Bianconi 	unsigned int byte_for_channel;
502607a568aSDenis CIOCCA 
50365c8aea0SLorenzo Bianconi 	byte_for_channel = DIV_ROUND_UP(ch->scan_type.realbits +
50465c8aea0SLorenzo Bianconi 					ch->scan_type.shift, 8);
505062809efSDenis Ciocca 	outdata = kmalloc(byte_for_channel, GFP_DMA | GFP_KERNEL);
506caf5ca12SLee Jones 	if (!outdata)
507caf5ca12SLee Jones 		return -ENOMEM;
50823491b51SDenis Ciocca 
509062809efSDenis Ciocca 	err = regmap_bulk_read(sdata->regmap, ch->address,
510062809efSDenis Ciocca 			       outdata, byte_for_channel);
51123491b51SDenis Ciocca 	if (err < 0)
512607a568aSDenis CIOCCA 		goto st_sensors_free_memory;
51323491b51SDenis Ciocca 
5144861a007SLinus Walleij 	if (byte_for_channel == 1)
5154861a007SLinus Walleij 		*data = (s8)*outdata;
5164861a007SLinus Walleij 	else if (byte_for_channel == 2)
51723491b51SDenis Ciocca 		*data = (s16)get_unaligned_le16(outdata);
518607a568aSDenis CIOCCA 	else if (byte_for_channel == 3)
5193009fb9cSAndy Shevchenko 		*data = (s32)sign_extend32(get_unaligned_le24(outdata), 23);
52023491b51SDenis Ciocca 
521607a568aSDenis CIOCCA st_sensors_free_memory:
522607a568aSDenis CIOCCA 	kfree(outdata);
523caf5ca12SLee Jones 
52423491b51SDenis Ciocca 	return err;
52523491b51SDenis Ciocca }
52623491b51SDenis Ciocca 
st_sensors_read_info_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * ch,int * val)52723491b51SDenis Ciocca int st_sensors_read_info_raw(struct iio_dev *indio_dev,
52823491b51SDenis Ciocca 				struct iio_chan_spec const *ch, int *val)
52923491b51SDenis Ciocca {
53023491b51SDenis Ciocca 	int err;
53123491b51SDenis Ciocca 	struct st_sensor_data *sdata = iio_priv(indio_dev);
53223491b51SDenis Ciocca 
5332da03b43SMiquel Raynal 	err = iio_device_claim_direct_mode(indio_dev);
5342da03b43SMiquel Raynal 	if (err)
5352da03b43SMiquel Raynal 		return err;
5362da03b43SMiquel Raynal 
53747401012SMiquel Raynal 	mutex_lock(&sdata->odr_lock);
5382da03b43SMiquel Raynal 
53923491b51SDenis Ciocca 	err = st_sensors_set_enable(indio_dev, true);
5402da03b43SMiquel Raynal 	if (err < 0)
5415bb8e72dSLee Jones 		goto out;
54223491b51SDenis Ciocca 
543a7ee8839SDenis CIOCCA 	msleep((sdata->sensor_settings->bootime * 1000) / sdata->odr);
544607a568aSDenis CIOCCA 	err = st_sensors_read_axis_data(indio_dev, ch, val);
5452da03b43SMiquel Raynal 	if (err < 0)
5465bb8e72dSLee Jones 		goto out;
54723491b51SDenis Ciocca 
54823491b51SDenis Ciocca 	*val = *val >> ch->scan_type.shift;
549d61a04dcSDenis CIOCCA 
550d61a04dcSDenis CIOCCA 	err = st_sensors_set_enable(indio_dev, false);
5512da03b43SMiquel Raynal 
5525bb8e72dSLee Jones out:
5532da03b43SMiquel Raynal 	mutex_unlock(&sdata->odr_lock);
5542da03b43SMiquel Raynal 	iio_device_release_direct_mode(indio_dev);
55523491b51SDenis Ciocca 
55623491b51SDenis Ciocca 	return err;
55723491b51SDenis Ciocca }
5580805b512SJonathan Cameron EXPORT_SYMBOL_NS(st_sensors_read_info_raw, IIO_ST_SENSORS);
55923491b51SDenis Ciocca 
560a090965bSDenis Ciocca /*
561a090965bSDenis Ciocca  * st_sensors_get_settings_index() - get index of the sensor settings for a
562a090965bSDenis Ciocca  *				     specific device from list of settings
563a090965bSDenis Ciocca  * @name: device name buffer reference.
564a090965bSDenis Ciocca  * @list: sensor settings list.
565a090965bSDenis Ciocca  * @list_length: length of sensor settings list.
566a090965bSDenis Ciocca  *
567a090965bSDenis Ciocca  * Return: non negative number on success (valid index),
568a090965bSDenis Ciocca  *	   negative error code otherwise.
569a090965bSDenis Ciocca  */
st_sensors_get_settings_index(const char * name,const struct st_sensor_settings * list,const int list_length)570a090965bSDenis Ciocca int st_sensors_get_settings_index(const char *name,
571a090965bSDenis Ciocca 				  const struct st_sensor_settings *list,
572a090965bSDenis Ciocca 				  const int list_length)
573a090965bSDenis Ciocca {
574a090965bSDenis Ciocca 	int i, n;
575a090965bSDenis Ciocca 
576a090965bSDenis Ciocca 	for (i = 0; i < list_length; i++) {
577a090965bSDenis Ciocca 		for (n = 0; n < ST_SENSORS_MAX_4WAI; n++) {
578a090965bSDenis Ciocca 			if (strcmp(name, list[i].sensors_supported[n]) == 0)
579a090965bSDenis Ciocca 				return i;
580a090965bSDenis Ciocca 		}
581a090965bSDenis Ciocca 	}
582a090965bSDenis Ciocca 
583a090965bSDenis Ciocca 	return -ENODEV;
584a090965bSDenis Ciocca }
5850805b512SJonathan Cameron EXPORT_SYMBOL_NS(st_sensors_get_settings_index, IIO_ST_SENSORS);
586a090965bSDenis Ciocca 
5871ecd245eSDenis Ciocca /*
5881ecd245eSDenis Ciocca  * st_sensors_verify_id() - verify sensor ID (WhoAmI) is matching with the
5891ecd245eSDenis Ciocca  *			    expected value
5901ecd245eSDenis Ciocca  * @indio_dev: IIO device reference.
5911ecd245eSDenis Ciocca  *
5921ecd245eSDenis Ciocca  * Return: 0 on success (valid sensor ID), else a negative error code.
5931ecd245eSDenis Ciocca  */
st_sensors_verify_id(struct iio_dev * indio_dev)5941ecd245eSDenis Ciocca int st_sensors_verify_id(struct iio_dev *indio_dev)
59523491b51SDenis Ciocca {
59623491b51SDenis Ciocca 	struct st_sensor_data *sdata = iio_priv(indio_dev);
597062809efSDenis Ciocca 	int wai, err;
59823491b51SDenis Ciocca 
5991ecd245eSDenis Ciocca 	if (sdata->sensor_settings->wai_addr) {
600062809efSDenis Ciocca 		err = regmap_read(sdata->regmap,
601062809efSDenis Ciocca 				  sdata->sensor_settings->wai_addr, &wai);
60223491b51SDenis Ciocca 		if (err < 0) {
6034e68cfbfSJonathan Cameron 			dev_err(&indio_dev->dev,
6044e68cfbfSJonathan Cameron 				"failed to read Who-Am-I register.\n");
605bc27381eSGiuseppe Barba 			return err;
60623491b51SDenis Ciocca 		}
60723491b51SDenis Ciocca 
6081ecd245eSDenis Ciocca 		if (sdata->sensor_settings->wai != wai) {
6094e68cfbfSJonathan Cameron 			dev_err(&indio_dev->dev,
6104e68cfbfSJonathan Cameron 				"%s: WhoAmI mismatch (0x%x).\n",
6115e02bac3SLinus Walleij 				indio_dev->name, wai);
612bc27381eSGiuseppe Barba 			return -EINVAL;
61323491b51SDenis Ciocca 		}
6144e68cfbfSJonathan Cameron 	}
61523491b51SDenis Ciocca 
6161ecd245eSDenis Ciocca 	return 0;
61723491b51SDenis Ciocca }
6180805b512SJonathan Cameron EXPORT_SYMBOL_NS(st_sensors_verify_id, IIO_ST_SENSORS);
61923491b51SDenis Ciocca 
st_sensors_sysfs_sampling_frequency_avail(struct device * dev,struct device_attribute * attr,char * buf)62023491b51SDenis Ciocca ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev,
62123491b51SDenis Ciocca 				struct device_attribute *attr, char *buf)
62223491b51SDenis Ciocca {
6234d2e4fc2SDenis CIOCCA 	int i, len = 0;
6244498863cSLars-Peter Clausen 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
6254d2e4fc2SDenis CIOCCA 	struct st_sensor_data *sdata = iio_priv(indio_dev);
62623491b51SDenis Ciocca 
6274d2e4fc2SDenis CIOCCA 	for (i = 0; i < ST_SENSORS_ODR_LIST_MAX; i++) {
628a7ee8839SDenis CIOCCA 		if (sdata->sensor_settings->odr.odr_avl[i].hz == 0)
6294d2e4fc2SDenis CIOCCA 			break;
6304d2e4fc2SDenis CIOCCA 
6314d2e4fc2SDenis CIOCCA 		len += scnprintf(buf + len, PAGE_SIZE - len, "%d ",
632a7ee8839SDenis CIOCCA 				sdata->sensor_settings->odr.odr_avl[i].hz);
6334d2e4fc2SDenis CIOCCA 	}
6344d2e4fc2SDenis CIOCCA 	buf[len - 1] = '\n';
6354d2e4fc2SDenis CIOCCA 
6364d2e4fc2SDenis CIOCCA 	return len;
63723491b51SDenis Ciocca }
6380805b512SJonathan Cameron EXPORT_SYMBOL_NS(st_sensors_sysfs_sampling_frequency_avail, IIO_ST_SENSORS);
63923491b51SDenis Ciocca 
st_sensors_sysfs_scale_avail(struct device * dev,struct device_attribute * attr,char * buf)64023491b51SDenis Ciocca ssize_t st_sensors_sysfs_scale_avail(struct device *dev,
64123491b51SDenis Ciocca 				struct device_attribute *attr, char *buf)
64223491b51SDenis Ciocca {
643d304286aSLorenzo Bianconi 	int i, len = 0, q, r;
6444498863cSLars-Peter Clausen 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
6454d2e4fc2SDenis CIOCCA 	struct st_sensor_data *sdata = iio_priv(indio_dev);
64623491b51SDenis Ciocca 
6474d2e4fc2SDenis CIOCCA 	for (i = 0; i < ST_SENSORS_FULLSCALE_AVL_MAX; i++) {
648a7ee8839SDenis CIOCCA 		if (sdata->sensor_settings->fs.fs_avl[i].num == 0)
6494d2e4fc2SDenis CIOCCA 			break;
6504d2e4fc2SDenis CIOCCA 
651d304286aSLorenzo Bianconi 		q = sdata->sensor_settings->fs.fs_avl[i].gain / 1000000;
652d304286aSLorenzo Bianconi 		r = sdata->sensor_settings->fs.fs_avl[i].gain % 1000000;
653d304286aSLorenzo Bianconi 
654d304286aSLorenzo Bianconi 		len += scnprintf(buf + len, PAGE_SIZE - len, "%u.%06u ", q, r);
6554d2e4fc2SDenis CIOCCA 	}
6564d2e4fc2SDenis CIOCCA 	buf[len - 1] = '\n';
6574d2e4fc2SDenis CIOCCA 
6584d2e4fc2SDenis CIOCCA 	return len;
65923491b51SDenis Ciocca }
6600805b512SJonathan Cameron EXPORT_SYMBOL_NS(st_sensors_sysfs_scale_avail, IIO_ST_SENSORS);
66123491b51SDenis Ciocca 
66223491b51SDenis Ciocca MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
66323491b51SDenis Ciocca MODULE_DESCRIPTION("STMicroelectronics ST-sensors core");
66423491b51SDenis Ciocca MODULE_LICENSE("GPL v2");
665