4th set of IIO new drivers cleanups and fixes for the 3.9 cycle
+ a new spi helper function. 1) Introduce spi_sync_transfer and use it within IIO. Originally it was envisioned that this nice little boilerplate replacement would go through the spi tree, but Grant Likely stated he'd prefer we take it through IIO as the example usecases were all in IIO (and are also in this pull request). Note that given their may have been some unresolved elements related to the coccinelle element of the patch, that has been stripped out and will doubtlessly follow at a later date (along with lots of other patches for drivers elsewhere in the tree). 2) New Invensense MPU6050 driver. This is stripped down to pretty much the basics from the original submission with the intent to build up all the fancy bits in an incremental (and hence reviewable fashion). It's been through a good few revisions so nice to finally merge this. 3) Change to iio_channel_get api to simplify device tree based mappings. The actual mappings are currently under review. 4) Build fixes for !CONFIG_IIO_TRIGGER in the st_sensors driver. This one snuck past during review and testing but got picked up by Randy Dunlap in a randconfig build. 5) Some max1363 cleanups and enhancements. 6) Some comment fixes to make them coherent and comprehensible. 7) Trivial build warning fix in mxs-lradc -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQIcBAABAgAGBQJRF9/7AAoJEFSFNJnE9BaIYJgP+gMbD+knXpWm6o9VSO/mZ2O6 TfpoZsLr8pZIXDbzqrNdO0lC8EYYzyukV3leCJAXhtVSZ3cvdWgjN99rouRcngKP 0CchGTAzK9IpbyHzwG+Yjv5kkwTqF1u5OZmQDSdvTqvoKCIRgSYmS8MleOwJVWmR x9yO3ogmoPQQiPuFq8D/jm+0v3PfcepSjnTY3d24uNpbLqUjQ1vMLDNKf4Ipb+XD jykWVVxYet3+om6PuRLEHs7PeLoIsCY79xdh+43m00eoYel65rrqFzVeuEGUYgzl EMhiaZ4GU2EKe3xAgDLykYp2PO/WlvDrhlAfuCXnuuMBsAMl8aZ+da4cwT57Agd8 D2XNvmLyPeLuHyQWtT68LqPsoXBCs1ZosfdHslJ2MbQcB6JSPvFShhUKmw3rL8wY ksp8sU37ouGpWLV2anGxMtVJHaglFrpt4TYO1QWfbRcKfsYJ2l28YJ0JtgJVF7D+ G3GDOSsUtJNLSgc7WxbONw6BWeWq34nGQPRmHAgKOQkjLxzcK5WTu7GAs7gCpCLW JrK1bJ8+ai6HdVPKFzgLgRTi5IdUCLLFr19cQDnPoPViB0krv+58jtglpxF0ZbUH fK0OUh/F4CO2SX/bYCxqLPZ0TkUTwpxSF5+5rMcEtKW5FXMfvY6+rOLaHhJX5mu6 q37/4gygKhbVdZVl1RO8 =htuw -----END PGP SIGNATURE----- Merge tag 'iio-for-3.9d' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next Jonathan writes: "4th set of IIO new drivers cleanups and fixes for the 3.9 cycle + a new spi helper function. 1) Introduce spi_sync_transfer and use it within IIO. Originally it was envisioned that this nice little boilerplate replacement would go through the spi tree, but Grant Likely stated he'd prefer we take it through IIO as the example usecases were all in IIO (and are also in this pull request). Note that given their may have been some unresolved elements related to the coccinelle element of the patch, that has been stripped out and will doubtlessly follow at a later date (along with lots of other patches for drivers elsewhere in the tree). 2) New Invensense MPU6050 driver. This is stripped down to pretty much the basics from the original submission with the intent to build up all the fancy bits in an incremental (and hence reviewable fashion). It's been through a good few revisions so nice to finally merge this. 3) Change to iio_channel_get api to simplify device tree based mappings. The actual mappings are currently under review. 4) Build fixes for !CONFIG_IIO_TRIGGER in the st_sensors driver. This one snuck past during review and testing but got picked up by Randy Dunlap in a randconfig build. 5) Some max1363 cleanups and enhancements. 6) Some comment fixes to make them coherent and comprehensible. 7) Trivial build warning fix in mxs-lradc"
This commit is contained in:
commit
ad463ac427
|
@ -0,0 +1,13 @@
|
|||
What: /sys/bus/iio/devices/iio:deviceX/in_gyro_matrix
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_accel_matrix
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_magn_matrix
|
||||
KernelVersion: 3.4.0
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
This is mounting matrix for motion sensors. Mounting matrix
|
||||
is a 3x3 unitary matrix. A typical mounting matrix would look like
|
||||
[0, 1, 0; 1, 0, 0; 0, 0, -1]. Using this information, it would be
|
||||
easy to tell the relative positions among sensors as well as their
|
||||
positions relative to the board that holds these sensors. Identity matrix
|
||||
[1, 0, 0; 0, 1, 0; 0, 0, 1] means sensor chip and device are perfectly
|
||||
aligned with each other. All axes are exactly the same.
|
|
@ -135,8 +135,7 @@ static int adc_jack_probe(struct platform_device *pdev)
|
|||
;
|
||||
data->num_conditions = i;
|
||||
|
||||
data->chan = iio_channel_get(dev_name(&pdev->dev),
|
||||
pdata->consumer_channel);
|
||||
data->chan = iio_channel_get(&pdev->dev, pdata->consumer_channel);
|
||||
if (IS_ERR(data->chan)) {
|
||||
err = PTR_ERR(data->chan);
|
||||
goto out;
|
||||
|
|
|
@ -94,7 +94,6 @@ error_ret:
|
|||
|
||||
static int kxsd9_read(struct iio_dev *indio_dev, u8 address)
|
||||
{
|
||||
struct spi_message msg;
|
||||
int ret;
|
||||
struct kxsd9_state *st = iio_priv(indio_dev);
|
||||
struct spi_transfer xfers[] = {
|
||||
|
@ -112,10 +111,7 @@ static int kxsd9_read(struct iio_dev *indio_dev, u8 address)
|
|||
|
||||
mutex_lock(&st->buf_lock);
|
||||
st->tx[0] = KXSD9_READ(address);
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfers[0], &msg);
|
||||
spi_message_add_tail(&xfers[1], &msg);
|
||||
ret = spi_sync(st->us, &msg);
|
||||
ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
|
||||
if (ret)
|
||||
return ret;
|
||||
return (((u16)(st->rx[0])) << 8) | (st->rx[1] & 0xF0);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include <linux/irq.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/iio/trigger.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
|
||||
#include <linux/iio/common/st_sensors.h>
|
||||
|
@ -419,10 +419,15 @@ static const struct iio_info accel_info = {
|
|||
.write_raw = &st_accel_write_raw,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_IIO_TRIGGER
|
||||
static const struct iio_trigger_ops st_accel_trigger_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.set_trigger_state = ST_ACCEL_TRIGGER_SET_STATE,
|
||||
};
|
||||
#define ST_ACCEL_TRIGGER_OPS (&st_accel_trigger_ops)
|
||||
#else
|
||||
#define ST_ACCEL_TRIGGER_OPS NULL
|
||||
#endif
|
||||
|
||||
int st_accel_common_probe(struct iio_dev *indio_dev)
|
||||
{
|
||||
|
@ -455,7 +460,7 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
|
|||
goto st_accel_common_probe_error;
|
||||
|
||||
err = st_sensors_allocate_trigger(indio_dev,
|
||||
&st_accel_trigger_ops);
|
||||
ST_ACCEL_TRIGGER_OPS);
|
||||
if (err < 0)
|
||||
goto st_accel_probe_trigger_error;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/trigger.h>
|
||||
|
||||
#include <linux/iio/common/st_sensors.h>
|
||||
#include <linux/iio/common/st_sensors_i2c.h>
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/trigger.h>
|
||||
|
||||
#include <linux/iio/common/st_sensors.h>
|
||||
#include <linux/iio/common/st_sensors_spi.h>
|
||||
|
|
|
@ -163,6 +163,8 @@ struct max1363_chip_info {
|
|||
* @mask_low: bitmask for enabled low thresholds
|
||||
* @thresh_high: high threshold values
|
||||
* @thresh_low: low threshold values
|
||||
* @vref: Reference voltage regulator
|
||||
* @vref_uv: Actual (external or internal) reference voltage
|
||||
*/
|
||||
struct max1363_state {
|
||||
struct i2c_client *client;
|
||||
|
@ -182,6 +184,8 @@ struct max1363_state {
|
|||
/* 4x unipolar first then the fours bipolar ones */
|
||||
s16 thresh_high[8];
|
||||
s16 thresh_low[8];
|
||||
struct regulator *vref;
|
||||
u32 vref_uv;
|
||||
};
|
||||
|
||||
#define MAX1363_MODE_SINGLE(_num, _mask) { \
|
||||
|
@ -393,6 +397,8 @@ static int max1363_read_raw(struct iio_dev *indio_dev,
|
|||
{
|
||||
struct max1363_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
unsigned long scale_uv;
|
||||
|
||||
switch (m) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
ret = max1363_read_single_chan(indio_dev, chan, val, m);
|
||||
|
@ -400,16 +406,10 @@ static int max1363_read_raw(struct iio_dev *indio_dev,
|
|||
return ret;
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
if ((1 << (st->chip_info->bits + 1)) >
|
||||
st->chip_info->int_vref_mv) {
|
||||
*val = 0;
|
||||
*val2 = 500000;
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
} else {
|
||||
*val = (st->chip_info->int_vref_mv)
|
||||
>> st->chip_info->bits;
|
||||
return IIO_VAL_INT;
|
||||
}
|
||||
scale_uv = st->vref_uv >> st->chip_info->bits;
|
||||
*val = scale_uv / 1000;
|
||||
*val2 = (scale_uv % 1000) * 1000;
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1390,12 +1390,16 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = {
|
|||
|
||||
static int max1363_initial_setup(struct max1363_state *st)
|
||||
{
|
||||
st->setupbyte = MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD
|
||||
| MAX1363_SETUP_POWER_UP_INT_REF
|
||||
| MAX1363_SETUP_INT_CLOCK
|
||||
st->setupbyte = MAX1363_SETUP_INT_CLOCK
|
||||
| MAX1363_SETUP_UNIPOLAR
|
||||
| MAX1363_SETUP_NORESET;
|
||||
|
||||
if (st->vref)
|
||||
st->setupbyte |= MAX1363_SETUP_AIN3_IS_REF_EXT_TO_REF;
|
||||
else
|
||||
st->setupbyte |= MAX1363_SETUP_POWER_UP_INT_REF
|
||||
| MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_INT;
|
||||
|
||||
/* Set scan mode writes the config anyway so wait until then */
|
||||
st->setupbyte = MAX1363_SETUP_BYTE(st->setupbyte);
|
||||
st->current_mode = &max1363_mode_table[st->chip_info->default_mode];
|
||||
|
@ -1410,8 +1414,9 @@ static int max1363_alloc_scan_masks(struct iio_dev *indio_dev)
|
|||
unsigned long *masks;
|
||||
int i;
|
||||
|
||||
masks = kzalloc(BITS_TO_LONGS(MAX1363_MAX_CHANNELS)*sizeof(long)*
|
||||
(st->chip_info->num_modes + 1), GFP_KERNEL);
|
||||
masks = devm_kzalloc(&indio_dev->dev,
|
||||
BITS_TO_LONGS(MAX1363_MAX_CHANNELS) * sizeof(long) *
|
||||
(st->chip_info->num_modes + 1), GFP_KERNEL);
|
||||
if (!masks)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -1490,6 +1495,7 @@ static int max1363_probe(struct i2c_client *client,
|
|||
int ret;
|
||||
struct max1363_state *st;
|
||||
struct iio_dev *indio_dev;
|
||||
struct regulator *vref;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(struct max1363_state));
|
||||
if (indio_dev == NULL) {
|
||||
|
@ -1504,7 +1510,7 @@ static int max1363_probe(struct i2c_client *client,
|
|||
|
||||
st = iio_priv(indio_dev);
|
||||
|
||||
st->reg = regulator_get(&client->dev, "vcc");
|
||||
st->reg = devm_regulator_get(&client->dev, "vcc");
|
||||
if (IS_ERR(st->reg)) {
|
||||
ret = PTR_ERR(st->reg);
|
||||
goto error_unregister_map;
|
||||
|
@ -1512,7 +1518,7 @@ static int max1363_probe(struct i2c_client *client,
|
|||
|
||||
ret = regulator_enable(st->reg);
|
||||
if (ret)
|
||||
goto error_put_reg;
|
||||
goto error_unregister_map;
|
||||
|
||||
/* this is only used for device removal purposes */
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
|
@ -1520,6 +1526,23 @@ static int max1363_probe(struct i2c_client *client,
|
|||
st->chip_info = &max1363_chip_info_tbl[id->driver_data];
|
||||
st->client = client;
|
||||
|
||||
st->vref_uv = st->chip_info->int_vref_mv * 1000;
|
||||
vref = devm_regulator_get(&client->dev, "vref");
|
||||
if (!IS_ERR(vref)) {
|
||||
int vref_uv;
|
||||
|
||||
ret = regulator_enable(vref);
|
||||
if (ret)
|
||||
goto error_disable_reg;
|
||||
st->vref = vref;
|
||||
vref_uv = regulator_get_voltage(vref);
|
||||
if (vref_uv <= 0) {
|
||||
ret = -EINVAL;
|
||||
goto error_disable_reg;
|
||||
}
|
||||
st->vref_uv = vref_uv;
|
||||
}
|
||||
|
||||
ret = max1363_alloc_scan_masks(indio_dev);
|
||||
if (ret)
|
||||
goto error_disable_reg;
|
||||
|
@ -1533,15 +1556,15 @@ static int max1363_probe(struct i2c_client *client,
|
|||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
ret = max1363_initial_setup(st);
|
||||
if (ret < 0)
|
||||
goto error_free_available_scan_masks;
|
||||
goto error_disable_reg;
|
||||
|
||||
ret = iio_triggered_buffer_setup(indio_dev, NULL,
|
||||
&max1363_trigger_handler, &max1363_buffered_setup_ops);
|
||||
if (ret)
|
||||
goto error_free_available_scan_masks;
|
||||
goto error_disable_reg;
|
||||
|
||||
if (client->irq) {
|
||||
ret = request_threaded_irq(st->client->irq,
|
||||
ret = devm_request_threaded_irq(&client->dev, st->client->irq,
|
||||
NULL,
|
||||
&max1363_event_handler,
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
|
@ -1554,20 +1577,16 @@ static int max1363_probe(struct i2c_client *client,
|
|||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret < 0)
|
||||
goto error_free_irq;
|
||||
goto error_uninit_buffer;
|
||||
|
||||
return 0;
|
||||
error_free_irq:
|
||||
if (client->irq)
|
||||
free_irq(st->client->irq, indio_dev);
|
||||
|
||||
error_uninit_buffer:
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
error_free_available_scan_masks:
|
||||
kfree(indio_dev->available_scan_masks);
|
||||
error_disable_reg:
|
||||
if (st->vref)
|
||||
regulator_disable(st->vref);
|
||||
regulator_disable(st->reg);
|
||||
error_put_reg:
|
||||
regulator_put(st->reg);
|
||||
error_unregister_map:
|
||||
iio_map_array_unregister(indio_dev);
|
||||
error_free_device:
|
||||
|
@ -1582,12 +1601,10 @@ static int max1363_remove(struct i2c_client *client)
|
|||
struct max1363_state *st = iio_priv(indio_dev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
if (client->irq)
|
||||
free_irq(st->client->irq, indio_dev);
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
kfree(indio_dev->available_scan_masks);
|
||||
if (st->vref)
|
||||
regulator_disable(st->vref);
|
||||
regulator_disable(st->reg);
|
||||
regulator_put(st->reg);
|
||||
iio_map_array_unregister(indio_dev);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
|
|
|
@ -213,7 +213,6 @@ static int ad5360_read(struct iio_dev *indio_dev, unsigned int type,
|
|||
unsigned int addr)
|
||||
{
|
||||
struct ad5360_state *st = iio_priv(indio_dev);
|
||||
struct spi_message m;
|
||||
int ret;
|
||||
struct spi_transfer t[] = {
|
||||
{
|
||||
|
@ -226,10 +225,6 @@ static int ad5360_read(struct iio_dev *indio_dev, unsigned int type,
|
|||
},
|
||||
};
|
||||
|
||||
spi_message_init(&m);
|
||||
spi_message_add_tail(&t[0], &m);
|
||||
spi_message_add_tail(&t[1], &m);
|
||||
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
|
||||
st->data[0].d32 = cpu_to_be32(AD5360_CMD(AD5360_CMD_SPECIAL_FUNCTION) |
|
||||
|
@ -237,7 +232,7 @@ static int ad5360_read(struct iio_dev *indio_dev, unsigned int type,
|
|||
AD5360_READBACK_TYPE(type) |
|
||||
AD5360_READBACK_ADDR(addr));
|
||||
|
||||
ret = spi_sync(st->spi, &m);
|
||||
ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
|
||||
if (ret >= 0)
|
||||
ret = be32_to_cpu(st->data[1].d32) & 0xffff;
|
||||
|
||||
|
|
|
@ -127,7 +127,6 @@ static int ad5421_write(struct iio_dev *indio_dev, unsigned int reg,
|
|||
static int ad5421_read(struct iio_dev *indio_dev, unsigned int reg)
|
||||
{
|
||||
struct ad5421_state *st = iio_priv(indio_dev);
|
||||
struct spi_message m;
|
||||
int ret;
|
||||
struct spi_transfer t[] = {
|
||||
{
|
||||
|
@ -140,15 +139,11 @@ static int ad5421_read(struct iio_dev *indio_dev, unsigned int reg)
|
|||
},
|
||||
};
|
||||
|
||||
spi_message_init(&m);
|
||||
spi_message_add_tail(&t[0], &m);
|
||||
spi_message_add_tail(&t[1], &m);
|
||||
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
|
||||
st->data[0].d32 = cpu_to_be32((1 << 23) | (reg << 16));
|
||||
|
||||
ret = spi_sync(st->spi, &m);
|
||||
ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
|
||||
if (ret >= 0)
|
||||
ret = be32_to_cpu(st->data[1].d32) & 0xffff;
|
||||
|
||||
|
|
|
@ -85,11 +85,7 @@ static int ad5504_spi_read(struct spi_device *spi, u8 addr)
|
|||
.rx_buf = &val,
|
||||
.len = 2,
|
||||
};
|
||||
struct spi_message m;
|
||||
|
||||
spi_message_init(&m);
|
||||
spi_message_add_tail(&t, &m);
|
||||
ret = spi_sync(spi, &m);
|
||||
ret = spi_sync_transfer(spi, &t, 1);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
|
@ -117,18 +117,13 @@ static int ad5686_spi_read(struct ad5686_state *st, u8 addr)
|
|||
.len = 3,
|
||||
},
|
||||
};
|
||||
struct spi_message m;
|
||||
int ret;
|
||||
|
||||
spi_message_init(&m);
|
||||
spi_message_add_tail(&t[0], &m);
|
||||
spi_message_add_tail(&t[1], &m);
|
||||
|
||||
st->data[0].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_READBACK_ENABLE) |
|
||||
AD5686_ADDR(addr));
|
||||
st->data[1].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_NOOP));
|
||||
|
||||
ret = spi_sync(st->spi, &m);
|
||||
ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -153,7 +153,6 @@ static int ad5755_write_ctrl(struct iio_dev *indio_dev, unsigned int channel,
|
|||
static int ad5755_read(struct iio_dev *indio_dev, unsigned int addr)
|
||||
{
|
||||
struct ad5755_state *st = iio_priv(indio_dev);
|
||||
struct spi_message m;
|
||||
int ret;
|
||||
struct spi_transfer t[] = {
|
||||
{
|
||||
|
@ -167,16 +166,12 @@ static int ad5755_read(struct iio_dev *indio_dev, unsigned int addr)
|
|||
},
|
||||
};
|
||||
|
||||
spi_message_init(&m);
|
||||
spi_message_add_tail(&t[0], &m);
|
||||
spi_message_add_tail(&t[1], &m);
|
||||
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
|
||||
st->data[0].d32 = cpu_to_be32(AD5755_READ_FLAG | (addr << 16));
|
||||
st->data[1].d32 = cpu_to_be32(AD5755_NOOP);
|
||||
|
||||
ret = spi_sync(st->spi, &m);
|
||||
ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
|
||||
if (ret >= 0)
|
||||
ret = be32_to_cpu(st->data[1].d32) & 0xffff;
|
||||
|
||||
|
|
|
@ -135,7 +135,6 @@ static int ad5764_read(struct iio_dev *indio_dev, unsigned int reg,
|
|||
unsigned int *val)
|
||||
{
|
||||
struct ad5764_state *st = iio_priv(indio_dev);
|
||||
struct spi_message m;
|
||||
int ret;
|
||||
struct spi_transfer t[] = {
|
||||
{
|
||||
|
@ -148,15 +147,11 @@ static int ad5764_read(struct iio_dev *indio_dev, unsigned int reg,
|
|||
},
|
||||
};
|
||||
|
||||
spi_message_init(&m);
|
||||
spi_message_add_tail(&t[0], &m);
|
||||
spi_message_add_tail(&t[1], &m);
|
||||
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
|
||||
st->data[0].d32 = cpu_to_be32((1 << 23) | (reg << 16));
|
||||
|
||||
ret = spi_sync(st->spi, &m);
|
||||
ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
|
||||
if (ret >= 0)
|
||||
*val = be32_to_cpu(st->data[1].d32) & 0xffff;
|
||||
|
||||
|
|
|
@ -125,7 +125,6 @@ static int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val)
|
|||
u8 d8[4];
|
||||
} data[3];
|
||||
int ret;
|
||||
struct spi_message msg;
|
||||
struct spi_transfer xfers[] = {
|
||||
{
|
||||
.tx_buf = &data[0].d8[1],
|
||||
|
@ -144,10 +143,7 @@ static int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val)
|
|||
AD5791_ADDR(addr));
|
||||
data[1].d32 = cpu_to_be32(AD5791_ADDR(AD5791_ADDR_NOOP));
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfers[0], &msg);
|
||||
spi_message_add_tail(&xfers[1], &msg);
|
||||
ret = spi_sync(spi, &msg);
|
||||
ret = spi_sync_transfer(spi, xfers, ARRAY_SIZE(xfers));
|
||||
|
||||
*val = be32_to_cpu(data[2].d32);
|
||||
|
||||
|
|
|
@ -287,7 +287,6 @@ struct ad9523_state {
|
|||
static int ad9523_read(struct iio_dev *indio_dev, unsigned addr)
|
||||
{
|
||||
struct ad9523_state *st = iio_priv(indio_dev);
|
||||
struct spi_message m;
|
||||
int ret;
|
||||
|
||||
/* We encode the register size 1..3 bytes into the register address.
|
||||
|
@ -305,15 +304,11 @@ static int ad9523_read(struct iio_dev *indio_dev, unsigned addr)
|
|||
},
|
||||
};
|
||||
|
||||
spi_message_init(&m);
|
||||
spi_message_add_tail(&t[0], &m);
|
||||
spi_message_add_tail(&t[1], &m);
|
||||
|
||||
st->data[0].d32 = cpu_to_be32(AD9523_READ |
|
||||
AD9523_CNT(AD9523_TRANSF_LEN(addr)) |
|
||||
AD9523_ADDR(addr));
|
||||
|
||||
ret = spi_sync(st->spi, &m);
|
||||
ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
|
||||
if (ret < 0)
|
||||
dev_err(&indio_dev->dev, "read failed (%d)", ret);
|
||||
else
|
||||
|
@ -326,7 +321,6 @@ static int ad9523_read(struct iio_dev *indio_dev, unsigned addr)
|
|||
static int ad9523_write(struct iio_dev *indio_dev, unsigned addr, unsigned val)
|
||||
{
|
||||
struct ad9523_state *st = iio_priv(indio_dev);
|
||||
struct spi_message m;
|
||||
int ret;
|
||||
struct spi_transfer t[] = {
|
||||
{
|
||||
|
@ -338,16 +332,12 @@ static int ad9523_write(struct iio_dev *indio_dev, unsigned addr, unsigned val)
|
|||
},
|
||||
};
|
||||
|
||||
spi_message_init(&m);
|
||||
spi_message_add_tail(&t[0], &m);
|
||||
spi_message_add_tail(&t[1], &m);
|
||||
|
||||
st->data[0].d32 = cpu_to_be32(AD9523_WRITE |
|
||||
AD9523_CNT(AD9523_TRANSF_LEN(addr)) |
|
||||
AD9523_ADDR(addr));
|
||||
st->data[1].d32 = cpu_to_be32(val);
|
||||
|
||||
ret = spi_sync(st->spi, &m);
|
||||
ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
|
||||
|
||||
if (ret < 0)
|
||||
dev_err(&indio_dev->dev, "write failed (%d)", ret);
|
||||
|
|
|
@ -213,7 +213,6 @@ error_ret:
|
|||
static int adxrs450_spi_initial(struct adxrs450_state *st,
|
||||
u32 *val, char chk)
|
||||
{
|
||||
struct spi_message msg;
|
||||
int ret;
|
||||
u32 tx;
|
||||
struct spi_transfer xfers = {
|
||||
|
@ -228,9 +227,7 @@ static int adxrs450_spi_initial(struct adxrs450_state *st,
|
|||
if (chk)
|
||||
tx |= (ADXRS450_CHK | ADXRS450_P);
|
||||
st->tx = cpu_to_be32(tx);
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfers, &msg);
|
||||
ret = spi_sync(st->us, &msg);
|
||||
ret = spi_sync_transfer(st->us, &xfers, 1);
|
||||
if (ret) {
|
||||
dev_err(&st->us->dev, "Problem while reading initializing data\n");
|
||||
goto error_ret;
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/iio/trigger.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
|
||||
#include <linux/iio/common/st_sensors.h>
|
||||
|
@ -287,10 +287,15 @@ static const struct iio_info gyro_info = {
|
|||
.write_raw = &st_gyro_write_raw,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_IIO_TRIGGER
|
||||
static const struct iio_trigger_ops st_gyro_trigger_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.set_trigger_state = ST_GYRO_TRIGGER_SET_STATE,
|
||||
};
|
||||
#define ST_GYRO_TRIGGER_OPS (&st_gyro_trigger_ops)
|
||||
#else
|
||||
#define ST_GYRO_TRIGGER_OPS NULL
|
||||
#endif
|
||||
|
||||
int st_gyro_common_probe(struct iio_dev *indio_dev)
|
||||
{
|
||||
|
@ -323,7 +328,7 @@ int st_gyro_common_probe(struct iio_dev *indio_dev)
|
|||
goto st_gyro_common_probe_error;
|
||||
|
||||
err = st_sensors_allocate_trigger(indio_dev,
|
||||
&st_gyro_trigger_ops);
|
||||
ST_GYRO_TRIGGER_OPS);
|
||||
if (err < 0)
|
||||
goto st_gyro_probe_trigger_error;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/trigger.h>
|
||||
|
||||
#include <linux/iio/common/st_sensors.h>
|
||||
#include <linux/iio/common/st_sensors_i2c.h>
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/trigger.h>
|
||||
|
||||
#include <linux/iio/common/st_sensors.h>
|
||||
#include <linux/iio/common/st_sensors_spi.h>
|
||||
|
|
|
@ -36,3 +36,5 @@ 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"
|
||||
|
|
|
@ -11,3 +11,5 @@ adis_lib-y += adis.o
|
|||
adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_trigger.o
|
||||
adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
|
||||
obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
|
||||
|
||||
obj-y += inv_mpu6050/
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
#
|
||||
# inv-mpu6050 drivers for Invensense MPU devices and combos
|
||||
#
|
||||
|
||||
config INV_MPU6050_IIO
|
||||
tristate "Invensense MPU6050 devices"
|
||||
depends on I2C && SYSFS
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
help
|
||||
This driver supports the Invensense MPU6050 devices.
|
||||
It is a gyroscope/accelerometer combo device.
|
||||
This driver can be built as a module. The module will be called
|
||||
inv-mpu6050.
|
|
@ -0,0 +1,6 @@
|
|||
#
|
||||
# Makefile for Invensense MPU6050 device.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_INV_MPU6050_IIO) += inv-mpu6050.o
|
||||
inv-mpu6050-objs := inv_mpu_core.o inv_mpu_ring.o inv_mpu_trigger.o
|
|
@ -0,0 +1,795 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Invensense, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include "inv_mpu_iio.h"
|
||||
|
||||
/*
|
||||
* this is the gyro scale translated from dynamic range plus/minus
|
||||
* {250, 500, 1000, 2000} to rad/s
|
||||
*/
|
||||
static const int gyro_scale_6050[] = {133090, 266181, 532362, 1064724};
|
||||
|
||||
/*
|
||||
* this is the accel scale translated from dynamic range plus/minus
|
||||
* {2, 4, 8, 16} to m/s^2
|
||||
*/
|
||||
static const int accel_scale[] = {598, 1196, 2392, 4785};
|
||||
|
||||
static const struct inv_mpu6050_reg_map reg_set_6050 = {
|
||||
.sample_rate_div = INV_MPU6050_REG_SAMPLE_RATE_DIV,
|
||||
.lpf = INV_MPU6050_REG_CONFIG,
|
||||
.user_ctrl = INV_MPU6050_REG_USER_CTRL,
|
||||
.fifo_en = INV_MPU6050_REG_FIFO_EN,
|
||||
.gyro_config = INV_MPU6050_REG_GYRO_CONFIG,
|
||||
.accl_config = INV_MPU6050_REG_ACCEL_CONFIG,
|
||||
.fifo_count_h = INV_MPU6050_REG_FIFO_COUNT_H,
|
||||
.fifo_r_w = INV_MPU6050_REG_FIFO_R_W,
|
||||
.raw_gyro = INV_MPU6050_REG_RAW_GYRO,
|
||||
.raw_accl = INV_MPU6050_REG_RAW_ACCEL,
|
||||
.temperature = INV_MPU6050_REG_TEMPERATURE,
|
||||
.int_enable = INV_MPU6050_REG_INT_ENABLE,
|
||||
.pwr_mgmt_1 = INV_MPU6050_REG_PWR_MGMT_1,
|
||||
.pwr_mgmt_2 = INV_MPU6050_REG_PWR_MGMT_2,
|
||||
};
|
||||
|
||||
static const struct inv_mpu6050_chip_config chip_config_6050 = {
|
||||
.fsr = INV_MPU6050_FSR_2000DPS,
|
||||
.lpf = INV_MPU6050_FILTER_20HZ,
|
||||
.fifo_rate = INV_MPU6050_INIT_FIFO_RATE,
|
||||
.gyro_fifo_enable = false,
|
||||
.accl_fifo_enable = false,
|
||||
.accl_fs = INV_MPU6050_FS_02G,
|
||||
};
|
||||
|
||||
static const struct inv_mpu6050_hw hw_info[INV_NUM_PARTS] = {
|
||||
{
|
||||
.num_reg = 117,
|
||||
.name = "MPU6050",
|
||||
.reg = ®_set_6050,
|
||||
.config = &chip_config_6050,
|
||||
},
|
||||
};
|
||||
|
||||
int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 d)
|
||||
{
|
||||
return i2c_smbus_write_i2c_block_data(st->client, reg, 1, &d);
|
||||
}
|
||||
|
||||
int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask)
|
||||
{
|
||||
u8 d, mgmt_1;
|
||||
int result;
|
||||
|
||||
/* switch clock needs to be careful. Only when gyro is on, can
|
||||
clock source be switched to gyro. Otherwise, it must be set to
|
||||
internal clock */
|
||||
if (INV_MPU6050_BIT_PWR_GYRO_STBY == mask) {
|
||||
result = i2c_smbus_read_i2c_block_data(st->client,
|
||||
st->reg->pwr_mgmt_1, 1, &mgmt_1);
|
||||
if (result != 1)
|
||||
return result;
|
||||
|
||||
mgmt_1 &= ~INV_MPU6050_BIT_CLK_MASK;
|
||||
}
|
||||
|
||||
if ((INV_MPU6050_BIT_PWR_GYRO_STBY == mask) && (!en)) {
|
||||
/* turning off gyro requires switch to internal clock first.
|
||||
Then turn off gyro engine */
|
||||
mgmt_1 |= INV_CLK_INTERNAL;
|
||||
result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, mgmt_1);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
|
||||
result = i2c_smbus_read_i2c_block_data(st->client,
|
||||
st->reg->pwr_mgmt_2, 1, &d);
|
||||
if (result != 1)
|
||||
return result;
|
||||
if (en)
|
||||
d &= ~mask;
|
||||
else
|
||||
d |= mask;
|
||||
result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_2, d);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
if (en) {
|
||||
/* Wait for output stablize */
|
||||
msleep(INV_MPU6050_TEMP_UP_TIME);
|
||||
if (INV_MPU6050_BIT_PWR_GYRO_STBY == mask) {
|
||||
/* switch internal clock to PLL */
|
||||
mgmt_1 |= INV_CLK_PLL;
|
||||
result = inv_mpu6050_write_reg(st,
|
||||
st->reg->pwr_mgmt_1, mgmt_1);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (power_on)
|
||||
result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, 0);
|
||||
else
|
||||
result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1,
|
||||
INV_MPU6050_BIT_SLEEP);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
if (power_on)
|
||||
msleep(INV_MPU6050_REG_UP_TIME);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* inv_mpu6050_init_config() - Initialize hardware, disable FIFO.
|
||||
*
|
||||
* Initial configuration:
|
||||
* FSR: ± 2000DPS
|
||||
* DLPF: 20Hz
|
||||
* FIFO rate: 50Hz
|
||||
* Clock source: Gyro PLL
|
||||
*/
|
||||
static int inv_mpu6050_init_config(struct iio_dev *indio_dev)
|
||||
{
|
||||
int result;
|
||||
u8 d;
|
||||
struct inv_mpu6050_state *st = iio_priv(indio_dev);
|
||||
|
||||
result = inv_mpu6050_set_power_itg(st, true);
|
||||
if (result)
|
||||
return result;
|
||||
d = (INV_MPU6050_FSR_2000DPS << INV_MPU6050_GYRO_CONFIG_FSR_SHIFT);
|
||||
result = inv_mpu6050_write_reg(st, st->reg->gyro_config, d);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
d = INV_MPU6050_FILTER_20HZ;
|
||||
result = inv_mpu6050_write_reg(st, st->reg->lpf, d);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
d = INV_MPU6050_ONE_K_HZ / INV_MPU6050_INIT_FIFO_RATE - 1;
|
||||
result = inv_mpu6050_write_reg(st, st->reg->sample_rate_div, d);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
d = (INV_MPU6050_FS_02G << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT);
|
||||
result = inv_mpu6050_write_reg(st, st->reg->accl_config, d);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
memcpy(&st->chip_config, hw_info[st->chip_type].config,
|
||||
sizeof(struct inv_mpu6050_chip_config));
|
||||
result = inv_mpu6050_set_power_itg(st, false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int inv_mpu6050_sensor_show(struct inv_mpu6050_state *st, int reg,
|
||||
int axis, int *val)
|
||||
{
|
||||
int ind, result;
|
||||
__be16 d;
|
||||
|
||||
ind = (axis - IIO_MOD_X) * 2;
|
||||
result = i2c_smbus_read_i2c_block_data(st->client, reg + ind, 2,
|
||||
(u8 *)&d);
|
||||
if (result != 2)
|
||||
return -EINVAL;
|
||||
*val = (short)be16_to_cpup(&d);
|
||||
|
||||
return IIO_VAL_INT;
|
||||
}
|
||||
|
||||
static int inv_mpu6050_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val,
|
||||
int *val2,
|
||||
long mask) {
|
||||
struct inv_mpu6050_state *st = iio_priv(indio_dev);
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
{
|
||||
int ret, result;
|
||||
|
||||
ret = IIO_VAL_INT;
|
||||
result = 0;
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
if (!st->chip_config.enable) {
|
||||
result = inv_mpu6050_set_power_itg(st, true);
|
||||
if (result)
|
||||
goto error_read_raw;
|
||||
}
|
||||
/* when enable is on, power is already on */
|
||||
switch (chan->type) {
|
||||
case IIO_ANGL_VEL:
|
||||
if (!st->chip_config.gyro_fifo_enable ||
|
||||
!st->chip_config.enable) {
|
||||
result = inv_mpu6050_switch_engine(st, true,
|
||||
INV_MPU6050_BIT_PWR_GYRO_STBY);
|
||||
if (result)
|
||||
goto error_read_raw;
|
||||
}
|
||||
ret = inv_mpu6050_sensor_show(st, st->reg->raw_gyro,
|
||||
chan->channel2, val);
|
||||
if (!st->chip_config.gyro_fifo_enable ||
|
||||
!st->chip_config.enable) {
|
||||
result = inv_mpu6050_switch_engine(st, false,
|
||||
INV_MPU6050_BIT_PWR_GYRO_STBY);
|
||||
if (result)
|
||||
goto error_read_raw;
|
||||
}
|
||||
break;
|
||||
case IIO_ACCEL:
|
||||
if (!st->chip_config.accl_fifo_enable ||
|
||||
!st->chip_config.enable) {
|
||||
result = inv_mpu6050_switch_engine(st, true,
|
||||
INV_MPU6050_BIT_PWR_ACCL_STBY);
|
||||
if (result)
|
||||
goto error_read_raw;
|
||||
}
|
||||
ret = inv_mpu6050_sensor_show(st, st->reg->raw_accl,
|
||||
chan->channel2, val);
|
||||
if (!st->chip_config.accl_fifo_enable ||
|
||||
!st->chip_config.enable) {
|
||||
result = inv_mpu6050_switch_engine(st, false,
|
||||
INV_MPU6050_BIT_PWR_ACCL_STBY);
|
||||
if (result)
|
||||
goto error_read_raw;
|
||||
}
|
||||
break;
|
||||
case IIO_TEMP:
|
||||
/* wait for stablization */
|
||||
msleep(INV_MPU6050_SENSOR_UP_TIME);
|
||||
inv_mpu6050_sensor_show(st, st->reg->temperature,
|
||||
IIO_MOD_X, val);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
error_read_raw:
|
||||
if (!st->chip_config.enable)
|
||||
result |= inv_mpu6050_set_power_itg(st, false);
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
return ret;
|
||||
}
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
switch (chan->type) {
|
||||
case IIO_ANGL_VEL:
|
||||
*val = 0;
|
||||
*val2 = gyro_scale_6050[st->chip_config.fsr];
|
||||
|
||||
return IIO_VAL_INT_PLUS_NANO;
|
||||
case IIO_ACCEL:
|
||||
*val = 0;
|
||||
*val2 = accel_scale[st->chip_config.accl_fs];
|
||||
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
case IIO_TEMP:
|
||||
*val = 0;
|
||||
*val2 = INV_MPU6050_TEMP_SCALE;
|
||||
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
case IIO_CHAN_INFO_OFFSET:
|
||||
switch (chan->type) {
|
||||
case IIO_TEMP:
|
||||
*val = INV_MPU6050_TEMP_OFFSET;
|
||||
|
||||
return IIO_VAL_INT;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int inv_mpu6050_write_fsr(struct inv_mpu6050_state *st, int fsr)
|
||||
{
|
||||
int result;
|
||||
u8 d;
|
||||
|
||||
if (fsr < 0 || fsr > INV_MPU6050_MAX_GYRO_FS_PARAM)
|
||||
return -EINVAL;
|
||||
if (fsr == st->chip_config.fsr)
|
||||
return 0;
|
||||
|
||||
d = (fsr << INV_MPU6050_GYRO_CONFIG_FSR_SHIFT);
|
||||
result = inv_mpu6050_write_reg(st, st->reg->gyro_config, d);
|
||||
if (result)
|
||||
return result;
|
||||
st->chip_config.fsr = fsr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int inv_mpu6050_write_accel_fs(struct inv_mpu6050_state *st, int fs)
|
||||
{
|
||||
int result;
|
||||
u8 d;
|
||||
|
||||
if (fs < 0 || fs > INV_MPU6050_MAX_ACCL_FS_PARAM)
|
||||
return -EINVAL;
|
||||
if (fs == st->chip_config.accl_fs)
|
||||
return 0;
|
||||
|
||||
d = (fs << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT);
|
||||
result = inv_mpu6050_write_reg(st, st->reg->accl_config, d);
|
||||
if (result)
|
||||
return result;
|
||||
st->chip_config.accl_fs = fs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int val,
|
||||
int val2,
|
||||
long mask) {
|
||||
struct inv_mpu6050_state *st = iio_priv(indio_dev);
|
||||
int result;
|
||||
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
/* we should only update scale when the chip is disabled, i.e.,
|
||||
not running */
|
||||
if (st->chip_config.enable) {
|
||||
result = -EBUSY;
|
||||
goto error_write_raw;
|
||||
}
|
||||
result = inv_mpu6050_set_power_itg(st, true);
|
||||
if (result)
|
||||
goto error_write_raw;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
switch (chan->type) {
|
||||
case IIO_ANGL_VEL:
|
||||
result = inv_mpu6050_write_fsr(st, val);
|
||||
break;
|
||||
case IIO_ACCEL:
|
||||
result = inv_mpu6050_write_accel_fs(st, val);
|
||||
break;
|
||||
default:
|
||||
result = -EINVAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
result = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
error_write_raw:
|
||||
result |= inv_mpu6050_set_power_itg(st, false);
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* inv_mpu6050_set_lpf() - set low pass filer based on fifo rate.
|
||||
*
|
||||
* Based on the Nyquist principle, the sampling rate must
|
||||
* exceed twice of the bandwidth of the signal, or there
|
||||
* would be alising. This function basically search for the
|
||||
* correct low pass parameters based on the fifo rate, e.g,
|
||||
* sampling frequency.
|
||||
*/
|
||||
static int inv_mpu6050_set_lpf(struct inv_mpu6050_state *st, int rate)
|
||||
{
|
||||
const int hz[] = {188, 98, 42, 20, 10, 5};
|
||||
const int d[] = {INV_MPU6050_FILTER_188HZ, INV_MPU6050_FILTER_98HZ,
|
||||
INV_MPU6050_FILTER_42HZ, INV_MPU6050_FILTER_20HZ,
|
||||
INV_MPU6050_FILTER_10HZ, INV_MPU6050_FILTER_5HZ};
|
||||
int i, h, result;
|
||||
u8 data;
|
||||
|
||||
h = (rate >> 1);
|
||||
i = 0;
|
||||
while ((h < hz[i]) && (i < ARRAY_SIZE(d) - 1))
|
||||
i++;
|
||||
data = d[i];
|
||||
result = inv_mpu6050_write_reg(st, st->reg->lpf, data);
|
||||
if (result)
|
||||
return result;
|
||||
st->chip_config.lpf = data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* inv_mpu6050_fifo_rate_store() - Set fifo rate.
|
||||
*/
|
||||
static ssize_t inv_mpu6050_fifo_rate_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
s32 fifo_rate;
|
||||
u8 d;
|
||||
int result;
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct inv_mpu6050_state *st = iio_priv(indio_dev);
|
||||
|
||||
if (kstrtoint(buf, 10, &fifo_rate))
|
||||
return -EINVAL;
|
||||
if (fifo_rate < INV_MPU6050_MIN_FIFO_RATE ||
|
||||
fifo_rate > INV_MPU6050_MAX_FIFO_RATE)
|
||||
return -EINVAL;
|
||||
if (fifo_rate == st->chip_config.fifo_rate)
|
||||
return count;
|
||||
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
if (st->chip_config.enable) {
|
||||
result = -EBUSY;
|
||||
goto fifo_rate_fail;
|
||||
}
|
||||
result = inv_mpu6050_set_power_itg(st, true);
|
||||
if (result)
|
||||
goto fifo_rate_fail;
|
||||
|
||||
d = INV_MPU6050_ONE_K_HZ / fifo_rate - 1;
|
||||
result = inv_mpu6050_write_reg(st, st->reg->sample_rate_div, d);
|
||||
if (result)
|
||||
goto fifo_rate_fail;
|
||||
st->chip_config.fifo_rate = fifo_rate;
|
||||
|
||||
result = inv_mpu6050_set_lpf(st, fifo_rate);
|
||||
if (result)
|
||||
goto fifo_rate_fail;
|
||||
|
||||
fifo_rate_fail:
|
||||
result |= inv_mpu6050_set_power_itg(st, false);
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* inv_fifo_rate_show() - Get the current sampling rate.
|
||||
*/
|
||||
static ssize_t inv_fifo_rate_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct inv_mpu6050_state *st = iio_priv(dev_to_iio_dev(dev));
|
||||
|
||||
return sprintf(buf, "%d\n", st->chip_config.fifo_rate);
|
||||
}
|
||||
|
||||
/**
|
||||
* inv_attr_show() - calling this function will show current
|
||||
* parameters.
|
||||
*/
|
||||
static ssize_t inv_attr_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct inv_mpu6050_state *st = iio_priv(dev_to_iio_dev(dev));
|
||||
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
|
||||
s8 *m;
|
||||
|
||||
switch (this_attr->address) {
|
||||
/* In MPU6050, the two matrix are the same because gyro and accel
|
||||
are integrated in one chip */
|
||||
case ATTR_GYRO_MATRIX:
|
||||
case ATTR_ACCL_MATRIX:
|
||||
m = st->plat_data.orientation;
|
||||
|
||||
return sprintf(buf, "%d, %d, %d; %d, %d, %d; %d, %d, %d\n",
|
||||
m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* inv_mpu6050_validate_trigger() - validate_trigger callback for invensense
|
||||
* MPU6050 device.
|
||||
* @indio_dev: The IIO device
|
||||
* @trig: The new trigger
|
||||
*
|
||||
* Returns: 0 if the 'trig' matches the trigger registered by the MPU6050
|
||||
* device, -EINVAL otherwise.
|
||||
*/
|
||||
static int inv_mpu6050_validate_trigger(struct iio_dev *indio_dev,
|
||||
struct iio_trigger *trig)
|
||||
{
|
||||
struct inv_mpu6050_state *st = iio_priv(indio_dev);
|
||||
|
||||
if (st->trig != trig)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define INV_MPU6050_CHAN(_type, _channel2, _index) \
|
||||
{ \
|
||||
.type = _type, \
|
||||
.modified = 1, \
|
||||
.channel2 = _channel2, \
|
||||
.info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT \
|
||||
| IIO_CHAN_INFO_RAW_SEPARATE_BIT, \
|
||||
.scan_index = _index, \
|
||||
.scan_type = { \
|
||||
.sign = 's', \
|
||||
.realbits = 16, \
|
||||
.storagebits = 16, \
|
||||
.shift = 0 , \
|
||||
.endianness = IIO_BE, \
|
||||
}, \
|
||||
}
|
||||
|
||||
static const struct iio_chan_spec inv_mpu_channels[] = {
|
||||
IIO_CHAN_SOFT_TIMESTAMP(INV_MPU6050_SCAN_TIMESTAMP),
|
||||
/*
|
||||
* Note that temperature should only be via polled reading only,
|
||||
* not the final scan elements output.
|
||||
*/
|
||||
{
|
||||
.type = IIO_TEMP,
|
||||
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT
|
||||
| IIO_CHAN_INFO_OFFSET_SEPARATE_BIT
|
||||
| IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
|
||||
.scan_index = -1,
|
||||
},
|
||||
INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X),
|
||||
INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y),
|
||||
INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z),
|
||||
|
||||
INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_X, INV_MPU6050_SCAN_ACCL_X),
|
||||
INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Y, INV_MPU6050_SCAN_ACCL_Y),
|
||||
INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z),
|
||||
};
|
||||
|
||||
/* constant IIO attribute */
|
||||
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("10 20 50 100 200 500");
|
||||
static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR, inv_fifo_rate_show,
|
||||
inv_mpu6050_fifo_rate_store);
|
||||
static IIO_DEVICE_ATTR(in_gyro_matrix, S_IRUGO, inv_attr_show, NULL,
|
||||
ATTR_GYRO_MATRIX);
|
||||
static IIO_DEVICE_ATTR(in_accel_matrix, S_IRUGO, inv_attr_show, NULL,
|
||||
ATTR_ACCL_MATRIX);
|
||||
|
||||
static struct attribute *inv_attributes[] = {
|
||||
&iio_dev_attr_in_gyro_matrix.dev_attr.attr,
|
||||
&iio_dev_attr_in_accel_matrix.dev_attr.attr,
|
||||
&iio_dev_attr_sampling_frequency.dev_attr.attr,
|
||||
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group inv_attribute_group = {
|
||||
.attrs = inv_attributes
|
||||
};
|
||||
|
||||
static const struct iio_info mpu_info = {
|
||||
.driver_module = THIS_MODULE,
|
||||
.read_raw = &inv_mpu6050_read_raw,
|
||||
.write_raw = &inv_mpu6050_write_raw,
|
||||
.attrs = &inv_attribute_group,
|
||||
.validate_trigger = inv_mpu6050_validate_trigger,
|
||||
};
|
||||
|
||||
/**
|
||||
* inv_check_and_setup_chip() - check and setup chip.
|
||||
*/
|
||||
static int inv_check_and_setup_chip(struct inv_mpu6050_state *st,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
int result;
|
||||
|
||||
st->chip_type = INV_MPU6050;
|
||||
st->hw = &hw_info[st->chip_type];
|
||||
st->reg = hw_info[st->chip_type].reg;
|
||||
|
||||
/* reset to make sure previous state are not there */
|
||||
result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1,
|
||||
INV_MPU6050_BIT_H_RESET);
|
||||
if (result)
|
||||
return result;
|
||||
msleep(INV_MPU6050_POWER_UP_TIME);
|
||||
/* toggle power state. After reset, the sleep bit could be on
|
||||
or off depending on the OTP settings. Toggling power would
|
||||
make it in a definite state as well as making the hardware
|
||||
state align with the software state */
|
||||
result = inv_mpu6050_set_power_itg(st, false);
|
||||
if (result)
|
||||
return result;
|
||||
result = inv_mpu6050_set_power_itg(st, true);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = inv_mpu6050_switch_engine(st, false,
|
||||
INV_MPU6050_BIT_PWR_ACCL_STBY);
|
||||
if (result)
|
||||
return result;
|
||||
result = inv_mpu6050_switch_engine(st, false,
|
||||
INV_MPU6050_BIT_PWR_GYRO_STBY);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* inv_mpu_probe() - probe function.
|
||||
* @client: i2c client.
|
||||
* @id: i2c device id.
|
||||
*
|
||||
* Returns 0 on success, a negative error code otherwise.
|
||||
*/
|
||||
static int inv_mpu_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct inv_mpu6050_state *st;
|
||||
struct iio_dev *indio_dev;
|
||||
int result;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_READ_I2C_BLOCK |
|
||||
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) {
|
||||
result = -ENOSYS;
|
||||
goto out_no_free;
|
||||
}
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
if (indio_dev == NULL) {
|
||||
result = -ENOMEM;
|
||||
goto out_no_free;
|
||||
}
|
||||
st = iio_priv(indio_dev);
|
||||
st->client = client;
|
||||
st->plat_data = *(struct inv_mpu6050_platform_data
|
||||
*)dev_get_platdata(&client->dev);
|
||||
/* power is turned on inside check chip type*/
|
||||
result = inv_check_and_setup_chip(st, id);
|
||||
if (result)
|
||||
goto out_free;
|
||||
|
||||
result = inv_mpu6050_init_config(indio_dev);
|
||||
if (result) {
|
||||
dev_err(&client->dev,
|
||||
"Could not initialize device.\n");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
indio_dev->dev.parent = &client->dev;
|
||||
indio_dev->name = id->name;
|
||||
indio_dev->channels = inv_mpu_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
|
||||
|
||||
indio_dev->info = &mpu_info;
|
||||
indio_dev->modes = INDIO_BUFFER_TRIGGERED;
|
||||
|
||||
result = iio_triggered_buffer_setup(indio_dev,
|
||||
inv_mpu6050_irq_handler,
|
||||
inv_mpu6050_read_fifo,
|
||||
NULL);
|
||||
if (result) {
|
||||
dev_err(&st->client->dev, "configure buffer fail %d\n",
|
||||
result);
|
||||
goto out_free;
|
||||
}
|
||||
result = inv_mpu6050_probe_trigger(indio_dev);
|
||||
if (result) {
|
||||
dev_err(&st->client->dev, "trigger probe fail %d\n", result);
|
||||
goto out_unreg_ring;
|
||||
}
|
||||
|
||||
INIT_KFIFO(st->timestamps);
|
||||
spin_lock_init(&st->time_stamp_lock);
|
||||
result = iio_device_register(indio_dev);
|
||||
if (result) {
|
||||
dev_err(&st->client->dev, "IIO register fail %d\n", result);
|
||||
goto out_remove_trigger;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_remove_trigger:
|
||||
inv_mpu6050_remove_trigger(st);
|
||||
out_unreg_ring:
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
out_free:
|
||||
iio_device_free(indio_dev);
|
||||
out_no_free:
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int inv_mpu_remove(struct i2c_client *client)
|
||||
{
|
||||
struct iio_dev *indio_dev = i2c_get_clientdata(client);
|
||||
struct inv_mpu6050_state *st = iio_priv(indio_dev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
inv_mpu6050_remove_trigger(st);
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
||||
static int inv_mpu_resume(struct device *dev)
|
||||
{
|
||||
return inv_mpu6050_set_power_itg(
|
||||
iio_priv(i2c_get_clientdata(to_i2c_client(dev))), true);
|
||||
}
|
||||
|
||||
static int inv_mpu_suspend(struct device *dev)
|
||||
{
|
||||
return inv_mpu6050_set_power_itg(
|
||||
iio_priv(i2c_get_clientdata(to_i2c_client(dev))), false);
|
||||
}
|
||||
static SIMPLE_DEV_PM_OPS(inv_mpu_pmops, inv_mpu_suspend, inv_mpu_resume);
|
||||
|
||||
#define INV_MPU6050_PMOPS (&inv_mpu_pmops)
|
||||
#else
|
||||
#define INV_MPU6050_PMOPS NULL
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
/*
|
||||
* device id table is used to identify what device can be
|
||||
* supported by this driver
|
||||
*/
|
||||
static const struct i2c_device_id inv_mpu_id[] = {
|
||||
{"mpu6050", INV_MPU6050},
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, inv_mpu_id);
|
||||
|
||||
static struct i2c_driver inv_mpu_driver = {
|
||||
.probe = inv_mpu_probe,
|
||||
.remove = inv_mpu_remove,
|
||||
.id_table = inv_mpu_id,
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "inv-mpu6050",
|
||||
.pm = INV_MPU6050_PMOPS,
|
||||
},
|
||||
};
|
||||
|
||||
module_i2c_driver(inv_mpu_driver);
|
||||
|
||||
MODULE_AUTHOR("Invensense Corporation");
|
||||
MODULE_DESCRIPTION("Invensense device MPU6050 driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Invensense, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/kfifo_buf.h>
|
||||
#include <linux/iio/trigger.h>
|
||||
#include <linux/iio/triggered_buffer.h>
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/platform_data/invensense_mpu6050.h>
|
||||
|
||||
/**
|
||||
* struct inv_mpu6050_reg_map - Notable registers.
|
||||
* @sample_rate_div: Divider applied to gyro output rate.
|
||||
* @lpf: Configures internal low pass filter.
|
||||
* @user_ctrl: Enables/resets the FIFO.
|
||||
* @fifo_en: Determines which data will appear in FIFO.
|
||||
* @gyro_config: gyro config register.
|
||||
* @accl_config: accel config register
|
||||
* @fifo_count_h: Upper byte of FIFO count.
|
||||
* @fifo_r_w: FIFO register.
|
||||
* @raw_gyro: Address of first gyro register.
|
||||
* @raw_accl: Address of first accel register.
|
||||
* @temperature: temperature register
|
||||
* @int_enable: Interrupt enable register.
|
||||
* @pwr_mgmt_1: Controls chip's power state and clock source.
|
||||
* @pwr_mgmt_2: Controls power state of individual sensors.
|
||||
*/
|
||||
struct inv_mpu6050_reg_map {
|
||||
u8 sample_rate_div;
|
||||
u8 lpf;
|
||||
u8 user_ctrl;
|
||||
u8 fifo_en;
|
||||
u8 gyro_config;
|
||||
u8 accl_config;
|
||||
u8 fifo_count_h;
|
||||
u8 fifo_r_w;
|
||||
u8 raw_gyro;
|
||||
u8 raw_accl;
|
||||
u8 temperature;
|
||||
u8 int_enable;
|
||||
u8 pwr_mgmt_1;
|
||||
u8 pwr_mgmt_2;
|
||||
};
|
||||
|
||||
/*device enum */
|
||||
enum inv_devices {
|
||||
INV_MPU6050,
|
||||
INV_NUM_PARTS
|
||||
};
|
||||
|
||||
/**
|
||||
* struct inv_mpu6050_chip_config - Cached chip configuration data.
|
||||
* @fsr: Full scale range.
|
||||
* @lpf: Digital low pass filter frequency.
|
||||
* @accl_fs: accel full scale range.
|
||||
* @enable: master enable state.
|
||||
* @accl_fifo_enable: enable accel data output
|
||||
* @gyro_fifo_enable: enable gyro data output
|
||||
* @fifo_rate: FIFO update rate.
|
||||
*/
|
||||
struct inv_mpu6050_chip_config {
|
||||
unsigned int fsr:2;
|
||||
unsigned int lpf:3;
|
||||
unsigned int accl_fs:2;
|
||||
unsigned int enable:1;
|
||||
unsigned int accl_fifo_enable:1;
|
||||
unsigned int gyro_fifo_enable:1;
|
||||
u16 fifo_rate;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct inv_mpu6050_hw - Other important hardware information.
|
||||
* @num_reg: Number of registers on device.
|
||||
* @name: name of the chip.
|
||||
* @reg: register map of the chip.
|
||||
* @config: configuration of the chip.
|
||||
*/
|
||||
struct inv_mpu6050_hw {
|
||||
u8 num_reg;
|
||||
u8 *name;
|
||||
const struct inv_mpu6050_reg_map *reg;
|
||||
const struct inv_mpu6050_chip_config *config;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct inv_mpu6050_state - Driver state variables.
|
||||
* @TIMESTAMP_FIFO_SIZE: fifo size for timestamp.
|
||||
* @trig: IIO trigger.
|
||||
* @chip_config: Cached attribute information.
|
||||
* @reg: Map of important registers.
|
||||
* @hw: Other hardware-specific information.
|
||||
* @chip_type: chip type.
|
||||
* @time_stamp_lock: spin lock to time stamp.
|
||||
* @client: i2c client handle.
|
||||
* @plat_data: platform data.
|
||||
* @timestamps: kfifo queue to store time stamp.
|
||||
*/
|
||||
struct inv_mpu6050_state {
|
||||
#define TIMESTAMP_FIFO_SIZE 16
|
||||
struct iio_trigger *trig;
|
||||
struct inv_mpu6050_chip_config chip_config;
|
||||
const struct inv_mpu6050_reg_map *reg;
|
||||
const struct inv_mpu6050_hw *hw;
|
||||
enum inv_devices chip_type;
|
||||
spinlock_t time_stamp_lock;
|
||||
struct i2c_client *client;
|
||||
struct inv_mpu6050_platform_data plat_data;
|
||||
DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
|
||||
};
|
||||
|
||||
/*register and associated bit definition*/
|
||||
#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_FIFO_EN 0x23
|
||||
#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_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_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_REG_PWR_MGMT_2 0x6C
|
||||
#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
|
||||
|
||||
#define INV_MPU6050_BYTES_PER_3AXIS_SENSOR 6
|
||||
#define INV_MPU6050_FIFO_COUNT_BYTE 2
|
||||
#define INV_MPU6050_FIFO_THRESHOLD 500
|
||||
#define INV_MPU6050_POWER_UP_TIME 100
|
||||
#define INV_MPU6050_TEMP_UP_TIME 100
|
||||
#define INV_MPU6050_SENSOR_UP_TIME 30
|
||||
#define INV_MPU6050_REG_UP_TIME 5
|
||||
|
||||
#define INV_MPU6050_TEMP_OFFSET 12421
|
||||
#define INV_MPU6050_TEMP_SCALE 2941
|
||||
#define INV_MPU6050_MAX_GYRO_FS_PARAM 3
|
||||
#define INV_MPU6050_MAX_ACCL_FS_PARAM 3
|
||||
#define INV_MPU6050_THREE_AXIS 3
|
||||
#define INV_MPU6050_GYRO_CONFIG_FSR_SHIFT 3
|
||||
#define INV_MPU6050_ACCL_CONFIG_FSR_SHIFT 3
|
||||
|
||||
/* 6 + 6 round up and plus 8 */
|
||||
#define INV_MPU6050_OUTPUT_DATA_SIZE 24
|
||||
|
||||
/* 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
|
||||
|
||||
/* scan element definition */
|
||||
enum inv_mpu6050_scan {
|
||||
INV_MPU6050_SCAN_ACCL_X,
|
||||
INV_MPU6050_SCAN_ACCL_Y,
|
||||
INV_MPU6050_SCAN_ACCL_Z,
|
||||
INV_MPU6050_SCAN_GYRO_X,
|
||||
INV_MPU6050_SCAN_GYRO_Y,
|
||||
INV_MPU6050_SCAN_GYRO_Z,
|
||||
INV_MPU6050_SCAN_TIMESTAMP,
|
||||
};
|
||||
|
||||
enum inv_mpu6050_filter_e {
|
||||
INV_MPU6050_FILTER_256HZ_NOLPF2 = 0,
|
||||
INV_MPU6050_FILTER_188HZ,
|
||||
INV_MPU6050_FILTER_98HZ,
|
||||
INV_MPU6050_FILTER_42HZ,
|
||||
INV_MPU6050_FILTER_20HZ,
|
||||
INV_MPU6050_FILTER_10HZ,
|
||||
INV_MPU6050_FILTER_5HZ,
|
||||
INV_MPU6050_FILTER_2100HZ_NOLPF,
|
||||
NUM_MPU6050_FILTER
|
||||
};
|
||||
|
||||
/* IIO attribute address */
|
||||
enum INV_MPU6050_IIO_ATTR_ADDR {
|
||||
ATTR_GYRO_MATRIX,
|
||||
ATTR_ACCL_MATRIX,
|
||||
};
|
||||
|
||||
enum inv_mpu6050_accl_fs_e {
|
||||
INV_MPU6050_FS_02G = 0,
|
||||
INV_MPU6050_FS_04G,
|
||||
INV_MPU6050_FS_08G,
|
||||
INV_MPU6050_FS_16G,
|
||||
NUM_ACCL_FSR
|
||||
};
|
||||
|
||||
enum inv_mpu6050_fsr_e {
|
||||
INV_MPU6050_FSR_250DPS = 0,
|
||||
INV_MPU6050_FSR_500DPS,
|
||||
INV_MPU6050_FSR_1000DPS,
|
||||
INV_MPU6050_FSR_2000DPS,
|
||||
NUM_MPU6050_FSR
|
||||
};
|
||||
|
||||
enum inv_mpu6050_clock_sel_e {
|
||||
INV_CLK_INTERNAL = 0,
|
||||
INV_CLK_PLL,
|
||||
NUM_CLK
|
||||
};
|
||||
|
||||
irqreturn_t inv_mpu6050_irq_handler(int irq, void *p);
|
||||
irqreturn_t inv_mpu6050_read_fifo(int irq, void *p);
|
||||
int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev);
|
||||
void inv_mpu6050_remove_trigger(struct inv_mpu6050_state *st);
|
||||
int inv_reset_fifo(struct iio_dev *indio_dev);
|
||||
int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask);
|
||||
int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 val);
|
||||
int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on);
|
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Invensense, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/poll.h>
|
||||
#include "inv_mpu_iio.h"
|
||||
|
||||
int inv_reset_fifo(struct iio_dev *indio_dev)
|
||||
{
|
||||
int result;
|
||||
u8 d;
|
||||
struct inv_mpu6050_state *st = iio_priv(indio_dev);
|
||||
|
||||
/* disable interrupt */
|
||||
result = inv_mpu6050_write_reg(st, st->reg->int_enable, 0);
|
||||
if (result) {
|
||||
dev_err(&st->client->dev, "int_enable failed %d\n", result);
|
||||
return result;
|
||||
}
|
||||
/* disable the sensor output to FIFO */
|
||||
result = inv_mpu6050_write_reg(st, st->reg->fifo_en, 0);
|
||||
if (result)
|
||||
goto reset_fifo_fail;
|
||||
/* disable fifo reading */
|
||||
result = inv_mpu6050_write_reg(st, st->reg->user_ctrl, 0);
|
||||
if (result)
|
||||
goto reset_fifo_fail;
|
||||
|
||||
/* reset FIFO*/
|
||||
result = inv_mpu6050_write_reg(st, st->reg->user_ctrl,
|
||||
INV_MPU6050_BIT_FIFO_RST);
|
||||
if (result)
|
||||
goto reset_fifo_fail;
|
||||
/* enable interrupt */
|
||||
if (st->chip_config.accl_fifo_enable ||
|
||||
st->chip_config.gyro_fifo_enable) {
|
||||
result = inv_mpu6050_write_reg(st, st->reg->int_enable,
|
||||
INV_MPU6050_BIT_DATA_RDY_EN);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
/* enable FIFO reading and I2C master interface*/
|
||||
result = inv_mpu6050_write_reg(st, st->reg->user_ctrl,
|
||||
INV_MPU6050_BIT_FIFO_EN);
|
||||
if (result)
|
||||
goto reset_fifo_fail;
|
||||
/* enable sensor output to FIFO */
|
||||
d = 0;
|
||||
if (st->chip_config.gyro_fifo_enable)
|
||||
d |= INV_MPU6050_BITS_GYRO_OUT;
|
||||
if (st->chip_config.accl_fifo_enable)
|
||||
d |= INV_MPU6050_BIT_ACCEL_OUT;
|
||||
result = inv_mpu6050_write_reg(st, st->reg->fifo_en, d);
|
||||
if (result)
|
||||
goto reset_fifo_fail;
|
||||
|
||||
return 0;
|
||||
|
||||
reset_fifo_fail:
|
||||
dev_err(&st->client->dev, "reset fifo failed %d\n", result);
|
||||
result = inv_mpu6050_write_reg(st, st->reg->int_enable,
|
||||
INV_MPU6050_BIT_DATA_RDY_EN);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void inv_clear_kfifo(struct inv_mpu6050_state *st)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
/* take the spin lock sem to avoid interrupt kick in */
|
||||
spin_lock_irqsave(&st->time_stamp_lock, flags);
|
||||
kfifo_reset(&st->timestamps);
|
||||
spin_unlock_irqrestore(&st->time_stamp_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* inv_mpu6050_irq_handler() - Cache a timestamp at each data ready interrupt.
|
||||
*/
|
||||
irqreturn_t inv_mpu6050_irq_handler(int irq, void *p)
|
||||
{
|
||||
struct iio_poll_func *pf = p;
|
||||
struct iio_dev *indio_dev = pf->indio_dev;
|
||||
struct inv_mpu6050_state *st = iio_priv(indio_dev);
|
||||
s64 timestamp;
|
||||
|
||||
timestamp = iio_get_time_ns();
|
||||
spin_lock(&st->time_stamp_lock);
|
||||
kfifo_in(&st->timestamps, ×tamp, 1);
|
||||
spin_unlock(&st->time_stamp_lock);
|
||||
|
||||
return IRQ_WAKE_THREAD;
|
||||
}
|
||||
|
||||
/**
|
||||
* inv_mpu6050_read_fifo() - Transfer data from hardware FIFO to KFIFO.
|
||||
*/
|
||||
irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
|
||||
{
|
||||
struct iio_poll_func *pf = p;
|
||||
struct iio_dev *indio_dev = pf->indio_dev;
|
||||
struct inv_mpu6050_state *st = iio_priv(indio_dev);
|
||||
size_t bytes_per_datum;
|
||||
int result;
|
||||
u8 data[INV_MPU6050_OUTPUT_DATA_SIZE];
|
||||
u16 fifo_count;
|
||||
s64 timestamp;
|
||||
u64 *tmp;
|
||||
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
if (!(st->chip_config.accl_fifo_enable |
|
||||
st->chip_config.gyro_fifo_enable))
|
||||
goto end_session;
|
||||
bytes_per_datum = 0;
|
||||
if (st->chip_config.accl_fifo_enable)
|
||||
bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR;
|
||||
|
||||
if (st->chip_config.gyro_fifo_enable)
|
||||
bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR;
|
||||
|
||||
/*
|
||||
* read fifo_count register to know how many bytes inside FIFO
|
||||
* right now
|
||||
*/
|
||||
result = i2c_smbus_read_i2c_block_data(st->client,
|
||||
st->reg->fifo_count_h,
|
||||
INV_MPU6050_FIFO_COUNT_BYTE, data);
|
||||
if (result != INV_MPU6050_FIFO_COUNT_BYTE)
|
||||
goto end_session;
|
||||
fifo_count = be16_to_cpup((__be16 *)(&data[0]));
|
||||
if (fifo_count < bytes_per_datum)
|
||||
goto end_session;
|
||||
/* fifo count can't be odd number, if it is odd, reset fifo*/
|
||||
if (fifo_count & 1)
|
||||
goto flush_fifo;
|
||||
if (fifo_count > INV_MPU6050_FIFO_THRESHOLD)
|
||||
goto flush_fifo;
|
||||
/* Timestamp mismatch. */
|
||||
if (kfifo_len(&st->timestamps) >
|
||||
fifo_count / bytes_per_datum + INV_MPU6050_TIME_STAMP_TOR)
|
||||
goto flush_fifo;
|
||||
while (fifo_count >= bytes_per_datum) {
|
||||
result = i2c_smbus_read_i2c_block_data(st->client,
|
||||
st->reg->fifo_r_w,
|
||||
bytes_per_datum, data);
|
||||
if (result != bytes_per_datum)
|
||||
goto flush_fifo;
|
||||
|
||||
result = kfifo_out(&st->timestamps, ×tamp, 1);
|
||||
/* when there is no timestamp, put timestamp as 0 */
|
||||
if (0 == result)
|
||||
timestamp = 0;
|
||||
|
||||
tmp = (u64 *)data;
|
||||
tmp[DIV_ROUND_UP(bytes_per_datum, 8)] = timestamp;
|
||||
result = iio_push_to_buffers(indio_dev, data);
|
||||
if (result)
|
||||
goto flush_fifo;
|
||||
fifo_count -= bytes_per_datum;
|
||||
}
|
||||
|
||||
end_session:
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
||||
flush_fifo:
|
||||
/* Flush HW and SW FIFOs. */
|
||||
inv_reset_fifo(indio_dev);
|
||||
inv_clear_kfifo(st);
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Invensense, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "inv_mpu_iio.h"
|
||||
|
||||
static void inv_scan_query(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct inv_mpu6050_state *st = iio_priv(indio_dev);
|
||||
|
||||
st->chip_config.gyro_fifo_enable =
|
||||
test_bit(INV_MPU6050_SCAN_GYRO_X,
|
||||
indio_dev->active_scan_mask) ||
|
||||
test_bit(INV_MPU6050_SCAN_GYRO_Y,
|
||||
indio_dev->active_scan_mask) ||
|
||||
test_bit(INV_MPU6050_SCAN_GYRO_Z,
|
||||
indio_dev->active_scan_mask);
|
||||
|
||||
st->chip_config.accl_fifo_enable =
|
||||
test_bit(INV_MPU6050_SCAN_ACCL_X,
|
||||
indio_dev->active_scan_mask) ||
|
||||
test_bit(INV_MPU6050_SCAN_ACCL_Y,
|
||||
indio_dev->active_scan_mask) ||
|
||||
test_bit(INV_MPU6050_SCAN_ACCL_Z,
|
||||
indio_dev->active_scan_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* inv_mpu6050_set_enable() - enable chip functions.
|
||||
* @indio_dev: Device driver instance.
|
||||
* @enable: enable/disable
|
||||
*/
|
||||
static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
|
||||
{
|
||||
struct inv_mpu6050_state *st = iio_priv(indio_dev);
|
||||
int result;
|
||||
|
||||
if (enable) {
|
||||
result = inv_mpu6050_set_power_itg(st, true);
|
||||
if (result)
|
||||
return result;
|
||||
inv_scan_query(indio_dev);
|
||||
if (st->chip_config.gyro_fifo_enable) {
|
||||
result = inv_mpu6050_switch_engine(st, true,
|
||||
INV_MPU6050_BIT_PWR_GYRO_STBY);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
if (st->chip_config.accl_fifo_enable) {
|
||||
result = inv_mpu6050_switch_engine(st, true,
|
||||
INV_MPU6050_BIT_PWR_ACCL_STBY);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
result = inv_reset_fifo(indio_dev);
|
||||
if (result)
|
||||
return result;
|
||||
} else {
|
||||
result = inv_mpu6050_write_reg(st, st->reg->fifo_en, 0);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = inv_mpu6050_write_reg(st, st->reg->int_enable, 0);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = inv_mpu6050_write_reg(st, st->reg->user_ctrl, 0);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = inv_mpu6050_switch_engine(st, false,
|
||||
INV_MPU6050_BIT_PWR_GYRO_STBY);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = inv_mpu6050_switch_engine(st, false,
|
||||
INV_MPU6050_BIT_PWR_ACCL_STBY);
|
||||
if (result)
|
||||
return result;
|
||||
result = inv_mpu6050_set_power_itg(st, false);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
st->chip_config.enable = enable;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* inv_mpu_data_rdy_trigger_set_state() - set data ready interrupt state
|
||||
* @trig: Trigger instance
|
||||
* @state: Desired trigger state
|
||||
*/
|
||||
static int inv_mpu_data_rdy_trigger_set_state(struct iio_trigger *trig,
|
||||
bool state)
|
||||
{
|
||||
return inv_mpu6050_set_enable(trig->private_data, state);
|
||||
}
|
||||
|
||||
static const struct iio_trigger_ops inv_mpu_trigger_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.set_trigger_state = &inv_mpu_data_rdy_trigger_set_state,
|
||||
};
|
||||
|
||||
int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev)
|
||||
{
|
||||
int ret;
|
||||
struct inv_mpu6050_state *st = iio_priv(indio_dev);
|
||||
|
||||
st->trig = iio_trigger_alloc("%s-dev%d",
|
||||
indio_dev->name,
|
||||
indio_dev->id);
|
||||
if (st->trig == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
ret = request_irq(st->client->irq, &iio_trigger_generic_data_rdy_poll,
|
||||
IRQF_TRIGGER_RISING,
|
||||
"inv_mpu",
|
||||
st->trig);
|
||||
if (ret)
|
||||
goto error_free_trig;
|
||||
st->trig->dev.parent = &st->client->dev;
|
||||
st->trig->private_data = indio_dev;
|
||||
st->trig->ops = &inv_mpu_trigger_ops;
|
||||
ret = iio_trigger_register(st->trig);
|
||||
if (ret)
|
||||
goto error_free_irq;
|
||||
indio_dev->trig = st->trig;
|
||||
|
||||
return 0;
|
||||
|
||||
error_free_irq:
|
||||
free_irq(st->client->irq, st->trig);
|
||||
error_free_trig:
|
||||
iio_trigger_free(st->trig);
|
||||
error_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void inv_mpu6050_remove_trigger(struct inv_mpu6050_state *st)
|
||||
{
|
||||
iio_trigger_unregister(st->trig);
|
||||
free_irq(st->client->irq, st->trig);
|
||||
iio_trigger_free(st->trig);
|
||||
}
|
|
@ -160,7 +160,7 @@ void iio_trigger_notify_done(struct iio_trigger *trig)
|
|||
trig->use_count--;
|
||||
if (trig->use_count == 0 && trig->ops && trig->ops->try_reenable)
|
||||
if (trig->ops->try_reenable(trig))
|
||||
/* Missed and interrupt so launch new poll now */
|
||||
/* Missed an interrupt so launch new poll now */
|
||||
iio_trigger_poll(trig, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(iio_trigger_notify_done);
|
||||
|
@ -193,7 +193,7 @@ static void iio_trigger_put_irq(struct iio_trigger *trig, int irq)
|
|||
* This is not currently handled. Alternative of not enabling trigger unless
|
||||
* the relevant function is in there may be the best option.
|
||||
*/
|
||||
/* Worth protecting against double additions?*/
|
||||
/* Worth protecting against double additions? */
|
||||
static int iio_trigger_attach_poll_func(struct iio_trigger *trig,
|
||||
struct iio_poll_func *pf)
|
||||
{
|
||||
|
@ -201,7 +201,7 @@ static int iio_trigger_attach_poll_func(struct iio_trigger *trig,
|
|||
bool notinuse
|
||||
= bitmap_empty(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER);
|
||||
|
||||
/* Prevent the module being removed whilst attached to a trigger */
|
||||
/* Prevent the module from being removed whilst attached to a trigger */
|
||||
__module_get(pf->indio_dev->info->driver_module);
|
||||
pf->irq = iio_trigger_get_irq(trig);
|
||||
ret = request_threaded_irq(pf->irq, pf->h, pf->thread,
|
||||
|
@ -288,7 +288,7 @@ void iio_dealloc_pollfunc(struct iio_poll_func *pf)
|
|||
EXPORT_SYMBOL_GPL(iio_dealloc_pollfunc);
|
||||
|
||||
/**
|
||||
* iio_trigger_read_current() - trigger consumer sysfs query which trigger
|
||||
* iio_trigger_read_current() - trigger consumer sysfs query current trigger
|
||||
*
|
||||
* For trigger consumers the current_trigger interface allows the trigger
|
||||
* used by the device to be queried.
|
||||
|
@ -305,7 +305,7 @@ static ssize_t iio_trigger_read_current(struct device *dev,
|
|||
}
|
||||
|
||||
/**
|
||||
* iio_trigger_write_current() trigger consumer sysfs set current trigger
|
||||
* iio_trigger_write_current() - trigger consumer sysfs set current trigger
|
||||
*
|
||||
* For trigger consumers the current_trigger interface allows the trigger
|
||||
* used for this device to be specified at run time based on the triggers
|
||||
|
@ -476,7 +476,7 @@ void iio_device_register_trigger_consumer(struct iio_dev *indio_dev)
|
|||
|
||||
void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev)
|
||||
{
|
||||
/* Clean up and associated but not attached triggers references */
|
||||
/* Clean up an associated but not attached trigger reference */
|
||||
if (indio_dev->trig)
|
||||
iio_trigger_put(indio_dev->trig);
|
||||
}
|
||||
|
|
|
@ -93,7 +93,8 @@ static const struct iio_chan_spec
|
|||
}
|
||||
|
||||
|
||||
struct iio_channel *iio_channel_get(const char *name, const char *channel_name)
|
||||
static struct iio_channel *iio_channel_get_sys(const char *name,
|
||||
const char *channel_name)
|
||||
{
|
||||
struct iio_map_internal *c_i = NULL, *c = NULL;
|
||||
struct iio_channel *channel;
|
||||
|
@ -144,6 +145,14 @@ error_no_mem:
|
|||
iio_device_put(c->indio_dev);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
struct iio_channel *iio_channel_get(struct device *dev,
|
||||
const char *channel_name)
|
||||
{
|
||||
const char *name = dev ? dev_name(dev) : NULL;
|
||||
|
||||
return iio_channel_get_sys(name, channel_name);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iio_channel_get);
|
||||
|
||||
void iio_channel_release(struct iio_channel *channel)
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#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/common/st_sensors.h>
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/trigger.h>
|
||||
|
||||
#include <linux/iio/common/st_sensors.h>
|
||||
#include <linux/iio/common/st_sensors_i2c.h>
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/trigger.h>
|
||||
|
||||
#include <linux/iio/common/st_sensors.h>
|
||||
#include <linux/iio/common/st_sensors_spi.h>
|
||||
|
|
|
@ -287,8 +287,8 @@ static int gab_probe(struct platform_device *pdev)
|
|||
* based on the channel supported by consumer device.
|
||||
*/
|
||||
for (chan = 0; chan < ARRAY_SIZE(gab_chan_name); chan++) {
|
||||
adc_bat->channel[chan] = iio_channel_get(dev_name(&pdev->dev),
|
||||
gab_chan_name[chan]);
|
||||
adc_bat->channel[chan] = iio_channel_get(&pdev->dev,
|
||||
gab_chan_name[chan]);
|
||||
if (IS_ERR(adc_bat->channel[chan])) {
|
||||
ret = PTR_ERR(adc_bat->channel[chan]);
|
||||
} else {
|
||||
|
|
|
@ -580,7 +580,7 @@ static void lp8788_irq_unregister(struct platform_device *pdev,
|
|||
}
|
||||
}
|
||||
|
||||
static void lp8788_setup_adc_channel(const char *consumer_name,
|
||||
static void lp8788_setup_adc_channel(struct device *dev,
|
||||
struct lp8788_charger *pchg)
|
||||
{
|
||||
struct lp8788_charger_platform_data *pdata = pchg->pdata;
|
||||
|
@ -590,11 +590,11 @@ static void lp8788_setup_adc_channel(const char *consumer_name,
|
|||
return;
|
||||
|
||||
/* ADC channel for battery voltage */
|
||||
chan = iio_channel_get(consumer_name, pdata->adc_vbatt);
|
||||
chan = iio_channel_get(dev, pdata->adc_vbatt);
|
||||
pchg->chan[LP8788_VBATT] = IS_ERR(chan) ? NULL : chan;
|
||||
|
||||
/* ADC channel for battery temperature */
|
||||
chan = iio_channel_get(consumer_name, pdata->adc_batt_temp);
|
||||
chan = iio_channel_get(dev, pdata->adc_batt_temp);
|
||||
pchg->chan[LP8788_BATT_TEMP] = IS_ERR(chan) ? NULL : chan;
|
||||
}
|
||||
|
||||
|
@ -704,7 +704,7 @@ static int lp8788_charger_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
lp8788_setup_adc_channel(pdev->name, pchg);
|
||||
lp8788_setup_adc_channel(&pdev->dev, pchg);
|
||||
|
||||
ret = lp8788_psy_register(pdev, pchg);
|
||||
if (ret)
|
||||
|
|
|
@ -53,7 +53,6 @@ int lis3l02dq_spi_read_reg_8(struct iio_dev *indio_dev,
|
|||
u8 reg_address, u8 *val)
|
||||
{
|
||||
struct lis3l02dq_state *st = iio_priv(indio_dev);
|
||||
struct spi_message msg;
|
||||
int ret;
|
||||
struct spi_transfer xfer = {
|
||||
.tx_buf = st->tx,
|
||||
|
@ -66,9 +65,7 @@ int lis3l02dq_spi_read_reg_8(struct iio_dev *indio_dev,
|
|||
st->tx[0] = LIS3L02DQ_READ_REG(reg_address);
|
||||
st->tx[1] = 0;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfer, &msg);
|
||||
ret = spi_sync(st->us, &msg);
|
||||
ret = spi_sync_transfer(st->us, &xfer, 1);
|
||||
*val = st->rx[1];
|
||||
mutex_unlock(&st->buf_lock);
|
||||
|
||||
|
@ -109,7 +106,6 @@ static int lis3l02dq_spi_write_reg_s16(struct iio_dev *indio_dev,
|
|||
s16 value)
|
||||
{
|
||||
int ret;
|
||||
struct spi_message msg;
|
||||
struct lis3l02dq_state *st = iio_priv(indio_dev);
|
||||
struct spi_transfer xfers[] = { {
|
||||
.tx_buf = st->tx,
|
||||
|
@ -129,10 +125,7 @@ static int lis3l02dq_spi_write_reg_s16(struct iio_dev *indio_dev,
|
|||
st->tx[2] = LIS3L02DQ_WRITE_REG(lower_reg_address + 1);
|
||||
st->tx[3] = (value >> 8) & 0xFF;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfers[0], &msg);
|
||||
spi_message_add_tail(&xfers[1], &msg);
|
||||
ret = spi_sync(st->us, &msg);
|
||||
ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
|
||||
mutex_unlock(&st->buf_lock);
|
||||
|
||||
return ret;
|
||||
|
@ -143,8 +136,6 @@ static int lis3l02dq_read_reg_s16(struct iio_dev *indio_dev,
|
|||
int *val)
|
||||
{
|
||||
struct lis3l02dq_state *st = iio_priv(indio_dev);
|
||||
|
||||
struct spi_message msg;
|
||||
int ret;
|
||||
s16 tempval;
|
||||
struct spi_transfer xfers[] = { {
|
||||
|
@ -167,10 +158,7 @@ static int lis3l02dq_read_reg_s16(struct iio_dev *indio_dev,
|
|||
st->tx[2] = LIS3L02DQ_READ_REG(lower_reg_address + 1);
|
||||
st->tx[3] = 0;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfers[0], &msg);
|
||||
spi_message_add_tail(&xfers[1], &msg);
|
||||
ret = spi_sync(st->us, &msg);
|
||||
ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
|
||||
if (ret) {
|
||||
dev_err(&st->us->dev, "problem when reading 16 bit register");
|
||||
goto error_ret;
|
||||
|
|
|
@ -90,7 +90,6 @@ int sca3000_read_data_short(struct sca3000_state *st,
|
|||
uint8_t reg_address_high,
|
||||
int len)
|
||||
{
|
||||
struct spi_message msg;
|
||||
struct spi_transfer xfer[2] = {
|
||||
{
|
||||
.len = 1,
|
||||
|
@ -101,11 +100,8 @@ int sca3000_read_data_short(struct sca3000_state *st,
|
|||
}
|
||||
};
|
||||
st->tx[0] = SCA3000_READ_REG(reg_address_high);
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfer[0], &msg);
|
||||
spi_message_add_tail(&xfer[1], &msg);
|
||||
|
||||
return spi_sync(st->us, &msg);
|
||||
return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -133,7 +129,6 @@ static int sca3000_reg_lock_on(struct sca3000_state *st)
|
|||
**/
|
||||
static int __sca3000_unlock_reg_lock(struct sca3000_state *st)
|
||||
{
|
||||
struct spi_message msg;
|
||||
struct spi_transfer xfer[3] = {
|
||||
{
|
||||
.len = 2,
|
||||
|
@ -154,12 +149,8 @@ static int __sca3000_unlock_reg_lock(struct sca3000_state *st)
|
|||
st->tx[3] = 0x50;
|
||||
st->tx[4] = SCA3000_WRITE_REG(SCA3000_REG_ADDR_UNLOCK);
|
||||
st->tx[5] = 0xA0;
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfer[0], &msg);
|
||||
spi_message_add_tail(&xfer[1], &msg);
|
||||
spi_message_add_tail(&xfer[2], &msg);
|
||||
|
||||
return spi_sync(st->us, &msg);
|
||||
return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -39,7 +39,6 @@ static int sca3000_read_data(struct sca3000_state *st,
|
|||
int len)
|
||||
{
|
||||
int ret;
|
||||
struct spi_message msg;
|
||||
struct spi_transfer xfer[2] = {
|
||||
{
|
||||
.len = 1,
|
||||
|
@ -55,10 +54,7 @@ static int sca3000_read_data(struct sca3000_state *st,
|
|||
}
|
||||
xfer[1].rx_buf = *rx_p;
|
||||
st->tx[0] = SCA3000_READ_REG(reg_address_high);
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfer[0], &msg);
|
||||
spi_message_add_tail(&xfer[1], &msg);
|
||||
ret = spi_sync(st->us, &msg);
|
||||
ret = spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer));
|
||||
if (ret) {
|
||||
dev_err(get_device(&st->us->dev), "problem reading register");
|
||||
goto error_free_rx;
|
||||
|
|
|
@ -199,12 +199,8 @@ static int __ad7280_read32(struct spi_device *spi, unsigned *val)
|
|||
.rx_buf = &rx_buf,
|
||||
.len = 4,
|
||||
};
|
||||
struct spi_message m;
|
||||
|
||||
spi_message_init(&m);
|
||||
spi_message_add_tail(&t, &m);
|
||||
|
||||
ret = spi_sync(spi, &m);
|
||||
ret = spi_sync_transfer(spi, &t, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ struct mxs_lradc_of_config {
|
|||
const char * const *irq_name;
|
||||
};
|
||||
|
||||
static const struct mxs_lradc_of_config const mxs_lradc_of_config[] = {
|
||||
static const struct mxs_lradc_of_config mxs_lradc_of_config[] = {
|
||||
[IMX23_LRADC] = {
|
||||
.irq_count = ARRAY_SIZE(mx23_lradc_irq_names),
|
||||
.irq_name = mx23_lradc_irq_names,
|
||||
|
|
|
@ -44,7 +44,6 @@ static ssize_t ad5930_set_parameter(struct device *dev,
|
|||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct spi_message msg;
|
||||
struct spi_transfer xfer;
|
||||
int ret;
|
||||
struct ad5903_config *config = (struct ad5903_config *)buf;
|
||||
|
@ -64,9 +63,7 @@ static ssize_t ad5930_set_parameter(struct device *dev,
|
|||
xfer.tx_buf = config;
|
||||
mutex_lock(&st->lock);
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfer, &msg);
|
||||
ret = spi_sync(st->sdev, &msg);
|
||||
ret = spi_sync_transfer(st->sdev, &xfer, 1);
|
||||
if (ret)
|
||||
goto error_ret;
|
||||
error_ret:
|
||||
|
|
|
@ -39,7 +39,6 @@ static ssize_t ad9850_set_parameter(struct device *dev,
|
|||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct spi_message msg;
|
||||
struct spi_transfer xfer;
|
||||
int ret;
|
||||
struct ad9850_config *config = (struct ad9850_config *)buf;
|
||||
|
@ -50,9 +49,7 @@ static ssize_t ad9850_set_parameter(struct device *dev,
|
|||
xfer.tx_buf = config;
|
||||
mutex_lock(&st->lock);
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfer, &msg);
|
||||
ret = spi_sync(st->sdev, &msg);
|
||||
ret = spi_sync_transfer(st->sdev, &xfer, 1);
|
||||
if (ret)
|
||||
goto error_ret;
|
||||
error_ret:
|
||||
|
|
|
@ -183,7 +183,6 @@ static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9852_set_parameter, 0);
|
|||
|
||||
static void ad9852_init(struct ad9852_state *st)
|
||||
{
|
||||
struct spi_message msg;
|
||||
struct spi_transfer xfer;
|
||||
int ret;
|
||||
u8 config[5];
|
||||
|
@ -199,9 +198,7 @@ static void ad9852_init(struct ad9852_state *st)
|
|||
xfer.len = 5;
|
||||
xfer.tx_buf = &config;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfer, &msg);
|
||||
ret = spi_sync(st->sdev, &msg);
|
||||
ret = spi_sync_transfer(st->sdev, &xfer, 1);
|
||||
if (ret)
|
||||
goto error_ret;
|
||||
|
||||
|
|
|
@ -103,7 +103,6 @@ static int ade7753_spi_read_reg_24(struct device *dev,
|
|||
u8 reg_address,
|
||||
u32 *val)
|
||||
{
|
||||
struct spi_message msg;
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct ade7753_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
@ -122,10 +121,7 @@ static int ade7753_spi_read_reg_24(struct device *dev,
|
|||
mutex_lock(&st->buf_lock);
|
||||
st->tx[0] = ADE7753_READ_REG(reg_address);
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfers[0], &msg);
|
||||
spi_message_add_tail(&xfers[1], &msg);
|
||||
ret = spi_sync(st->us, &msg);
|
||||
ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
|
||||
if (ret) {
|
||||
dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X",
|
||||
reg_address);
|
||||
|
|
|
@ -103,7 +103,6 @@ static int ade7754_spi_read_reg_24(struct device *dev,
|
|||
u8 reg_address,
|
||||
u32 *val)
|
||||
{
|
||||
struct spi_message msg;
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct ade7754_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
@ -122,9 +121,7 @@ static int ade7754_spi_read_reg_24(struct device *dev,
|
|||
st->tx[2] = 0;
|
||||
st->tx[3] = 0;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(xfers, &msg);
|
||||
ret = spi_sync(st->us, &msg);
|
||||
ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
|
||||
if (ret) {
|
||||
dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X",
|
||||
reg_address);
|
||||
|
|
|
@ -47,7 +47,6 @@ static int ade7758_spi_write_reg_16(struct device *dev,
|
|||
u16 value)
|
||||
{
|
||||
int ret;
|
||||
struct spi_message msg;
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct ade7758_state *st = iio_priv(indio_dev);
|
||||
struct spi_transfer xfers[] = {
|
||||
|
@ -63,9 +62,7 @@ static int ade7758_spi_write_reg_16(struct device *dev,
|
|||
st->tx[1] = (value >> 8) & 0xFF;
|
||||
st->tx[2] = value & 0xFF;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(xfers, &msg);
|
||||
ret = spi_sync(st->us, &msg);
|
||||
ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
|
||||
mutex_unlock(&st->buf_lock);
|
||||
|
||||
return ret;
|
||||
|
@ -76,7 +73,6 @@ static int ade7758_spi_write_reg_24(struct device *dev,
|
|||
u32 value)
|
||||
{
|
||||
int ret;
|
||||
struct spi_message msg;
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct ade7758_state *st = iio_priv(indio_dev);
|
||||
struct spi_transfer xfers[] = {
|
||||
|
@ -93,9 +89,7 @@ static int ade7758_spi_write_reg_24(struct device *dev,
|
|||
st->tx[2] = (value >> 8) & 0xFF;
|
||||
st->tx[3] = value & 0xFF;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(xfers, &msg);
|
||||
ret = spi_sync(st->us, &msg);
|
||||
ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
|
||||
mutex_unlock(&st->buf_lock);
|
||||
|
||||
return ret;
|
||||
|
@ -105,7 +99,6 @@ int ade7758_spi_read_reg_8(struct device *dev,
|
|||
u8 reg_address,
|
||||
u8 *val)
|
||||
{
|
||||
struct spi_message msg;
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct ade7758_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
@ -128,10 +121,7 @@ int ade7758_spi_read_reg_8(struct device *dev,
|
|||
st->tx[0] = ADE7758_READ_REG(reg_address);
|
||||
st->tx[1] = 0;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfers[0], &msg);
|
||||
spi_message_add_tail(&xfers[1], &msg);
|
||||
ret = spi_sync(st->us, &msg);
|
||||
ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
|
||||
if (ret) {
|
||||
dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X",
|
||||
reg_address);
|
||||
|
@ -148,7 +138,6 @@ static int ade7758_spi_read_reg_16(struct device *dev,
|
|||
u8 reg_address,
|
||||
u16 *val)
|
||||
{
|
||||
struct spi_message msg;
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct ade7758_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
@ -173,10 +162,7 @@ static int ade7758_spi_read_reg_16(struct device *dev,
|
|||
st->tx[1] = 0;
|
||||
st->tx[2] = 0;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfers[0], &msg);
|
||||
spi_message_add_tail(&xfers[1], &msg);
|
||||
ret = spi_sync(st->us, &msg);
|
||||
ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
|
||||
if (ret) {
|
||||
dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X",
|
||||
reg_address);
|
||||
|
@ -194,7 +180,6 @@ static int ade7758_spi_read_reg_24(struct device *dev,
|
|||
u8 reg_address,
|
||||
u32 *val)
|
||||
{
|
||||
struct spi_message msg;
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct ade7758_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
@ -219,10 +204,7 @@ static int ade7758_spi_read_reg_24(struct device *dev,
|
|||
st->tx[2] = 0;
|
||||
st->tx[3] = 0;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfers[0], &msg);
|
||||
spi_message_add_tail(&xfers[1], &msg);
|
||||
ret = spi_sync(st->us, &msg);
|
||||
ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
|
||||
if (ret) {
|
||||
dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X",
|
||||
reg_address);
|
||||
|
|
|
@ -103,7 +103,6 @@ static int ade7759_spi_read_reg_40(struct device *dev,
|
|||
u8 reg_address,
|
||||
u64 *val)
|
||||
{
|
||||
struct spi_message msg;
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct ade7759_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
@ -120,9 +119,7 @@ static int ade7759_spi_read_reg_40(struct device *dev,
|
|||
st->tx[0] = ADE7759_READ_REG(reg_address);
|
||||
memset(&st->tx[1], 0 , 5);
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(xfers, &msg);
|
||||
ret = spi_sync(st->us, &msg);
|
||||
ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
|
||||
if (ret) {
|
||||
dev_err(&st->us->dev, "problem when reading 40 bit register 0x%02X",
|
||||
reg_address);
|
||||
|
|
|
@ -20,7 +20,6 @@ static int ade7854_spi_write_reg_8(struct device *dev,
|
|||
u8 value)
|
||||
{
|
||||
int ret;
|
||||
struct spi_message msg;
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct ade7854_state *st = iio_priv(indio_dev);
|
||||
struct spi_transfer xfer = {
|
||||
|
@ -35,9 +34,7 @@ static int ade7854_spi_write_reg_8(struct device *dev,
|
|||
st->tx[2] = reg_address & 0xFF;
|
||||
st->tx[3] = value & 0xFF;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfer, &msg);
|
||||
ret = spi_sync(st->spi, &msg);
|
||||
ret = spi_sync_transfer(st->spi, &xfer, 1);
|
||||
mutex_unlock(&st->buf_lock);
|
||||
|
||||
return ret;
|
||||
|
@ -48,7 +45,6 @@ static int ade7854_spi_write_reg_16(struct device *dev,
|
|||
u16 value)
|
||||
{
|
||||
int ret;
|
||||
struct spi_message msg;
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct ade7854_state *st = iio_priv(indio_dev);
|
||||
struct spi_transfer xfer = {
|
||||
|
@ -64,9 +60,7 @@ static int ade7854_spi_write_reg_16(struct device *dev,
|
|||
st->tx[3] = (value >> 8) & 0xFF;
|
||||
st->tx[4] = value & 0xFF;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfer, &msg);
|
||||
ret = spi_sync(st->spi, &msg);
|
||||
ret = spi_sync_transfer(st->spi, &xfer, 1);
|
||||
mutex_unlock(&st->buf_lock);
|
||||
|
||||
return ret;
|
||||
|
@ -77,7 +71,6 @@ static int ade7854_spi_write_reg_24(struct device *dev,
|
|||
u32 value)
|
||||
{
|
||||
int ret;
|
||||
struct spi_message msg;
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct ade7854_state *st = iio_priv(indio_dev);
|
||||
struct spi_transfer xfer = {
|
||||
|
@ -94,9 +87,7 @@ static int ade7854_spi_write_reg_24(struct device *dev,
|
|||
st->tx[4] = (value >> 8) & 0xFF;
|
||||
st->tx[5] = value & 0xFF;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfer, &msg);
|
||||
ret = spi_sync(st->spi, &msg);
|
||||
ret = spi_sync_transfer(st->spi, &xfer, 1);
|
||||
mutex_unlock(&st->buf_lock);
|
||||
|
||||
return ret;
|
||||
|
@ -107,7 +98,6 @@ static int ade7854_spi_write_reg_32(struct device *dev,
|
|||
u32 value)
|
||||
{
|
||||
int ret;
|
||||
struct spi_message msg;
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct ade7854_state *st = iio_priv(indio_dev);
|
||||
struct spi_transfer xfer = {
|
||||
|
@ -125,9 +115,7 @@ static int ade7854_spi_write_reg_32(struct device *dev,
|
|||
st->tx[5] = (value >> 8) & 0xFF;
|
||||
st->tx[6] = value & 0xFF;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfer, &msg);
|
||||
ret = spi_sync(st->spi, &msg);
|
||||
ret = spi_sync_transfer(st->spi, &xfer, 1);
|
||||
mutex_unlock(&st->buf_lock);
|
||||
|
||||
return ret;
|
||||
|
@ -137,7 +125,6 @@ static int ade7854_spi_read_reg_8(struct device *dev,
|
|||
u16 reg_address,
|
||||
u8 *val)
|
||||
{
|
||||
struct spi_message msg;
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct ade7854_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
@ -159,10 +146,7 @@ static int ade7854_spi_read_reg_8(struct device *dev,
|
|||
st->tx[1] = (reg_address >> 8) & 0xFF;
|
||||
st->tx[2] = reg_address & 0xFF;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfers[0], &msg);
|
||||
spi_message_add_tail(&xfers[1], &msg);
|
||||
ret = spi_sync(st->spi, &msg);
|
||||
ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
|
||||
if (ret) {
|
||||
dev_err(&st->spi->dev, "problem when reading 8 bit register 0x%02X",
|
||||
reg_address);
|
||||
|
@ -179,7 +163,6 @@ static int ade7854_spi_read_reg_16(struct device *dev,
|
|||
u16 reg_address,
|
||||
u16 *val)
|
||||
{
|
||||
struct spi_message msg;
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct ade7854_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
@ -200,10 +183,7 @@ static int ade7854_spi_read_reg_16(struct device *dev,
|
|||
st->tx[1] = (reg_address >> 8) & 0xFF;
|
||||
st->tx[2] = reg_address & 0xFF;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfers[0], &msg);
|
||||
spi_message_add_tail(&xfers[1], &msg);
|
||||
ret = spi_sync(st->spi, &msg);
|
||||
ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
|
||||
if (ret) {
|
||||
dev_err(&st->spi->dev, "problem when reading 16 bit register 0x%02X",
|
||||
reg_address);
|
||||
|
@ -220,7 +200,6 @@ static int ade7854_spi_read_reg_24(struct device *dev,
|
|||
u16 reg_address,
|
||||
u32 *val)
|
||||
{
|
||||
struct spi_message msg;
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct ade7854_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
@ -242,10 +221,7 @@ static int ade7854_spi_read_reg_24(struct device *dev,
|
|||
st->tx[1] = (reg_address >> 8) & 0xFF;
|
||||
st->tx[2] = reg_address & 0xFF;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfers[0], &msg);
|
||||
spi_message_add_tail(&xfers[1], &msg);
|
||||
ret = spi_sync(st->spi, &msg);
|
||||
ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
|
||||
if (ret) {
|
||||
dev_err(&st->spi->dev, "problem when reading 24 bit register 0x%02X",
|
||||
reg_address);
|
||||
|
@ -262,7 +238,6 @@ static int ade7854_spi_read_reg_32(struct device *dev,
|
|||
u16 reg_address,
|
||||
u32 *val)
|
||||
{
|
||||
struct spi_message msg;
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct ade7854_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
@ -284,10 +259,7 @@ static int ade7854_spi_read_reg_32(struct device *dev,
|
|||
st->tx[1] = (reg_address >> 8) & 0xFF;
|
||||
st->tx[2] = reg_address & 0xFF;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfers[0], &msg);
|
||||
spi_message_add_tail(&xfers[1], &msg);
|
||||
ret = spi_sync(st->spi, &msg);
|
||||
ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
|
||||
if (ret) {
|
||||
dev_err(&st->spi->dev, "problem when reading 32 bit register 0x%02X",
|
||||
reg_address);
|
||||
|
|
|
@ -130,15 +130,12 @@ static int ad2s1210_config_read(struct ad2s1210_state *st,
|
|||
.rx_buf = st->rx,
|
||||
.tx_buf = st->tx,
|
||||
};
|
||||
struct spi_message msg;
|
||||
int ret = 0;
|
||||
|
||||
ad2s1210_set_mode(MOD_CONFIG, st);
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfer, &msg);
|
||||
st->tx[0] = address | AD2S1210_MSB_IS_HIGH;
|
||||
st->tx[1] = AD2S1210_REG_FAULT;
|
||||
ret = spi_sync(st->sdev, &msg);
|
||||
ret = spi_sync_transfer(st->sdev, &xfer, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
st->old_data = true;
|
||||
|
|
|
@ -235,6 +235,16 @@ void st_sensors_deallocate_trigger(struct iio_dev *indio_dev);
|
|||
irqreturn_t st_sensors_trigger_handler(int irq, void *p);
|
||||
|
||||
int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf);
|
||||
#else
|
||||
static inline int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
|
||||
const struct iio_trigger_ops *trigger_ops)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void st_sensors_deallocate_trigger(struct iio_dev *indio_dev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
int st_sensors_init_sensor(struct iio_dev *indio_dev);
|
||||
|
|
|
@ -31,14 +31,15 @@ struct iio_channel {
|
|||
|
||||
/**
|
||||
* iio_channel_get() - get description of all that is needed to access channel.
|
||||
* @name: Unique name of the device as provided in the iio_map
|
||||
* @dev: Pointer to consumer device. Device name must match
|
||||
* the name of the device as provided in the iio_map
|
||||
* with which the desired provider to consumer mapping
|
||||
* was registered.
|
||||
* @consumer_channel: Unique name to identify the channel on the consumer
|
||||
* side. This typically describes the channels use within
|
||||
* the consumer. E.g. 'battery_voltage'
|
||||
*/
|
||||
struct iio_channel *iio_channel_get(const char *name,
|
||||
struct iio_channel *iio_channel_get(struct device *dev,
|
||||
const char *consumer_channel);
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#ifndef _IIO_TRIGGER_H_
|
||||
#define _IIO_TRIGGER_H_
|
||||
|
||||
#ifdef CONFIG_IIO_TRIGGER
|
||||
struct iio_subirq {
|
||||
bool enabled;
|
||||
};
|
||||
|
@ -117,4 +118,8 @@ irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private);
|
|||
__printf(1, 2) struct iio_trigger *iio_trigger_alloc(const char *fmt, ...);
|
||||
void iio_trigger_free(struct iio_trigger *trig);
|
||||
|
||||
#else
|
||||
struct iio_trigger;
|
||||
struct iio_trigger_ops;
|
||||
#endif
|
||||
#endif /* _IIO_TRIGGER_H_ */
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Invensense, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __INV_MPU6050_PLATFORM_H_
|
||||
#define __INV_MPU6050_PLATFORM_H_
|
||||
|
||||
/**
|
||||
* struct inv_mpu6050_platform_data - Platform data for the mpu driver
|
||||
* @orientation: Orientation matrix of the chip
|
||||
*
|
||||
* Contains platform specific information on how to configure the MPU6050 to
|
||||
* work on this platform. The orientation matricies are 3x3 rotation matricies
|
||||
* that are applied to the data to rotate from the mounting orientation to the
|
||||
* platform orientation. The values must be one of 0, 1, or -1 and each row and
|
||||
* column should have exactly 1 non-zero value.
|
||||
*/
|
||||
struct inv_mpu6050_platform_data {
|
||||
__s8 orientation[9];
|
||||
};
|
||||
|
||||
#endif
|
|
@ -591,6 +591,26 @@ spi_transfer_del(struct spi_transfer *t)
|
|||
list_del(&t->transfer_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* spi_message_init_with_transfers - Initialize spi_message and append transfers
|
||||
* @m: spi_message to be initialized
|
||||
* @xfers: An array of spi transfers
|
||||
* @num_xfers: Number of items in the xfer array
|
||||
*
|
||||
* This function initializes the given spi_message and adds each spi_transfer in
|
||||
* the given array to the message.
|
||||
*/
|
||||
static inline void
|
||||
spi_message_init_with_transfers(struct spi_message *m,
|
||||
struct spi_transfer *xfers, unsigned int num_xfers)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
spi_message_init(m);
|
||||
for (i = 0; i < num_xfers; ++i)
|
||||
spi_message_add_tail(&xfers[i], m);
|
||||
}
|
||||
|
||||
/* It's fine to embed message and transaction structures in other data
|
||||
* structures so long as you don't free them while they're in use.
|
||||
*/
|
||||
|
@ -683,6 +703,30 @@ spi_read(struct spi_device *spi, void *buf, size_t len)
|
|||
return spi_sync(spi, &m);
|
||||
}
|
||||
|
||||
/**
|
||||
* spi_sync_transfer - synchronous SPI data transfer
|
||||
* @spi: device with which data will be exchanged
|
||||
* @xfers: An array of spi_transfers
|
||||
* @num_xfers: Number of items in the xfer array
|
||||
* Context: can sleep
|
||||
*
|
||||
* Does a synchronous SPI data transfer of the given spi_transfer array.
|
||||
*
|
||||
* For more specific semantics see spi_sync().
|
||||
*
|
||||
* It returns zero on success, else a negative error code.
|
||||
*/
|
||||
static inline int
|
||||
spi_sync_transfer(struct spi_device *spi, struct spi_transfer *xfers,
|
||||
unsigned int num_xfers)
|
||||
{
|
||||
struct spi_message msg;
|
||||
|
||||
spi_message_init_with_transfers(&msg, xfers, num_xfers);
|
||||
|
||||
return spi_sync(spi, &msg);
|
||||
}
|
||||
|
||||
/* this copies txbuf and rxbuf data; for small transfers only! */
|
||||
extern int spi_write_then_read(struct spi_device *spi,
|
||||
const void *txbuf, unsigned n_tx,
|
||||
|
|
Loading…
Reference in New Issue