diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-06 04:16:23 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-06 04:16:23 +0300 |
commit | c6a677c6f37bb7abc85ba7e3465e82b9f7eb1d91 (patch) | |
tree | 9d0d4bb2e150837297cddc5be7f1b4950e9ab228 /drivers/iio/accel | |
parent | e87d51ac61f88ae44fe14b34abe08566032d726b (diff) | |
parent | 11270059e8d0b6f80801fac910c4ef751ca05c4c (diff) | |
download | linux-c6a677c6f37bb7abc85ba7e3465e82b9f7eb1d91.tar.xz |
Merge tag 'staging-4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
Pull staging/IIO updates from Greg KH:
"Here is the big staging tree update for 4.12-rc1.
It's a big one, adding about 350k new lines of crap^Wcode, mostly all
in a big dump of media drivers from Intel. But there's other new
drivers in here as well, yet-another-wifi driver, new IIO drivers, and
a new crypto accelerator.
We also deleted a bunch of stuff, mostly in patch cleanups, but also
the Android ION code has shrunk a lot, and the Android low memory
killer driver was finally deleted, much to the celebration of the -mm
developers.
All of these have been in linux-next with a few build issues that will
show up when you merge to your tree"
Merge conflicts in the new rtl8723bs driver (due to the wifi changes
this merge window) handled as per linux-next, courtesy of Stephen
Rothwell.
* tag 'staging-4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (1182 commits)
staging: fsl-mc/dpio: add cpu <--> LE conversion for dpaa2_fd
staging: ks7010: remove line continuations in quoted strings
staging: vt6656: use tabs instead of spaces
staging: android: ion: Fix unnecessary initialization of static variable
staging: media: atomisp: fix range checking on clk_num
staging: media: atomisp: fix misspelled word in comment
staging: media: atomisp: kmap() can't fail
staging: atomisp: remove #ifdef for runtime PM functions
staging: atomisp: satm include directory is gone
atomisp: remove some more unused files
atomisp: remove hmm_load/store/clear indirections
atomisp: kill off mmgr_free
atomisp: clean up the hmm init/cleanup indirections
atomisp: handle allocation calls before init in the hmm layer
staging: fsl-dpaa2/eth: Add maintainer for Ethernet driver
staging: fsl-dpaa2/eth: Add TODO file
staging: fsl-dpaa2/eth: Add trace points
staging: fsl-dpaa2/eth: Add driver specific stats
staging: fsl-dpaa2/eth: Add ethtool support
staging: fsl-dpaa2/eth: Add Freescale DPAA2 Ethernet driver
...
Diffstat (limited to 'drivers/iio/accel')
-rw-r--r-- | drivers/iio/accel/Kconfig | 31 | ||||
-rw-r--r-- | drivers/iio/accel/Makefile | 3 | ||||
-rw-r--r-- | drivers/iio/accel/adxl345.h | 18 | ||||
-rw-r--r-- | drivers/iio/accel/adxl345_core.c | 179 | ||||
-rw-r--r-- | drivers/iio/accel/adxl345_i2c.c | 73 | ||||
-rw-r--r-- | drivers/iio/accel/adxl345_spi.c | 81 | ||||
-rw-r--r-- | drivers/iio/accel/bma180.c | 32 | ||||
-rw-r--r-- | drivers/iio/accel/mma7455_i2c.c | 8 | ||||
-rw-r--r-- | drivers/iio/accel/mma7660.c | 7 |
9 files changed, 426 insertions, 6 deletions
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index ef8401ac1141..15de262015df 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -5,6 +5,37 @@ menu "Accelerometers" +config ADXL345 + tristate + +config ADXL345_I2C + tristate "Analog Devices ADXL345 3-Axis Digital Accelerometer I2C Driver" + depends on INPUT_ADXL34X=n + depends on I2C + select ADXL345 + select REGMAP_I2C + help + Say Y here if you want to build support for the Analog Devices + ADXL345 3-axis digital accelerometer. + + To compile this driver as a module, choose M here: the module + will be called adxl345_i2c and you will also get adxl345_core + for the core module. + +config ADXL345_SPI + tristate "Analog Devices ADXL345 3-Axis Digital Accelerometer SPI Driver" + depends on INPUT_ADXL34X=n + depends on SPI + select ADXL345 + select REGMAP_SPI + help + Say Y here if you want to build support for the Analog Devices + ADXL345 3-axis digital accelerometer. + + To compile this driver as a module, choose M here: the module + will be called adxl345_spi and you will also get adxl345_core + for the core module. + config BMA180 tristate "Bosch BMA180/BMA250 3-Axis Accelerometer Driver" depends on I2C diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index 69fe8edc57a2..31fba1974e95 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -3,6 +3,9 @@ # # When adding new entries keep the list in alphabetical order +obj-$(CONFIG_ADXL345) += adxl345_core.o +obj-$(CONFIG_ADXL345_I2C) += adxl345_i2c.o +obj-$(CONFIG_ADXL345_SPI) += adxl345_spi.o obj-$(CONFIG_BMA180) += bma180.o obj-$(CONFIG_BMA220) += bma220_spi.o obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o diff --git a/drivers/iio/accel/adxl345.h b/drivers/iio/accel/adxl345.h new file mode 100644 index 000000000000..c1ddf3927c47 --- /dev/null +++ b/drivers/iio/accel/adxl345.h @@ -0,0 +1,18 @@ +/* + * ADXL345 3-Axis Digital Accelerometer + * + * Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com> + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + */ + +#ifndef _ADXL345_H_ +#define _ADXL345_H_ + +int adxl345_core_probe(struct device *dev, struct regmap *regmap, + const char *name); +int adxl345_core_remove(struct device *dev); + +#endif /* _ADXL345_H_ */ diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c new file mode 100644 index 000000000000..9ccb5828db98 --- /dev/null +++ b/drivers/iio/accel/adxl345_core.c @@ -0,0 +1,179 @@ +/* + * ADXL345 3-Axis Digital Accelerometer IIO core driver + * + * Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com> + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + */ + +#include <linux/module.h> +#include <linux/regmap.h> + +#include <linux/iio/iio.h> + +#include "adxl345.h" + +#define ADXL345_REG_DEVID 0x00 +#define ADXL345_REG_POWER_CTL 0x2D +#define ADXL345_REG_DATA_FORMAT 0x31 +#define ADXL345_REG_DATAX0 0x32 +#define ADXL345_REG_DATAY0 0x34 +#define ADXL345_REG_DATAZ0 0x36 + +#define ADXL345_POWER_CTL_MEASURE BIT(3) +#define ADXL345_POWER_CTL_STANDBY 0x00 + +#define ADXL345_DATA_FORMAT_FULL_RES BIT(3) /* Up to 13-bits resolution */ +#define ADXL345_DATA_FORMAT_2G 0 +#define ADXL345_DATA_FORMAT_4G 1 +#define ADXL345_DATA_FORMAT_8G 2 +#define ADXL345_DATA_FORMAT_16G 3 + +#define ADXL345_DEVID 0xE5 + +/* + * In full-resolution mode, scale factor is maintained at ~4 mg/LSB + * in all g ranges. + * + * At +/- 16g with 13-bit resolution, scale is computed as: + * (16 + 16) * 9.81 / (2^13 - 1) = 0.0383 + */ +static const int adxl345_uscale = 38300; + +struct adxl345_data { + struct regmap *regmap; + u8 data_range; +}; + +#define ADXL345_CHANNEL(reg, axis) { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = IIO_MOD_##axis, \ + .address = reg, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ +} + +static const struct iio_chan_spec adxl345_channels[] = { + ADXL345_CHANNEL(ADXL345_REG_DATAX0, X), + ADXL345_CHANNEL(ADXL345_REG_DATAY0, Y), + ADXL345_CHANNEL(ADXL345_REG_DATAZ0, Z), +}; + +static int adxl345_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct adxl345_data *data = iio_priv(indio_dev); + __le16 regval; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + /* + * Data is stored in adjacent registers: + * ADXL345_REG_DATA(X0/Y0/Z0) contain the least significant byte + * and ADXL345_REG_DATA(X0/Y0/Z0) + 1 the most significant byte + */ + ret = regmap_bulk_read(data->regmap, chan->address, ®val, + sizeof(regval)); + if (ret < 0) + return ret; + + *val = sign_extend32(le16_to_cpu(regval), 12); + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = adxl345_uscale; + + return IIO_VAL_INT_PLUS_MICRO; + } + + return -EINVAL; +} + +static const struct iio_info adxl345_info = { + .driver_module = THIS_MODULE, + .read_raw = adxl345_read_raw, +}; + +int adxl345_core_probe(struct device *dev, struct regmap *regmap, + const char *name) +{ + struct adxl345_data *data; + struct iio_dev *indio_dev; + u32 regval; + int ret; + + ret = regmap_read(regmap, ADXL345_REG_DEVID, ®val); + if (ret < 0) { + dev_err(dev, "Error reading device ID: %d\n", ret); + return ret; + } + + if (regval != ADXL345_DEVID) { + dev_err(dev, "Invalid device ID: %x, expected %x\n", + regval, ADXL345_DEVID); + return -ENODEV; + } + + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + dev_set_drvdata(dev, indio_dev); + data->regmap = regmap; + /* Enable full-resolution mode */ + data->data_range = ADXL345_DATA_FORMAT_FULL_RES; + + ret = regmap_write(data->regmap, ADXL345_REG_DATA_FORMAT, + data->data_range); + if (ret < 0) { + dev_err(dev, "Failed to set data range: %d\n", ret); + return ret; + } + + indio_dev->dev.parent = dev; + indio_dev->name = name; + indio_dev->info = &adxl345_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = adxl345_channels; + indio_dev->num_channels = ARRAY_SIZE(adxl345_channels); + + /* Enable measurement mode */ + ret = regmap_write(data->regmap, ADXL345_REG_POWER_CTL, + ADXL345_POWER_CTL_MEASURE); + if (ret < 0) { + dev_err(dev, "Failed to enable measurement mode: %d\n", ret); + return ret; + } + + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(dev, "iio_device_register failed: %d\n", ret); + regmap_write(data->regmap, ADXL345_REG_POWER_CTL, + ADXL345_POWER_CTL_STANDBY); + } + + return ret; +} +EXPORT_SYMBOL_GPL(adxl345_core_probe); + +int adxl345_core_remove(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adxl345_data *data = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + return regmap_write(data->regmap, ADXL345_REG_POWER_CTL, + ADXL345_POWER_CTL_STANDBY); +} +EXPORT_SYMBOL_GPL(adxl345_core_remove); + +MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>"); +MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer core driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/accel/adxl345_i2c.c b/drivers/iio/accel/adxl345_i2c.c new file mode 100644 index 000000000000..05e1ec49700c --- /dev/null +++ b/drivers/iio/accel/adxl345_i2c.c @@ -0,0 +1,73 @@ +/* + * ADXL345 3-Axis Digital Accelerometer I2C driver + * + * Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com> + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * 7-bit I2C slave address: 0x1D (ALT ADDRESS pin tied to VDDIO) or + * 0x53 (ALT ADDRESS pin grounded) + */ + +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/regmap.h> + +#include "adxl345.h" + +static const struct regmap_config adxl345_i2c_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +static int adxl345_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct regmap *regmap; + + regmap = devm_regmap_init_i2c(client, &adxl345_i2c_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "Error initializing i2c regmap: %ld\n", + PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + return adxl345_core_probe(&client->dev, regmap, id ? id->name : NULL); +} + +static int adxl345_i2c_remove(struct i2c_client *client) +{ + return adxl345_core_remove(&client->dev); +} + +static const struct i2c_device_id adxl345_i2c_id[] = { + { "adxl345", 0 }, + { } +}; + +MODULE_DEVICE_TABLE(i2c, adxl345_i2c_id); + +static const struct of_device_id adxl345_of_match[] = { + { .compatible = "adi,adxl345" }, + { }, +}; + +MODULE_DEVICE_TABLE(of, adxl345_of_match); + +static struct i2c_driver adxl345_i2c_driver = { + .driver = { + .name = "adxl345_i2c", + .of_match_table = adxl345_of_match, + }, + .probe = adxl345_i2c_probe, + .remove = adxl345_i2c_remove, + .id_table = adxl345_i2c_id, +}; + +module_i2c_driver(adxl345_i2c_driver); + +MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>"); +MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer I2C driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/accel/adxl345_spi.c b/drivers/iio/accel/adxl345_spi.c new file mode 100644 index 000000000000..6d658196f81c --- /dev/null +++ b/drivers/iio/accel/adxl345_spi.c @@ -0,0 +1,81 @@ +/* + * ADXL345 3-Axis Digital Accelerometer SPI driver + * + * Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com> + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + */ + +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/spi/spi.h> + +#include "adxl345.h" + +#define ADXL345_MAX_SPI_FREQ_HZ 5000000 + +static const struct regmap_config adxl345_spi_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + /* Setting bits 7 and 6 enables multiple-byte read */ + .read_flag_mask = BIT(7) | BIT(6), +}; + +static int adxl345_spi_probe(struct spi_device *spi) +{ + const struct spi_device_id *id = spi_get_device_id(spi); + struct regmap *regmap; + + /* Bail out if max_speed_hz exceeds 5 MHz */ + if (spi->max_speed_hz > ADXL345_MAX_SPI_FREQ_HZ) { + dev_err(&spi->dev, "SPI CLK, %d Hz exceeds 5 MHz\n", + spi->max_speed_hz); + return -EINVAL; + } + + regmap = devm_regmap_init_spi(spi, &adxl345_spi_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&spi->dev, "Error initializing spi regmap: %ld\n", + PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + return adxl345_core_probe(&spi->dev, regmap, id->name); +} + +static int adxl345_spi_remove(struct spi_device *spi) +{ + return adxl345_core_remove(&spi->dev); +} + +static const struct spi_device_id adxl345_spi_id[] = { + { "adxl345", 0 }, + { } +}; + +MODULE_DEVICE_TABLE(spi, adxl345_spi_id); + +static const struct of_device_id adxl345_of_match[] = { + { .compatible = "adi,adxl345" }, + { }, +}; + +MODULE_DEVICE_TABLE(of, adxl345_of_match); + +static struct spi_driver adxl345_spi_driver = { + .driver = { + .name = "adxl345_spi", + .of_match_table = adxl345_of_match, + }, + .probe = adxl345_spi_probe, + .remove = adxl345_spi_remove, + .id_table = adxl345_spi_id, +}; + +module_spi_driver(adxl345_spi_driver); + +MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>"); +MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer SPI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index 0890934ef66f..efc67739c28f 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -18,6 +18,7 @@ #include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/delay.h> +#include <linux/of_device.h> #include <linux/of.h> #include <linux/bitops.h> #include <linux/slab.h> @@ -32,7 +33,7 @@ #define BMA180_DRV_NAME "bma180" #define BMA180_IRQ_NAME "bma180_event" -enum { +enum chip_ids { BMA180, BMA250, }; @@ -41,11 +42,11 @@ struct bma180_data; struct bma180_part_info { const struct iio_chan_spec *channels; - unsigned num_channels; + unsigned int num_channels; const int *scale_table; - unsigned num_scales; + unsigned int num_scales; const int *bw_table; - unsigned num_bw; + unsigned int num_bw; u8 int_reset_reg, int_reset_mask; u8 sleep_reg, sleep_mask; @@ -408,7 +409,7 @@ err: dev_err(&data->client->dev, "failed to disable the chip\n"); } -static ssize_t bma180_show_avail(char *buf, const int *vals, unsigned n, +static ssize_t bma180_show_avail(char *buf, const int *vals, unsigned int n, bool micros) { size_t len = 0; @@ -707,6 +708,7 @@ static int bma180_probe(struct i2c_client *client, { struct bma180_data *data; struct iio_dev *indio_dev; + enum chip_ids chip; int ret; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); @@ -716,7 +718,11 @@ static int bma180_probe(struct i2c_client *client, data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); data->client = client; - data->part_info = &bma180_part_info[id->driver_data]; + if (client->dev.of_node) + chip = (enum chip_ids)of_device_get_match_data(&client->dev); + else + chip = id->driver_data; + data->part_info = &bma180_part_info[chip]; ret = data->part_info->chip_config(data); if (ret < 0) @@ -844,10 +850,24 @@ static struct i2c_device_id bma180_ids[] = { MODULE_DEVICE_TABLE(i2c, bma180_ids); +static const struct of_device_id bma180_of_match[] = { + { + .compatible = "bosch,bma180", + .data = (void *)BMA180 + }, + { + .compatible = "bosch,bma250", + .data = (void *)BMA250 + }, + { } +}; +MODULE_DEVICE_TABLE(of, bma180_of_match); + static struct i2c_driver bma180_driver = { .driver = { .name = "bma180", .pm = BMA180_PM_OPS, + .of_match_table = bma180_of_match, }, .probe = bma180_probe, .remove = bma180_remove, diff --git a/drivers/iio/accel/mma7455_i2c.c b/drivers/iio/accel/mma7455_i2c.c index 3cab5fb4a3c4..73bf81a8ab14 100644 --- a/drivers/iio/accel/mma7455_i2c.c +++ b/drivers/iio/accel/mma7455_i2c.c @@ -41,12 +41,20 @@ static const struct i2c_device_id mma7455_i2c_ids[] = { }; MODULE_DEVICE_TABLE(i2c, mma7455_i2c_ids); +static const struct of_device_id mma7455_of_match[] = { + { .compatible = "fsl,mma7455" }, + { .compatible = "fsl,mma7456" }, + { } +}; +MODULE_DEVICE_TABLE(of, mma7455_of_match); + static struct i2c_driver mma7455_i2c_driver = { .probe = mma7455_i2c_probe, .remove = mma7455_i2c_remove, .id_table = mma7455_i2c_ids, .driver = { .name = "mma7455-i2c", + .of_match_table = mma7455_of_match, }, }; module_i2c_driver(mma7455_i2c_driver); diff --git a/drivers/iio/accel/mma7660.c b/drivers/iio/accel/mma7660.c index 3a40774cca74..42fa57e41bdd 100644 --- a/drivers/iio/accel/mma7660.c +++ b/drivers/iio/accel/mma7660.c @@ -253,6 +253,12 @@ static const struct i2c_device_id mma7660_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, mma7660_i2c_id); +static const struct of_device_id mma7660_of_match[] = { + { .compatible = "fsl,mma7660" }, + { } +}; +MODULE_DEVICE_TABLE(of, mma7660_of_match); + static const struct acpi_device_id mma7660_acpi_id[] = { {"MMA7660", 0}, {} @@ -264,6 +270,7 @@ static struct i2c_driver mma7660_driver = { .driver = { .name = "mma7660", .pm = MMA7660_PM_OPS, + .of_match_table = mma7660_of_match, .acpi_match_table = ACPI_PTR(mma7660_acpi_id), }, .probe = mma7660_probe, |