Commit d3532d69 authored by Ramona Bolboaca's avatar Ramona Bolboaca Committed by Jonathan Cameron
Browse files

drivers: iio: accel: Add support for ADXL359 device

parent b311d2e1
Loading
Loading
Loading
Loading
+19 −1
Original line number Diff line number Diff line
@@ -10,12 +10,30 @@

#include <linux/regmap.h>

enum adxl355_device_type {
	ADXL355,
	ADXL359,
};

struct adxl355_fractional_type {
	int integer;
	int decimal;
};

struct device;

struct adxl355_chip_info {
	const char			*name;
	u8				part_id;
	struct adxl355_fractional_type	accel_scale;
	struct adxl355_fractional_type	temp_offset;
};

extern const struct regmap_access_table adxl355_readable_regs_tbl;
extern const struct regmap_access_table adxl355_writeable_regs_tbl;
extern const struct adxl355_chip_info adxl35x_chip_info[];

int adxl355_core_probe(struct device *dev, struct regmap *regmap,
		       const char *name);
		       const struct adxl355_chip_info *chip_info);

#endif /* _ADXL355_H_ */
+68 −19
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@
#define ADXL355_DEVID_AD_VAL		0xAD
#define ADXL355_DEVID_MST_VAL		0x1D
#define ADXL355_PARTID_VAL		0xED
#define ADXL359_PARTID_VAL		0xE9
#define ADXL355_RESET_CODE		0x52

static const struct regmap_range adxl355_read_reg_range[] = {
@@ -83,6 +84,60 @@ const struct regmap_access_table adxl355_writeable_regs_tbl = {
};
EXPORT_SYMBOL_NS_GPL(adxl355_writeable_regs_tbl, IIO_ADXL355);

const struct adxl355_chip_info adxl35x_chip_info[] = {
	[ADXL355] = {
		.name = "adxl355",
		.part_id = ADXL355_PARTID_VAL,
		/*
		 * At +/- 2g with 20-bit resolution, scale is given in datasheet
		 * as 3.9ug/LSB = 0.0000039 * 9.80665 = 0.00003824593 m/s^2.
		 */
		.accel_scale = {
			.integer = 0,
			.decimal = 38245,
		},
		/*
		 * The datasheet defines an intercept of 1885 LSB at 25 degC
		 * and a slope of -9.05 LSB/C. The following formula can be used
		 * to find the temperature:
		 * Temp = ((RAW - 1885)/(-9.05)) + 25 but this doesn't follow
		 * the format of the IIO which is Temp = (RAW + OFFSET) * SCALE.
		 * Hence using some rearranging we get the scale as -110.497238
		 * and offset as -2111.25.
		 */
		.temp_offset = {
			.integer =  -2111,
			.decimal = 250000,
		},
	},
	[ADXL359] = {
		.name = "adxl359",
		.part_id = ADXL359_PARTID_VAL,
		/*
		 * At +/- 10g with 20-bit resolution, scale is given in datasheet
		 * as 19.5ug/LSB = 0.0000195 * 9.80665 = 0.0.00019122967 m/s^2.
		 */
		.accel_scale = {
			.integer = 0,
			.decimal = 191229,
		},
		/*
		 * The datasheet defines an intercept of 1852 LSB at 25 degC
		 * and a slope of -9.05 LSB/C. The following formula can be used
		 * to find the temperature:
		 * Temp = ((RAW - 1852)/(-9.05)) + 25 but this doesn't follow
		 * the format of the IIO which is Temp = (RAW + OFFSET) * SCALE.
		 * Hence using some rearranging we get the scale as -110.497238
		 * and offset as -2079.25.
		 */
		.temp_offset = {
			.integer = -2079,
			.decimal = 250000,
		},
	},
};
EXPORT_SYMBOL_NS_GPL(adxl35x_chip_info, IIO_ADXL355);

enum adxl355_op_mode {
	ADXL355_MEASUREMENT,
	ADXL355_STANDBY,
@@ -162,6 +217,7 @@ static const struct adxl355_chan_info adxl355_chans[] = {
};

struct adxl355_data {
	const struct adxl355_chip_info *chip_info;
	struct regmap *regmap;
	struct device *dev;
	struct mutex lock; /* lock to protect op_mode */
@@ -456,33 +512,25 @@ static int adxl355_read_raw(struct iio_dev *indio_dev,

	case IIO_CHAN_INFO_SCALE:
		switch (chan->type) {
		case IIO_TEMP:
			/*
		 * The datasheet defines an intercept of 1885 LSB at 25 degC
		 * and a slope of -9.05 LSB/C. The following formula can be used
		 * to find the temperature:
		 * Temp = ((RAW - 1885)/(-9.05)) + 25 but this doesn't follow
		 * the format of the IIO which is Temp = (RAW + OFFSET) * SCALE.
		 * Hence using some rearranging we get the scale as -110.497238
		 * and offset as -2111.25.
			 * Temperature scale is -110.497238.
			 * See the detailed explanation in adxl35x_chip_info
			 * definition above.
			 */
		case IIO_TEMP:
			*val = -110;
			*val2 = 497238;
			return IIO_VAL_INT_PLUS_MICRO;
		/*
		 * At +/- 2g with 20-bit resolution, scale is given in datasheet
		 * as 3.9ug/LSB = 0.0000039 * 9.80665 = 0.00003824593 m/s^2.
		 */
		case IIO_ACCEL:
			*val = 0;
			*val2 = 38245;
			*val = data->chip_info->accel_scale.integer;
			*val2 = data->chip_info->accel_scale.decimal;
			return IIO_VAL_INT_PLUS_NANO;
		default:
			return -EINVAL;
		}
	case IIO_CHAN_INFO_OFFSET:
		*val = -2111;
		*val2 = 250000;
		*val = data->chip_info->temp_offset.integer;
		*val2 = data->chip_info->temp_offset.decimal;
		return IIO_VAL_INT_PLUS_MICRO;
	case IIO_CHAN_INFO_CALIBBIAS:
		*val = sign_extend32(data->calibbias[chan->address], 15);
@@ -705,7 +753,7 @@ static int adxl355_probe_trigger(struct iio_dev *indio_dev, int irq)
}

int adxl355_core_probe(struct device *dev, struct regmap *regmap,
		       const char *name)
		       const struct adxl355_chip_info *chip_info)
{
	struct adxl355_data *data;
	struct iio_dev *indio_dev;
@@ -720,9 +768,10 @@ int adxl355_core_probe(struct device *dev, struct regmap *regmap,
	data->regmap = regmap;
	data->dev = dev;
	data->op_mode = ADXL355_STANDBY;
	data->chip_info = chip_info;
	mutex_init(&data->lock);

	indio_dev->name = name;
	indio_dev->name = chip_info->name;
	indio_dev->info = &adxl355_info;
	indio_dev->modes = INDIO_DIRECT_MODE;
	indio_dev->channels = adxl355_channels;
+19 −3
Original line number Diff line number Diff line
@@ -23,6 +23,20 @@ static const struct regmap_config adxl355_i2c_regmap_config = {
static int adxl355_i2c_probe(struct i2c_client *client)
{
	struct regmap *regmap;
	const struct adxl355_chip_info *chip_data;
	const struct i2c_device_id *adxl355;

	chip_data = device_get_match_data(&client->dev);
	if (!chip_data) {
		adxl355 = to_i2c_driver(client->dev.driver)->id_table;
		if (!adxl355)
			return -EINVAL;

		chip_data = (void *)i2c_match_id(adxl355, client)->driver_data;

		if (!chip_data)
			return -EINVAL;
	}

	regmap = devm_regmap_init_i2c(client, &adxl355_i2c_regmap_config);
	if (IS_ERR(regmap)) {
@@ -32,17 +46,19 @@ static int adxl355_i2c_probe(struct i2c_client *client)
		return PTR_ERR(regmap);
	}

	return adxl355_core_probe(&client->dev, regmap, client->name);
	return adxl355_core_probe(&client->dev, regmap, chip_data);
}

static const struct i2c_device_id adxl355_i2c_id[] = {
	{ "adxl355", 0 },
	{ "adxl355", (kernel_ulong_t)&adxl35x_chip_info[ADXL355] },
	{ "adxl359", (kernel_ulong_t)&adxl35x_chip_info[ADXL359] },
	{ }
};
MODULE_DEVICE_TABLE(i2c, adxl355_i2c_id);

static const struct of_device_id adxl355_of_match[] = {
	{ .compatible = "adi,adxl355" },
	{ .compatible = "adi,adxl355", .data = &adxl35x_chip_info[ADXL355] },
	{ .compatible = "adi,adxl359", .data = &adxl35x_chip_info[ADXL359] },
	{ }
};
MODULE_DEVICE_TABLE(of, adxl355_of_match);
+15 −4
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
#include <linux/mod_devicetable.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <linux/property.h>

#include "adxl355.h"

@@ -24,9 +25,17 @@ static const struct regmap_config adxl355_spi_regmap_config = {

static int adxl355_spi_probe(struct spi_device *spi)
{
	const struct spi_device_id *id = spi_get_device_id(spi);
	const struct adxl355_chip_info *chip_data;
	struct regmap *regmap;

	chip_data = device_get_match_data(&spi->dev);
	if (!chip_data) {
		chip_data = (void *)spi_get_device_id(spi)->driver_data;

		if (!chip_data)
			return -EINVAL;
	}

	regmap = devm_regmap_init_spi(spi, &adxl355_spi_regmap_config);
	if (IS_ERR(regmap)) {
		dev_err(&spi->dev, "Error initializing spi regmap: %ld\n",
@@ -35,17 +44,19 @@ static int adxl355_spi_probe(struct spi_device *spi)
		return PTR_ERR(regmap);
	}

	return adxl355_core_probe(&spi->dev, regmap, id->name);
	return adxl355_core_probe(&spi->dev, regmap, chip_data);
}

static const struct spi_device_id adxl355_spi_id[] = {
	{ "adxl355", 0 },
	{ "adxl355", (kernel_ulong_t)&adxl35x_chip_info[ADXL355] },
	{ "adxl359", (kernel_ulong_t)&adxl35x_chip_info[ADXL359] },
	{ }
};
MODULE_DEVICE_TABLE(spi, adxl355_spi_id);

static const struct of_device_id adxl355_of_match[] = {
	{ .compatible = "adi,adxl355" },
	{ .compatible = "adi,adxl355", .data = &adxl35x_chip_info[ADXL355] },
	{ .compatible = "adi,adxl359", .data = &adxl35x_chip_info[ADXL359] },
	{ }
};
MODULE_DEVICE_TABLE(of, adxl355_of_match);