First set of new drivers and cleanups for IIO in the 3.15 cycle.
New drivers: * si7005 relative humidity and temperature sensor * Lite-on ltr501 ambient light and proximity sensor Cleanups * Clean up some dead comments in max1363 * Drop some obsolete variables in adjd_s311 and tcs3472 left over from the introduction of iio_push_to_buffers_with_timestamp. * Drop some unneeded linux/init.h includes * Squish a sparse warning in mpl3115 by correctly specifying a be32 variable. * A number of cleanups and fixes for sca3000 * Drop an unneed checks in mxs-lradc, ad7303 and adis16400. * Drop a platform_set_drvdata in viperboard after the only use of it was removed during a devm conversion. * Add a missing device name for ak8975 to comply with the ABI. * Put mpu6050 into the IMU menu as it slipped out into the main menu. * Fix a typo and some comment formatting in mpu6050. * Document at91 ADC clock properties. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJS+R3TAAoJEFSFNJnE9BaILtoP/RiZaeAQe5hKVtS7DBNmtbvH NVrk4SDl8F5WH6O6MKvRn54aBWyPj3axyMb0WLv9oGQycxlflT/420Q1UaayG4oX W1IOS/X2JNrWpt/xlNPi8crqpcRZbLVjKoRGhw0BMR9OTD+x6U+NTNGpr9WJUNAB CjmYpa6MhouQMd59+HMroSf1PIvBfvG2fkAMg2AoRSQ6TU19q5Yi0zzqwS17iZf3 VTazh63dVKYyt3MJimjnGcA4A2kv5YOrfK59qYfHPIVR4AfKNVKlwVQlu8TlBaXE eYr2G1Jbd/GRkUe5FRGL9Nlnl8exnUU8JGCTpeXSJSmDWAe2xVkjTNbDDyrT5Gem 6c02ms0xYeIxqzYpZVZs8OueuZhs2DztcT0e+p7ByvjBZ+XvMEp9t00DnsV3rSEa Y9X1vpeZei5bRW+woKCniEhV/89seUe1ASyj/g8yiPYc5b1mKhcUQKFs1vCToWjV v0MEp15569jeqX+6igOAloArxykrdmS4hAeMfyKoijApd97n5hkK2jwjFxRv9rZs 2Q+2qTDA/3E9+wRjLrx4v+Bu6EKH44K5Z5H5rPmnsgRe8/0UQx4xvhI6Bv2Krx0v CKdwNAo6Z5iePAtmaMU46l9h1AygOAzub9V2L36Irxd4BFLLYUj1zSW2hN1zgfCX 4YTgPtTGZ/lBfNsvBy9b =nSiE -----END PGP SIGNATURE----- Merge tag 'iio-for-3.15a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next Jonathan writes: First set of new drivers and cleanups for IIO in the 3.15 cycle. New drivers: * si7005 relative humidity and temperature sensor * Lite-on ltr501 ambient light and proximity sensor Cleanups * Clean up some dead comments in max1363 * Drop some obsolete variables in adjd_s311 and tcs3472 left over from the introduction of iio_push_to_buffers_with_timestamp. * Drop some unneeded linux/init.h includes * Squish a sparse warning in mpl3115 by correctly specifying a be32 variable. * A number of cleanups and fixes for sca3000 * Drop an unneed checks in mxs-lradc, ad7303 and adis16400. * Drop a platform_set_drvdata in viperboard after the only use of it was removed during a devm conversion. * Add a missing device name for ak8975 to comply with the ABI. * Put mpu6050 into the IMU menu as it slipped out into the main menu. * Fix a typo and some comment formatting in mpu6050. * Document at91 ADC clock properties.
This commit is contained in:
commit
e5b9c05772
|
@ -5,6 +5,9 @@ Required properties:
|
|||
<chip> can be "at91sam9260", "at91sam9g45" or "at91sam9x5"
|
||||
- reg: Should contain ADC registers location and length
|
||||
- interrupts: Should contain the IRQ line for the ADC
|
||||
- clock-names: tuple listing input clock names.
|
||||
Required elements: "adc_clk", "adc_op_clk".
|
||||
- clocks: phandles to input clocks.
|
||||
- atmel,adc-channels-used: Bitmask of the channels muxed and enable for this
|
||||
device
|
||||
- atmel,adc-startup-time: Startup Time of the ADC in microseconds as
|
||||
|
@ -44,6 +47,8 @@ adc0: adc@fffb0000 {
|
|||
compatible = "atmel,at91sam9260-adc";
|
||||
reg = <0xfffb0000 0x100>;
|
||||
interrupts = <20 4>;
|
||||
clocks = <&adc_clk>, <&adc_op_clk>;
|
||||
clock-names = "adc_clk", "adc_op_clk";
|
||||
atmel,adc-channel-base = <0x30>;
|
||||
atmel,adc-channels-used = <0xff>;
|
||||
atmel,adc-drdy-mask = <0x10000>;
|
||||
|
|
|
@ -8,17 +8,11 @@
|
|||
* based on linux/drivers/acron/char/pcf8583.c
|
||||
* Copyright (C) 2000 Russell King
|
||||
*
|
||||
* Driver for max1363 and similar chips.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* max1363.c
|
||||
*
|
||||
* Partial support for max1363 and similar chips.
|
||||
*
|
||||
* Not currently implemented.
|
||||
*
|
||||
* - Control of internal reference.
|
||||
*/
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
|
|
|
@ -139,8 +139,6 @@ static int vprbrd_adc_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ static ssize_t ad7303_write_dac_powerdown(struct iio_dev *indio_dev,
|
|||
ad7303_write(st, chan->channel, st->dac_cache[chan->channel]);
|
||||
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
return ret ? ret : len;
|
||||
return len;
|
||||
}
|
||||
|
||||
static int ad7303_get_vref(struct ad7303_state *st,
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/delay.h>
|
||||
|
|
|
@ -12,4 +12,14 @@ config DHT11
|
|||
Other sensors should work as well as long as they speak the
|
||||
same protocol.
|
||||
|
||||
config SI7005
|
||||
tristate "SI7005 relative humidity and temperature sensor"
|
||||
depends on I2C
|
||||
help
|
||||
Say yes here to build support for the Silabs Si7005 relative
|
||||
humidity and temperature sensor.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called si7005.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -3,3 +3,4 @@
|
|||
#
|
||||
|
||||
obj-$(CONFIG_DHT11) += dht11.o
|
||||
obj-$(CONFIG_SI7005) += si7005.o
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* si7005.c - Support for Silabs Si7005 humidity and temperature sensor
|
||||
*
|
||||
* Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
|
||||
*
|
||||
* 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 0x40)
|
||||
*
|
||||
* TODO: heater, fast mode, processed mode (temp. / linearity compensation)
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pm.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
|
||||
#define SI7005_STATUS 0x00
|
||||
#define SI7005_DATA 0x01 /* 16-bit, MSB */
|
||||
#define SI7005_CONFIG 0x03
|
||||
#define SI7005_ID 0x11
|
||||
|
||||
#define SI7005_STATUS_NRDY BIT(0)
|
||||
#define SI7005_CONFIG_TEMP BIT(4)
|
||||
#define SI7005_CONFIG_START BIT(0)
|
||||
|
||||
#define SI7005_ID_7005 0x50
|
||||
#define SI7005_ID_7015 0xf0
|
||||
|
||||
struct si7005_data {
|
||||
struct i2c_client *client;
|
||||
struct mutex lock;
|
||||
u8 config;
|
||||
};
|
||||
|
||||
static int si7005_read_measurement(struct si7005_data *data, bool temp)
|
||||
{
|
||||
int tries = 50;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
|
||||
ret = i2c_smbus_write_byte_data(data->client, SI7005_CONFIG,
|
||||
data->config | SI7005_CONFIG_START |
|
||||
(temp ? SI7005_CONFIG_TEMP : 0));
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
while (tries-- > 0) {
|
||||
msleep(20);
|
||||
ret = i2c_smbus_read_byte_data(data->client, SI7005_STATUS);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
if (!(ret & SI7005_STATUS_NRDY))
|
||||
break;
|
||||
}
|
||||
if (tries < 0) {
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = i2c_smbus_read_word_swapped(data->client, SI7005_DATA);
|
||||
|
||||
done:
|
||||
mutex_unlock(&data->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int si7005_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan, int *val,
|
||||
int *val2, long mask)
|
||||
{
|
||||
struct si7005_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
ret = si7005_read_measurement(data, chan->type == IIO_TEMP);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*val = ret;
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
if (chan->type == IIO_TEMP) {
|
||||
*val = 7;
|
||||
*val2 = 812500;
|
||||
} else {
|
||||
*val = 3;
|
||||
*val2 = 906250;
|
||||
}
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
case IIO_CHAN_INFO_OFFSET:
|
||||
if (chan->type == IIO_TEMP)
|
||||
*val = -50 * 32 * 4;
|
||||
else
|
||||
*val = -24 * 16 * 16;
|
||||
return IIO_VAL_INT;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct iio_chan_spec si7005_channels[] = {
|
||||
{
|
||||
.type = IIO_HUMIDITYRELATIVE,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
|
||||
BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET),
|
||||
},
|
||||
{
|
||||
.type = IIO_TEMP,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
|
||||
BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET),
|
||||
}
|
||||
};
|
||||
|
||||
static const struct iio_info si7005_info = {
|
||||
.read_raw = si7005_read_raw,
|
||||
.driver_module = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int si7005_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct iio_dev *indio_dev;
|
||||
struct si7005_data *data;
|
||||
int ret;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
|
||||
return -ENODEV;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
data = iio_priv(indio_dev);
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
data->client = client;
|
||||
mutex_init(&data->lock);
|
||||
|
||||
indio_dev->dev.parent = &client->dev;
|
||||
indio_dev->name = dev_name(&client->dev);
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->info = &si7005_info;
|
||||
|
||||
indio_dev->channels = si7005_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(si7005_channels);
|
||||
|
||||
ret = i2c_smbus_read_byte_data(client, SI7005_ID);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret != SI7005_ID_7005 && ret != SI7005_ID_7015)
|
||||
return -ENODEV;
|
||||
|
||||
ret = i2c_smbus_read_byte_data(client, SI7005_CONFIG);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
data->config = ret;
|
||||
|
||||
return devm_iio_device_register(&client->dev, indio_dev);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id si7005_id[] = {
|
||||
{ "si7005", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, si7005_id);
|
||||
|
||||
static struct i2c_driver si7005_driver = {
|
||||
.driver = {
|
||||
.name = "si7005",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = si7005_probe,
|
||||
.id_table = si7005_id,
|
||||
};
|
||||
module_i2c_driver(si7005_driver);
|
||||
|
||||
MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
|
||||
MODULE_DESCRIPTION("Silabs Si7005 humidity and temperature sensor driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -25,6 +25,8 @@ config ADIS16480
|
|||
Say yes here to build support for Analog Devices ADIS16375, ADIS16480,
|
||||
ADIS16485, ADIS16488 inertial sensors.
|
||||
|
||||
source "drivers/iio/imu/inv_mpu6050/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
config IIO_ADIS_LIB
|
||||
|
@ -38,5 +40,3 @@ config IIO_ADIS_LIB_BUFFER
|
|||
help
|
||||
A set of buffer helper functions for the Analog Devices ADIS* device
|
||||
family.
|
||||
|
||||
source "drivers/iio/imu/inv_mpu6050/Kconfig"
|
||||
|
|
|
@ -281,7 +281,7 @@ static ssize_t adis16400_write_frequency(struct device *dev,
|
|||
st->variant->set_freq(st, val);
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
|
||||
return ret ? ret : len;
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Power down the device */
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/err.h>
|
||||
|
@ -117,7 +116,7 @@ int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask)
|
|||
return result;
|
||||
|
||||
if (en) {
|
||||
/* Wait for output stablize */
|
||||
/* Wait for output stabilize */
|
||||
msleep(INV_MPU6050_TEMP_UP_TIME);
|
||||
if (INV_MPU6050_BIT_PWR_GYRO_STBY == mask) {
|
||||
/* switch internal clock to PLL */
|
||||
|
|
|
@ -126,35 +126,35 @@ struct inv_mpu6050_state {
|
|||
#define INV_MPU6050_REG_SAMPLE_RATE_DIV 0x19
|
||||
#define INV_MPU6050_REG_CONFIG 0x1A
|
||||
#define INV_MPU6050_REG_GYRO_CONFIG 0x1B
|
||||
#define INV_MPU6050_REG_ACCEL_CONFIG 0x1C
|
||||
#define INV_MPU6050_REG_ACCEL_CONFIG 0x1C
|
||||
|
||||
#define INV_MPU6050_REG_FIFO_EN 0x23
|
||||
#define INV_MPU6050_BIT_ACCEL_OUT 0x08
|
||||
#define INV_MPU6050_BITS_GYRO_OUT 0x70
|
||||
#define INV_MPU6050_BIT_ACCEL_OUT 0x08
|
||||
#define INV_MPU6050_BITS_GYRO_OUT 0x70
|
||||
|
||||
#define INV_MPU6050_REG_INT_ENABLE 0x38
|
||||
#define INV_MPU6050_BIT_DATA_RDY_EN 0x01
|
||||
#define INV_MPU6050_BIT_DMP_INT_EN 0x02
|
||||
#define INV_MPU6050_BIT_DATA_RDY_EN 0x01
|
||||
#define INV_MPU6050_BIT_DMP_INT_EN 0x02
|
||||
|
||||
#define INV_MPU6050_REG_RAW_ACCEL 0x3B
|
||||
#define INV_MPU6050_REG_TEMPERATURE 0x41
|
||||
#define INV_MPU6050_REG_RAW_GYRO 0x43
|
||||
|
||||
#define INV_MPU6050_REG_USER_CTRL 0x6A
|
||||
#define INV_MPU6050_BIT_FIFO_RST 0x04
|
||||
#define INV_MPU6050_BIT_DMP_RST 0x08
|
||||
#define INV_MPU6050_BIT_I2C_MST_EN 0x20
|
||||
#define INV_MPU6050_BIT_FIFO_EN 0x40
|
||||
#define INV_MPU6050_BIT_DMP_EN 0x80
|
||||
#define INV_MPU6050_BIT_FIFO_RST 0x04
|
||||
#define INV_MPU6050_BIT_DMP_RST 0x08
|
||||
#define INV_MPU6050_BIT_I2C_MST_EN 0x20
|
||||
#define INV_MPU6050_BIT_FIFO_EN 0x40
|
||||
#define INV_MPU6050_BIT_DMP_EN 0x80
|
||||
|
||||
#define INV_MPU6050_REG_PWR_MGMT_1 0x6B
|
||||
#define INV_MPU6050_BIT_H_RESET 0x80
|
||||
#define INV_MPU6050_BIT_SLEEP 0x40
|
||||
#define INV_MPU6050_BIT_CLK_MASK 0x7
|
||||
#define INV_MPU6050_BIT_H_RESET 0x80
|
||||
#define INV_MPU6050_BIT_SLEEP 0x40
|
||||
#define INV_MPU6050_BIT_CLK_MASK 0x7
|
||||
|
||||
#define INV_MPU6050_REG_PWR_MGMT_2 0x6C
|
||||
#define INV_MPU6050_BIT_PWR_ACCL_STBY 0x38
|
||||
#define INV_MPU6050_BIT_PWR_GYRO_STBY 0x07
|
||||
#define INV_MPU6050_BIT_PWR_ACCL_STBY 0x38
|
||||
#define INV_MPU6050_BIT_PWR_GYRO_STBY 0x07
|
||||
|
||||
#define INV_MPU6050_REG_FIFO_COUNT_H 0x72
|
||||
#define INV_MPU6050_REG_FIFO_R_W 0x74
|
||||
|
@ -180,10 +180,10 @@ struct inv_mpu6050_state {
|
|||
|
||||
/* init parameters */
|
||||
#define INV_MPU6050_INIT_FIFO_RATE 50
|
||||
#define INV_MPU6050_TIME_STAMP_TOR 5
|
||||
#define INV_MPU6050_MAX_FIFO_RATE 1000
|
||||
#define INV_MPU6050_MIN_FIFO_RATE 4
|
||||
#define INV_MPU6050_ONE_K_HZ 1000
|
||||
#define INV_MPU6050_TIME_STAMP_TOR 5
|
||||
#define INV_MPU6050_MAX_FIFO_RATE 1000
|
||||
#define INV_MPU6050_MIN_FIFO_RATE 4
|
||||
#define INV_MPU6050_ONE_K_HZ 1000
|
||||
|
||||
/* scan element definition */
|
||||
enum inv_mpu6050_scan {
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/err.h>
|
||||
|
|
|
@ -90,6 +90,18 @@ config SENSORS_LM3533
|
|||
changes. The ALS-control output values can be set per zone for the
|
||||
three current output channels.
|
||||
|
||||
config LTR501
|
||||
tristate "LTR-501ALS-01 light sensor"
|
||||
depends on I2C
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
help
|
||||
If you say yes here you get support for the Lite-On LTR-501ALS-01
|
||||
ambient light and proximity sensor.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called ltr501.
|
||||
|
||||
config TCS3472
|
||||
tristate "TAOS TCS3472 color light-to-digital converter"
|
||||
depends on I2C
|
||||
|
|
|
@ -10,6 +10,7 @@ obj-$(CONFIG_CM36651) += cm36651.o
|
|||
obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o
|
||||
obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o
|
||||
obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o
|
||||
obj-$(CONFIG_LTR501) += ltr501.o
|
||||
obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o
|
||||
obj-$(CONFIG_TCS3472) += tcs3472.o
|
||||
obj-$(CONFIG_TSL4531) += tsl4531.o
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -120,7 +119,6 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p)
|
|||
struct iio_dev *indio_dev = pf->indio_dev;
|
||||
struct adjd_s311_data *data = iio_priv(indio_dev);
|
||||
s64 time_ns = iio_get_time_ns();
|
||||
int len = 0;
|
||||
int i, j = 0;
|
||||
|
||||
int ret = adjd_s311_req_data(indio_dev);
|
||||
|
@ -135,7 +133,6 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p)
|
|||
goto done;
|
||||
|
||||
data->buffer[j++] = ret & ADJD_S311_DATA_MASK;
|
||||
len += 2;
|
||||
}
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, time_ns);
|
||||
|
|
|
@ -0,0 +1,445 @@
|
|||
/*
|
||||
* ltr501.c - Support for Lite-On LTR501 ambient light and proximity sensor
|
||||
*
|
||||
* Copyright 2014 Peter Meerwald <pmeerw@pmeerw.net>
|
||||
*
|
||||
* 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 0x23
|
||||
*
|
||||
* TODO: interrupt, threshold, measurement rate, IR LED characteristics
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/triggered_buffer.h>
|
||||
|
||||
#define LTR501_DRV_NAME "ltr501"
|
||||
|
||||
#define LTR501_ALS_CONTR 0x80 /* ALS operation mode, SW reset */
|
||||
#define LTR501_PS_CONTR 0x81 /* PS operation mode */
|
||||
#define LTR501_PART_ID 0x86
|
||||
#define LTR501_MANUFAC_ID 0x87
|
||||
#define LTR501_ALS_DATA1 0x88 /* 16-bit, little endian */
|
||||
#define LTR501_ALS_DATA0 0x8a /* 16-bit, little endian */
|
||||
#define LTR501_ALS_PS_STATUS 0x8c
|
||||
#define LTR501_PS_DATA 0x8d /* 16-bit, little endian */
|
||||
|
||||
#define LTR501_ALS_CONTR_SW_RESET BIT(2)
|
||||
#define LTR501_CONTR_PS_GAIN_MASK (BIT(3) | BIT(2))
|
||||
#define LTR501_CONTR_PS_GAIN_SHIFT 2
|
||||
#define LTR501_CONTR_ALS_GAIN_MASK BIT(3)
|
||||
#define LTR501_CONTR_ACTIVE BIT(1)
|
||||
|
||||
#define LTR501_STATUS_ALS_RDY BIT(2)
|
||||
#define LTR501_STATUS_PS_RDY BIT(0)
|
||||
|
||||
#define LTR501_PS_DATA_MASK 0x7ff
|
||||
|
||||
struct ltr501_data {
|
||||
struct i2c_client *client;
|
||||
struct mutex lock_als, lock_ps;
|
||||
u8 als_contr, ps_contr;
|
||||
};
|
||||
|
||||
static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask)
|
||||
{
|
||||
int tries = 100;
|
||||
int ret;
|
||||
|
||||
while (tries--) {
|
||||
ret = i2c_smbus_read_byte_data(data->client,
|
||||
LTR501_ALS_PS_STATUS);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if ((ret & drdy_mask) == drdy_mask)
|
||||
return 0;
|
||||
msleep(25);
|
||||
}
|
||||
|
||||
dev_err(&data->client->dev, "ltr501_drdy() failed, data not ready\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int ltr501_read_als(struct ltr501_data *data, __le16 buf[2])
|
||||
{
|
||||
int ret = ltr501_drdy(data, LTR501_STATUS_ALS_RDY);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* always read both ALS channels in given order */
|
||||
return i2c_smbus_read_i2c_block_data(data->client,
|
||||
LTR501_ALS_DATA1, 2 * sizeof(__le16), (u8 *) buf);
|
||||
}
|
||||
|
||||
static int ltr501_read_ps(struct ltr501_data *data)
|
||||
{
|
||||
int ret = ltr501_drdy(data, LTR501_STATUS_PS_RDY);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return i2c_smbus_read_word_data(data->client, LTR501_PS_DATA);
|
||||
}
|
||||
|
||||
#define LTR501_INTENSITY_CHANNEL(_idx, _addr, _mod, _shared) { \
|
||||
.type = IIO_INTENSITY, \
|
||||
.modified = 1, \
|
||||
.address = (_addr), \
|
||||
.channel2 = (_mod), \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
|
||||
.info_mask_shared_by_type = (_shared), \
|
||||
.scan_index = (_idx), \
|
||||
.scan_type = { \
|
||||
.sign = 'u', \
|
||||
.realbits = 16, \
|
||||
.storagebits = 16, \
|
||||
.endianness = IIO_CPU, \
|
||||
} \
|
||||
}
|
||||
|
||||
static const struct iio_chan_spec ltr501_channels[] = {
|
||||
LTR501_INTENSITY_CHANNEL(0, LTR501_ALS_DATA0, IIO_MOD_LIGHT_BOTH, 0),
|
||||
LTR501_INTENSITY_CHANNEL(1, LTR501_ALS_DATA1, IIO_MOD_LIGHT_IR,
|
||||
BIT(IIO_CHAN_INFO_SCALE)),
|
||||
{
|
||||
.type = IIO_PROXIMITY,
|
||||
.address = LTR501_PS_DATA,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
|
||||
BIT(IIO_CHAN_INFO_SCALE),
|
||||
.scan_index = 2,
|
||||
.scan_type = {
|
||||
.sign = 'u',
|
||||
.realbits = 11,
|
||||
.storagebits = 16,
|
||||
.endianness = IIO_CPU,
|
||||
},
|
||||
},
|
||||
IIO_CHAN_SOFT_TIMESTAMP(3),
|
||||
};
|
||||
|
||||
static const int ltr501_ps_gain[4][2] = {
|
||||
{1, 0}, {0, 250000}, {0, 125000}, {0, 62500}
|
||||
};
|
||||
|
||||
static int ltr501_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val, int *val2, long mask)
|
||||
{
|
||||
struct ltr501_data *data = iio_priv(indio_dev);
|
||||
__le16 buf[2];
|
||||
int ret, i;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
if (iio_buffer_enabled(indio_dev))
|
||||
return -EBUSY;
|
||||
|
||||
switch (chan->type) {
|
||||
case IIO_INTENSITY:
|
||||
mutex_lock(&data->lock_als);
|
||||
ret = ltr501_read_als(data, buf);
|
||||
mutex_unlock(&data->lock_als);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*val = le16_to_cpu(chan->address == LTR501_ALS_DATA1 ?
|
||||
buf[0] : buf[1]);
|
||||
return IIO_VAL_INT;
|
||||
case IIO_PROXIMITY:
|
||||
mutex_lock(&data->lock_ps);
|
||||
ret = ltr501_read_ps(data);
|
||||
mutex_unlock(&data->lock_ps);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*val = ret & LTR501_PS_DATA_MASK;
|
||||
return IIO_VAL_INT;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
switch (chan->type) {
|
||||
case IIO_INTENSITY:
|
||||
if (data->als_contr & LTR501_CONTR_ALS_GAIN_MASK) {
|
||||
*val = 0;
|
||||
*val2 = 5000;
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
} else {
|
||||
*val = 1;
|
||||
*val2 = 0;
|
||||
return IIO_VAL_INT;
|
||||
}
|
||||
case IIO_PROXIMITY:
|
||||
i = (data->ps_contr & LTR501_CONTR_PS_GAIN_MASK) >>
|
||||
LTR501_CONTR_PS_GAIN_SHIFT;
|
||||
*val = ltr501_ps_gain[i][0];
|
||||
*val2 = ltr501_ps_gain[i][1];
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ltr501_get_ps_gain_index(int val, int val2)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ltr501_ps_gain); i++)
|
||||
if (val == ltr501_ps_gain[i][0] && val2 == ltr501_ps_gain[i][1])
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ltr501_write_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int val, int val2, long mask)
|
||||
{
|
||||
struct ltr501_data *data = iio_priv(indio_dev);
|
||||
int i;
|
||||
|
||||
if (iio_buffer_enabled(indio_dev))
|
||||
return -EBUSY;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
switch (chan->type) {
|
||||
case IIO_INTENSITY:
|
||||
if (val == 0 && val2 == 5000)
|
||||
data->als_contr |= LTR501_CONTR_ALS_GAIN_MASK;
|
||||
else if (val == 1 && val2 == 0)
|
||||
data->als_contr &= ~LTR501_CONTR_ALS_GAIN_MASK;
|
||||
else
|
||||
return -EINVAL;
|
||||
return i2c_smbus_write_byte_data(data->client,
|
||||
LTR501_ALS_CONTR, data->als_contr);
|
||||
case IIO_PROXIMITY:
|
||||
i = ltr501_get_ps_gain_index(val, val2);
|
||||
if (i < 0)
|
||||
return -EINVAL;
|
||||
data->ps_contr &= ~LTR501_CONTR_PS_GAIN_MASK;
|
||||
data->ps_contr |= i << LTR501_CONTR_PS_GAIN_SHIFT;
|
||||
return i2c_smbus_write_byte_data(data->client,
|
||||
LTR501_PS_CONTR, data->ps_contr);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static IIO_CONST_ATTR(in_proximity_scale_available, "1 0.25 0.125 0.0625");
|
||||
static IIO_CONST_ATTR(in_intensity_scale_available, "1 0.005");
|
||||
|
||||
static struct attribute *ltr501_attributes[] = {
|
||||
&iio_const_attr_in_proximity_scale_available.dev_attr.attr,
|
||||
&iio_const_attr_in_intensity_scale_available.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group ltr501_attribute_group = {
|
||||
.attrs = ltr501_attributes,
|
||||
};
|
||||
|
||||
static const struct iio_info ltr501_info = {
|
||||
.read_raw = ltr501_read_raw,
|
||||
.write_raw = ltr501_write_raw,
|
||||
.attrs = <r501_attribute_group,
|
||||
.driver_module = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int ltr501_write_contr(struct i2c_client *client, u8 als_val, u8 ps_val)
|
||||
{
|
||||
int ret = i2c_smbus_write_byte_data(client, LTR501_ALS_CONTR, als_val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return i2c_smbus_write_byte_data(client, LTR501_PS_CONTR, ps_val);
|
||||
}
|
||||
|
||||
static irqreturn_t ltr501_trigger_handler(int irq, void *p)
|
||||
{
|
||||
struct iio_poll_func *pf = p;
|
||||
struct iio_dev *indio_dev = pf->indio_dev;
|
||||
struct ltr501_data *data = iio_priv(indio_dev);
|
||||
u16 buf[8];
|
||||
__le16 als_buf[2];
|
||||
u8 mask = 0;
|
||||
int j = 0;
|
||||
int ret;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
/* figure out which data needs to be ready */
|
||||
if (test_bit(0, indio_dev->active_scan_mask) ||
|
||||
test_bit(1, indio_dev->active_scan_mask))
|
||||
mask |= LTR501_STATUS_ALS_RDY;
|
||||
if (test_bit(2, indio_dev->active_scan_mask))
|
||||
mask |= LTR501_STATUS_PS_RDY;
|
||||
|
||||
ret = ltr501_drdy(data, mask);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
if (mask & LTR501_STATUS_ALS_RDY) {
|
||||
ret = i2c_smbus_read_i2c_block_data(data->client,
|
||||
LTR501_ALS_DATA1, sizeof(als_buf), (u8 *) als_buf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (test_bit(0, indio_dev->active_scan_mask))
|
||||
buf[j++] = le16_to_cpu(als_buf[1]);
|
||||
if (test_bit(1, indio_dev->active_scan_mask))
|
||||
buf[j++] = le16_to_cpu(als_buf[0]);
|
||||
}
|
||||
|
||||
if (mask & LTR501_STATUS_PS_RDY) {
|
||||
ret = i2c_smbus_read_word_data(data->client, LTR501_PS_DATA);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
buf[j++] = ret & LTR501_PS_DATA_MASK;
|
||||
}
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, buf,
|
||||
iio_get_time_ns());
|
||||
|
||||
done:
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int ltr501_init(struct ltr501_data *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = i2c_smbus_read_byte_data(data->client, LTR501_ALS_CONTR);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
data->als_contr = ret | LTR501_CONTR_ACTIVE;
|
||||
|
||||
ret = i2c_smbus_read_byte_data(data->client, LTR501_PS_CONTR);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
data->ps_contr = ret | LTR501_CONTR_ACTIVE;
|
||||
|
||||
return ltr501_write_contr(data->client, data->als_contr,
|
||||
data->ps_contr);
|
||||
}
|
||||
|
||||
static int ltr501_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct ltr501_data *data;
|
||||
struct iio_dev *indio_dev;
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
data = iio_priv(indio_dev);
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
data->client = client;
|
||||
mutex_init(&data->lock_als);
|
||||
mutex_init(&data->lock_ps);
|
||||
|
||||
ret = i2c_smbus_read_byte_data(data->client, LTR501_PART_ID);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if ((ret >> 4) != 0x8)
|
||||
return -ENODEV;
|
||||
|
||||
indio_dev->dev.parent = &client->dev;
|
||||
indio_dev->info = <r501_info;
|
||||
indio_dev->channels = ltr501_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(ltr501_channels);
|
||||
indio_dev->name = LTR501_DRV_NAME;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
ret = ltr501_init(data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = iio_triggered_buffer_setup(indio_dev, NULL,
|
||||
ltr501_trigger_handler, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret)
|
||||
goto error_unreg_buffer;
|
||||
|
||||
return 0;
|
||||
|
||||
error_unreg_buffer:
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ltr501_powerdown(struct ltr501_data *data)
|
||||
{
|
||||
return ltr501_write_contr(data->client,
|
||||
data->als_contr & ~LTR501_CONTR_ACTIVE,
|
||||
data->ps_contr & ~LTR501_CONTR_ACTIVE);
|
||||
}
|
||||
|
||||
static int ltr501_remove(struct i2c_client *client)
|
||||
{
|
||||
struct iio_dev *indio_dev = i2c_get_clientdata(client);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
ltr501_powerdown(iio_priv(indio_dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int ltr501_suspend(struct device *dev)
|
||||
{
|
||||
struct ltr501_data *data = iio_priv(i2c_get_clientdata(
|
||||
to_i2c_client(dev)));
|
||||
return ltr501_powerdown(data);
|
||||
}
|
||||
|
||||
static int ltr501_resume(struct device *dev)
|
||||
{
|
||||
struct ltr501_data *data = iio_priv(i2c_get_clientdata(
|
||||
to_i2c_client(dev)));
|
||||
|
||||
return ltr501_write_contr(data->client, data->als_contr,
|
||||
data->ps_contr);
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(ltr501_pm_ops, ltr501_suspend, ltr501_resume);
|
||||
|
||||
static const struct i2c_device_id ltr501_id[] = {
|
||||
{ "ltr501", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ltr501_id);
|
||||
|
||||
static struct i2c_driver ltr501_driver = {
|
||||
.driver = {
|
||||
.name = LTR501_DRV_NAME,
|
||||
.pm = <r501_pm_ops,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = ltr501_probe,
|
||||
.remove = ltr501_remove,
|
||||
.id_table = ltr501_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(ltr501_driver);
|
||||
|
||||
MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
|
||||
MODULE_DESCRIPTION("Lite-On LTR501 ambient light and proximity sensor driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -179,7 +179,6 @@ static irqreturn_t tcs3472_trigger_handler(int irq, void *p)
|
|||
struct iio_poll_func *pf = p;
|
||||
struct iio_dev *indio_dev = pf->indio_dev;
|
||||
struct tcs3472_data *data = iio_priv(indio_dev);
|
||||
int len = 0;
|
||||
int i, j = 0;
|
||||
|
||||
int ret = tcs3472_req_data(data);
|
||||
|
@ -194,7 +193,6 @@ static irqreturn_t tcs3472_trigger_handler(int irq, void *p)
|
|||
goto done;
|
||||
|
||||
data->buffer[j++] = ret;
|
||||
len += 2;
|
||||
}
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
|
||||
|
|
|
@ -513,6 +513,7 @@ static int ak8975_probe(struct i2c_client *client,
|
|||
indio_dev->channels = ak8975_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(ak8975_channels);
|
||||
indio_dev->info = &ak8975_info;
|
||||
indio_dev->name = id->name;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
err = iio_device_register(indio_dev);
|
||||
|
|
|
@ -77,7 +77,7 @@ static int mpl3115_read_raw(struct iio_dev *indio_dev,
|
|||
int *val, int *val2, long mask)
|
||||
{
|
||||
struct mpl3115_data *data = iio_priv(indio_dev);
|
||||
s32 tmp = 0;
|
||||
__be32 tmp = 0;
|
||||
int ret;
|
||||
|
||||
switch (mask) {
|
||||
|
|
|
@ -65,7 +65,8 @@
|
|||
|
||||
#define SCA3000_RING_BUF_ENABLE 0x80
|
||||
#define SCA3000_RING_BUF_8BIT 0x40
|
||||
/* Free fall detection triggers an interrupt if the acceleration
|
||||
/*
|
||||
* Free fall detection triggers an interrupt if the acceleration
|
||||
* is below a threshold for equivalent of 25cm drop
|
||||
*/
|
||||
#define SCA3000_FREE_FALL_DETECT 0x10
|
||||
|
@ -73,8 +74,9 @@
|
|||
#define SCA3000_MEAS_MODE_OP_1 0x01
|
||||
#define SCA3000_MEAS_MODE_OP_2 0x02
|
||||
|
||||
/* In motion detection mode the accelerations are band pass filtered
|
||||
* (aprox 1 - 25Hz) and then a programmable threshold used to trigger
|
||||
/*
|
||||
* In motion detection mode the accelerations are band pass filtered
|
||||
* (approx 1 - 25Hz) and then a programmable threshold used to trigger
|
||||
* and interrupt.
|
||||
*/
|
||||
#define SCA3000_MEAS_MODE_MOT_DET 0x03
|
||||
|
@ -99,8 +101,10 @@
|
|||
#define SCA3000_REG_CTRL_SEL_MD_Y_TH 0x03
|
||||
#define SCA3000_REG_CTRL_SEL_MD_X_TH 0x04
|
||||
#define SCA3000_REG_CTRL_SEL_MD_Z_TH 0x05
|
||||
/* BE VERY CAREFUL WITH THIS, IF 3 BITS ARE NOT SET the device
|
||||
will not function */
|
||||
/*
|
||||
* BE VERY CAREFUL WITH THIS, IF 3 BITS ARE NOT SET the device
|
||||
* will not function
|
||||
*/
|
||||
#define SCA3000_REG_CTRL_SEL_OUT_CTRL 0x0B
|
||||
#define SCA3000_OUT_CTRL_PROT_MASK 0xE0
|
||||
#define SCA3000_OUT_CTRL_BUF_X_EN 0x10
|
||||
|
@ -109,8 +113,9 @@
|
|||
#define SCA3000_OUT_CTRL_BUF_DIV_4 0x02
|
||||
#define SCA3000_OUT_CTRL_BUF_DIV_2 0x01
|
||||
|
||||
/* Control which motion detector interrupts are on.
|
||||
* For now only OR combinations are supported.x
|
||||
/*
|
||||
* Control which motion detector interrupts are on.
|
||||
* For now only OR combinations are supported.
|
||||
*/
|
||||
#define SCA3000_MD_CTRL_PROT_MASK 0xC0
|
||||
#define SCA3000_MD_CTRL_OR_Y 0x01
|
||||
|
@ -121,7 +126,8 @@
|
|||
#define SCA3000_MD_CTRL_AND_X 0x10
|
||||
#define SAC3000_MD_CTRL_AND_Z 0x20
|
||||
|
||||
/* Some control registers of complex access methods requiring this register to
|
||||
/*
|
||||
* Some control registers of complex access methods requiring this register to
|
||||
* be used to remove a lock.
|
||||
*/
|
||||
#define SCA3000_REG_ADDR_UNLOCK 0x1e
|
||||
|
@ -139,7 +145,8 @@
|
|||
/* Values of multiplexed registers (write to ctrl_data after select) */
|
||||
#define SCA3000_REG_ADDR_CTRL_DATA 0x22
|
||||
|
||||
/* Measurement modes available on some sca3000 series chips. Code assumes others
|
||||
/*
|
||||
* Measurement modes available on some sca3000 series chips. Code assumes others
|
||||
* may become available in the future.
|
||||
*
|
||||
* Bypass - Bypass the low-pass filter in the signal channel so as to increase
|
||||
|
@ -160,7 +167,6 @@
|
|||
* struct sca3000_state - device instance state information
|
||||
* @us: the associated spi device
|
||||
* @info: chip variant information
|
||||
* @indio_dev: device information used by the IIO core
|
||||
* @interrupt_handler_ws: event interrupt handler for all events
|
||||
* @last_timestamp: the timestamp of the last event
|
||||
* @mo_det_use_count: reference counter for the motion detection unit
|
||||
|
|
|
@ -32,7 +32,8 @@ enum sca3000_variant {
|
|||
e05,
|
||||
};
|
||||
|
||||
/* Note where option modes are not defined, the chip simply does not
|
||||
/*
|
||||
* Note where option modes are not defined, the chip simply does not
|
||||
* support any.
|
||||
* Other chips in the sca3000 series use i2c and are not included here.
|
||||
*
|
||||
|
@ -191,7 +192,6 @@ error_ret:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Crucial that lock is called before calling this */
|
||||
/**
|
||||
* sca3000_read_ctrl_reg() read from lock protected control register.
|
||||
*
|
||||
|
@ -250,9 +250,8 @@ error_ret:
|
|||
}
|
||||
#endif /* SCA3000_DEBUG */
|
||||
|
||||
|
||||
/**
|
||||
* sca3000_show_reg() - sysfs interface to read the chip revision number
|
||||
* sca3000_show_rev() - sysfs interface to read the chip revision number
|
||||
**/
|
||||
static ssize_t sca3000_show_rev(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
|
@ -312,7 +311,7 @@ sca3000_show_available_measurement_modes(struct device *dev,
|
|||
}
|
||||
|
||||
/**
|
||||
* sca3000_show_measurmenet_mode() sysfs read of current mode
|
||||
* sca3000_show_measurement_mode() sysfs read of current mode
|
||||
**/
|
||||
static ssize_t
|
||||
sca3000_show_measurement_mode(struct device *dev,
|
||||
|
@ -403,7 +402,8 @@ error_ret:
|
|||
}
|
||||
|
||||
|
||||
/* Not even vaguely standard attributes so defined here rather than
|
||||
/*
|
||||
* Not even vaguely standard attributes so defined here rather than
|
||||
* in the relevant IIO core headers
|
||||
*/
|
||||
static IIO_DEVICE_ATTR(measurement_mode_available, S_IRUGO,
|
||||
|
@ -450,6 +450,18 @@ static const struct iio_chan_spec sca3000_channels[] = {
|
|||
SCA3000_CHAN(2, IIO_MOD_Z),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec sca3000_channels_with_temp[] = {
|
||||
SCA3000_CHAN(0, IIO_MOD_X),
|
||||
SCA3000_CHAN(1, IIO_MOD_Y),
|
||||
SCA3000_CHAN(2, IIO_MOD_Z),
|
||||
{
|
||||
.type = IIO_TEMP,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
|
||||
BIT(IIO_CHAN_INFO_OFFSET),
|
||||
},
|
||||
};
|
||||
|
||||
static u8 sca3000_addresses[3][3] = {
|
||||
[0] = {SCA3000_REG_ADDR_X_MSB, SCA3000_REG_CTRL_SEL_MD_X_TH,
|
||||
SCA3000_MD_CTRL_OR_X},
|
||||
|
@ -472,19 +484,30 @@ static int sca3000_read_raw(struct iio_dev *indio_dev,
|
|||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
mutex_lock(&st->lock);
|
||||
if (st->mo_det_use_count) {
|
||||
mutex_unlock(&st->lock);
|
||||
return -EBUSY;
|
||||
if (chan->type == IIO_ACCEL) {
|
||||
if (st->mo_det_use_count) {
|
||||
mutex_unlock(&st->lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
address = sca3000_addresses[chan->address][0];
|
||||
ret = sca3000_read_data_short(st, address, 2);
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&st->lock);
|
||||
return ret;
|
||||
}
|
||||
*val = (be16_to_cpup((__be16 *)st->rx) >> 3) & 0x1FFF;
|
||||
*val = ((*val) << (sizeof(*val)*8 - 13)) >>
|
||||
(sizeof(*val)*8 - 13);
|
||||
} else {
|
||||
/* get the temperature when available */
|
||||
ret = sca3000_read_data_short(st,
|
||||
SCA3000_REG_ADDR_TEMP_MSB, 2);
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&st->lock);
|
||||
return ret;
|
||||
}
|
||||
*val = ((st->rx[0] & 0x3F) << 3) | ((st->rx[1] & 0xE0) >> 5);
|
||||
}
|
||||
address = sca3000_addresses[chan->address][0];
|
||||
ret = sca3000_read_data_short(st, address, 2);
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&st->lock);
|
||||
return ret;
|
||||
}
|
||||
*val = (be16_to_cpup((__be16 *)st->rx) >> 3) & 0x1FFF;
|
||||
*val = ((*val) << (sizeof(*val)*8 - 13)) >>
|
||||
(sizeof(*val)*8 - 13);
|
||||
mutex_unlock(&st->lock);
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
|
@ -494,6 +517,10 @@ static int sca3000_read_raw(struct iio_dev *indio_dev,
|
|||
else /* temperature */
|
||||
*val2 = 555556;
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
case IIO_CHAN_INFO_OFFSET:
|
||||
*val = -214;
|
||||
*val2 = 600000;
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -547,7 +574,7 @@ error_ret:
|
|||
return ret;
|
||||
}
|
||||
/**
|
||||
* __sca3000_get_base_frequency() obtain mode specific base frequency
|
||||
* __sca3000_get_base_freq() obtain mode specific base frequency
|
||||
*
|
||||
* lock must be held
|
||||
**/
|
||||
|
@ -663,7 +690,8 @@ error_free_lock:
|
|||
return ret ? ret : len;
|
||||
}
|
||||
|
||||
/* Should only really be registered if ring buffer support is compiled in.
|
||||
/*
|
||||
* Should only really be registered if ring buffer support is compiled in.
|
||||
* Does no harm however and doing it right would add a fair bit of complexity
|
||||
*/
|
||||
static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(sca3000_read_av_freq);
|
||||
|
@ -672,37 +700,6 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
|
|||
sca3000_read_frequency,
|
||||
sca3000_set_frequency);
|
||||
|
||||
|
||||
/**
|
||||
* sca3000_read_temp() sysfs interface to get the temperature when available
|
||||
*
|
||||
* The alignment of data in here is downright odd. See data sheet.
|
||||
* Converting this into a meaningful value is left to inline functions in
|
||||
* userspace part of header.
|
||||
**/
|
||||
static ssize_t sca3000_read_temp(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct sca3000_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
int val;
|
||||
ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_TEMP_MSB, 2);
|
||||
if (ret < 0)
|
||||
goto error_ret;
|
||||
val = ((st->rx[0] & 0x3F) << 3) | ((st->rx[1] & 0xE0) >> 5);
|
||||
|
||||
return sprintf(buf, "%d\n", val);
|
||||
|
||||
error_ret:
|
||||
return ret;
|
||||
}
|
||||
static IIO_DEV_ATTR_TEMP_RAW(sca3000_read_temp);
|
||||
|
||||
static IIO_CONST_ATTR_TEMP_SCALE("0.555556");
|
||||
static IIO_CONST_ATTR_TEMP_OFFSET("-214.6");
|
||||
|
||||
/**
|
||||
* sca3000_read_thresh() - query of a threshold
|
||||
**/
|
||||
|
@ -782,33 +779,16 @@ static struct attribute *sca3000_attributes[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute *sca3000_attributes_with_temp[] = {
|
||||
&iio_dev_attr_revision.dev_attr.attr,
|
||||
&iio_dev_attr_measurement_mode_available.dev_attr.attr,
|
||||
&iio_dev_attr_measurement_mode.dev_attr.attr,
|
||||
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
|
||||
&iio_dev_attr_sampling_frequency.dev_attr.attr,
|
||||
/* Only present if temp sensor is */
|
||||
&iio_dev_attr_in_temp_raw.dev_attr.attr,
|
||||
&iio_const_attr_in_temp_offset.dev_attr.attr,
|
||||
&iio_const_attr_in_temp_scale.dev_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group sca3000_attribute_group = {
|
||||
.attrs = sca3000_attributes,
|
||||
};
|
||||
|
||||
static const struct attribute_group sca3000_attribute_group_with_temp = {
|
||||
.attrs = sca3000_attributes_with_temp,
|
||||
};
|
||||
|
||||
/* RING RELATED interrupt handler */
|
||||
/* depending on event, push to the ring buffer event chrdev or the event one */
|
||||
|
||||
/**
|
||||
* sca3000_event_handler() - handling ring and non ring events
|
||||
*
|
||||
* Ring related interrupt handler. Depending on event, push to
|
||||
* the ring buffer event chrdev or the event one.
|
||||
*
|
||||
* This function is complicated by the fact that the devices can signify ring
|
||||
* and non ring events via the same interrupt line and they can only
|
||||
* be distinguished via a read of the relevant status register.
|
||||
|
@ -820,7 +800,8 @@ static irqreturn_t sca3000_event_handler(int irq, void *private)
|
|||
int ret, val;
|
||||
s64 last_timestamp = iio_get_time_ns();
|
||||
|
||||
/* Could lead if badly timed to an extra read of status reg,
|
||||
/*
|
||||
* Could lead if badly timed to an extra read of status reg,
|
||||
* but ensures no interrupt is missed.
|
||||
*/
|
||||
mutex_lock(&st->lock);
|
||||
|
@ -935,7 +916,6 @@ static ssize_t sca3000_query_free_fall_mode(struct device *dev,
|
|||
* the device falls more than 25cm. This has not been tested due
|
||||
* to fragile wiring.
|
||||
**/
|
||||
|
||||
static ssize_t sca3000_set_free_fall_mode(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
|
@ -957,7 +937,7 @@ static ssize_t sca3000_set_free_fall_mode(struct device *dev,
|
|||
if (ret)
|
||||
goto error_ret;
|
||||
|
||||
/*if off and should be on*/
|
||||
/* if off and should be on */
|
||||
if (val && !(st->rx[0] & protect_mask))
|
||||
ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
|
||||
(st->rx[0] | SCA3000_FREE_FALL_DETECT));
|
||||
|
@ -972,7 +952,7 @@ error_ret:
|
|||
}
|
||||
|
||||
/**
|
||||
* sca3000_set_mo_det() simple on off control for motion detector
|
||||
* sca3000_write_event_config() simple on off control for motion detector
|
||||
*
|
||||
* This is a per axis control, but enabling any will result in the
|
||||
* motion detector unit being enabled.
|
||||
|
@ -992,13 +972,15 @@ static int sca3000_write_event_config(struct iio_dev *indio_dev,
|
|||
int num = chan->channel2;
|
||||
|
||||
mutex_lock(&st->lock);
|
||||
/* First read the motion detector config to find out if
|
||||
* this axis is on*/
|
||||
/*
|
||||
* First read the motion detector config to find out if
|
||||
* this axis is on
|
||||
*/
|
||||
ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL);
|
||||
if (ret < 0)
|
||||
goto exit_point;
|
||||
ctrlval = ret;
|
||||
/* Off and should be on */
|
||||
/* if off and should be on */
|
||||
if (state && !(ctrlval & sca3000_addresses[num][2])) {
|
||||
ret = sca3000_write_ctrl_reg(st,
|
||||
SCA3000_REG_CTRL_SEL_MD_CTRL,
|
||||
|
@ -1021,7 +1003,7 @@ static int sca3000_write_event_config(struct iio_dev *indio_dev,
|
|||
ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
|
||||
if (ret)
|
||||
goto exit_point;
|
||||
/*if off and should be on*/
|
||||
/* if off and should be on */
|
||||
if ((st->mo_det_use_count)
|
||||
&& ((st->rx[0] & protect_mask) != SCA3000_MEAS_MODE_MOT_DET))
|
||||
ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
|
||||
|
@ -1067,7 +1049,7 @@ static struct attribute_group sca3000_event_attribute_group = {
|
|||
* Devices use flash memory to store many of the register values
|
||||
* and hence can come up in somewhat unpredictable states.
|
||||
* Hence reset everything on driver load.
|
||||
**/
|
||||
**/
|
||||
static int sca3000_clean_setup(struct sca3000_state *st)
|
||||
{
|
||||
int ret;
|
||||
|
@ -1107,9 +1089,11 @@ static int sca3000_clean_setup(struct sca3000_state *st)
|
|||
| SCA3000_INT_MASK_ACTIVE_LOW);
|
||||
if (ret)
|
||||
goto error_ret;
|
||||
/* Select normal measurement mode, free fall off, ring off */
|
||||
/* Ring in 12 bit mode - it is fine to overwrite reserved bits 3,5
|
||||
* as that occurs in one of the example on the datasheet */
|
||||
/*
|
||||
* Select normal measurement mode, free fall off, ring off
|
||||
* Ring in 12 bit mode - it is fine to overwrite reserved bits 3,5
|
||||
* as that occurs in one of the example on the datasheet
|
||||
*/
|
||||
ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
|
||||
if (ret)
|
||||
goto error_ret;
|
||||
|
@ -1133,16 +1117,6 @@ static const struct iio_info sca3000_info = {
|
|||
.driver_module = THIS_MODULE,
|
||||
};
|
||||
|
||||
static const struct iio_info sca3000_info_with_temp = {
|
||||
.attrs = &sca3000_attribute_group_with_temp,
|
||||
.read_raw = &sca3000_read_raw,
|
||||
.read_event_value = &sca3000_read_thresh,
|
||||
.write_event_value = &sca3000_write_thresh,
|
||||
.read_event_config = &sca3000_read_event_config,
|
||||
.write_event_config = &sca3000_write_event_config,
|
||||
.driver_module = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int sca3000_probe(struct spi_device *spi)
|
||||
{
|
||||
int ret;
|
||||
|
@ -1162,10 +1136,12 @@ static int sca3000_probe(struct spi_device *spi)
|
|||
|
||||
indio_dev->dev.parent = &spi->dev;
|
||||
indio_dev->name = spi_get_device_id(spi)->name;
|
||||
if (st->info->temp_output)
|
||||
indio_dev->info = &sca3000_info_with_temp;
|
||||
else {
|
||||
indio_dev->info = &sca3000_info;
|
||||
indio_dev->info = &sca3000_info;
|
||||
if (st->info->temp_output) {
|
||||
indio_dev->channels = sca3000_channels_with_temp;
|
||||
indio_dev->num_channels =
|
||||
ARRAY_SIZE(sca3000_channels_with_temp);
|
||||
} else {
|
||||
indio_dev->channels = sca3000_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(sca3000_channels);
|
||||
}
|
||||
|
@ -1236,7 +1212,7 @@ static int sca3000_remove(struct spi_device *spi)
|
|||
struct iio_dev *indio_dev = spi_get_drvdata(spi);
|
||||
struct sca3000_state *st = iio_priv(indio_dev);
|
||||
|
||||
/* Must ensure no interrupts can be generated after this!*/
|
||||
/* Must ensure no interrupts can be generated after this! */
|
||||
sca3000_stop_all_interrupts(st);
|
||||
if (spi->irq)
|
||||
free_irq(spi->irq, indio_dev);
|
||||
|
|
|
@ -897,10 +897,6 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev,
|
|||
{
|
||||
struct mxs_lradc *lradc = iio_priv(iio_dev);
|
||||
|
||||
/* Check for invalid channel */
|
||||
if (chan->channel > LRADC_MAX_TOTAL_CHANS)
|
||||
return -EINVAL;
|
||||
|
||||
switch (m) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
if (chan->type == IIO_TEMP)
|
||||
|
|
Loading…
Reference in New Issue