iio: make st_sensors drivers use regmap
This patch is meant to replace the i2c/spi transfer functions with regmap. SPI framework requires DMA safe buffers so let's add GFP_DMA flag for memory allocation used by bulk_read functions. Signed-off-by: Denis Ciocca <denis.ciocca@st.com> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
parent
1ecd245e0e
commit
062809ef77
|
@ -39,7 +39,8 @@ static int st_accel_buffer_postenable(struct iio_dev *indio_dev)
|
||||||
int err;
|
int err;
|
||||||
struct st_sensor_data *adata = iio_priv(indio_dev);
|
struct st_sensor_data *adata = iio_priv(indio_dev);
|
||||||
|
|
||||||
adata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
|
adata->buffer_data = kmalloc(indio_dev->scan_bytes,
|
||||||
|
GFP_DMA | GFP_KERNEL);
|
||||||
if (adata->buffer_data == NULL) {
|
if (adata->buffer_data == NULL) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto allocate_memory_error;
|
goto allocate_memory_error;
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/mutex.h>
|
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
|
@ -1177,7 +1176,6 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
|
||||||
|
|
||||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||||
indio_dev->info = &accel_info;
|
indio_dev->info = &accel_info;
|
||||||
mutex_init(&adata->tb.buf_lock);
|
|
||||||
|
|
||||||
err = st_sensors_power_enable(indio_dev);
|
err = st_sensors_power_enable(indio_dev);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -1188,7 +1186,6 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
|
||||||
goto st_accel_power_off;
|
goto st_accel_power_off;
|
||||||
|
|
||||||
adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS;
|
adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS;
|
||||||
adata->multiread_bit = adata->sensor_settings->multi_read_bit;
|
|
||||||
indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
|
indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
|
||||||
|
|
||||||
channels_size = indio_dev->num_channels * sizeof(struct iio_chan_spec);
|
channels_size = indio_dev->num_channels * sizeof(struct iio_chan_spec);
|
||||||
|
|
|
@ -174,7 +174,9 @@ static int st_accel_i2c_probe(struct i2c_client *client)
|
||||||
adata = iio_priv(indio_dev);
|
adata = iio_priv(indio_dev);
|
||||||
adata->sensor_settings = (struct st_sensor_settings *)settings;
|
adata->sensor_settings = (struct st_sensor_settings *)settings;
|
||||||
|
|
||||||
st_sensors_i2c_configure(indio_dev, client, adata);
|
ret = st_sensors_i2c_configure(indio_dev, client);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
ret = st_accel_common_probe(indio_dev);
|
ret = st_accel_common_probe(indio_dev);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
|
|
@ -17,15 +17,16 @@
|
||||||
#include <linux/iio/trigger_consumer.h>
|
#include <linux/iio/trigger_consumer.h>
|
||||||
#include <linux/iio/triggered_buffer.h>
|
#include <linux/iio/triggered_buffer.h>
|
||||||
#include <linux/irqreturn.h>
|
#include <linux/irqreturn.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
|
||||||
#include <linux/iio/common/st_sensors.h>
|
#include <linux/iio/common/st_sensors.h>
|
||||||
|
|
||||||
|
|
||||||
static int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
|
static int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
struct st_sensor_data *sdata = iio_priv(indio_dev);
|
struct st_sensor_data *sdata = iio_priv(indio_dev);
|
||||||
unsigned int num_data_channels = sdata->num_data_channels;
|
unsigned int num_data_channels = sdata->num_data_channels;
|
||||||
|
int i;
|
||||||
|
|
||||||
for_each_set_bit(i, indio_dev->active_scan_mask, num_data_channels) {
|
for_each_set_bit(i, indio_dev->active_scan_mask, num_data_channels) {
|
||||||
const struct iio_chan_spec *channel = &indio_dev->channels[i];
|
const struct iio_chan_spec *channel = &indio_dev->channels[i];
|
||||||
|
@ -36,11 +37,8 @@ static int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
|
||||||
channel->scan_type.storagebits >> 3;
|
channel->scan_type.storagebits >> 3;
|
||||||
|
|
||||||
buf = PTR_ALIGN(buf, storage_bytes);
|
buf = PTR_ALIGN(buf, storage_bytes);
|
||||||
if (sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
|
if (regmap_bulk_read(sdata->regmap, channel->address,
|
||||||
channel->address,
|
buf, bytes_to_read) < 0)
|
||||||
bytes_to_read, buf,
|
|
||||||
sdata->multiread_bit) <
|
|
||||||
bytes_to_read)
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
/* Advance the buffer pointer */
|
/* Advance the buffer pointer */
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
#include <linux/iio/common/st_sensors.h>
|
#include <linux/iio/common/st_sensors.h>
|
||||||
|
|
||||||
|
@ -28,19 +29,10 @@ static inline u32 st_sensors_get_unaligned_le24(const u8 *p)
|
||||||
int st_sensors_write_data_with_mask(struct iio_dev *indio_dev,
|
int st_sensors_write_data_with_mask(struct iio_dev *indio_dev,
|
||||||
u8 reg_addr, u8 mask, u8 data)
|
u8 reg_addr, u8 mask, u8 data)
|
||||||
{
|
{
|
||||||
int err;
|
|
||||||
u8 new_data;
|
|
||||||
struct st_sensor_data *sdata = iio_priv(indio_dev);
|
struct st_sensor_data *sdata = iio_priv(indio_dev);
|
||||||
|
|
||||||
err = sdata->tf->read_byte(&sdata->tb, sdata->dev, reg_addr, &new_data);
|
return regmap_update_bits(sdata->regmap,
|
||||||
if (err < 0)
|
reg_addr, mask, data << __ffs(mask));
|
||||||
goto st_sensors_write_data_with_mask_error;
|
|
||||||
|
|
||||||
new_data = ((new_data & (~mask)) | ((data << __ffs(mask)) & mask));
|
|
||||||
err = sdata->tf->write_byte(&sdata->tb, sdata->dev, reg_addr, new_data);
|
|
||||||
|
|
||||||
st_sensors_write_data_with_mask_error:
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev,
|
int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev,
|
||||||
|
@ -48,19 +40,15 @@ int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev,
|
||||||
unsigned *readval)
|
unsigned *readval)
|
||||||
{
|
{
|
||||||
struct st_sensor_data *sdata = iio_priv(indio_dev);
|
struct st_sensor_data *sdata = iio_priv(indio_dev);
|
||||||
u8 readdata;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!readval)
|
if (!readval)
|
||||||
return sdata->tf->write_byte(&sdata->tb, sdata->dev,
|
return regmap_write(sdata->regmap, reg, writeval);
|
||||||
(u8)reg, (u8)writeval);
|
|
||||||
|
|
||||||
err = sdata->tf->read_byte(&sdata->tb, sdata->dev, (u8)reg, &readdata);
|
err = regmap_read(sdata->regmap, reg, readval);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
*readval = (unsigned)readdata;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(st_sensors_debugfs_reg_access);
|
EXPORT_SYMBOL(st_sensors_debugfs_reg_access);
|
||||||
|
@ -545,7 +533,7 @@ st_sensors_match_scale_error:
|
||||||
EXPORT_SYMBOL(st_sensors_set_fullscale_by_gain);
|
EXPORT_SYMBOL(st_sensors_set_fullscale_by_gain);
|
||||||
|
|
||||||
static int st_sensors_read_axis_data(struct iio_dev *indio_dev,
|
static int st_sensors_read_axis_data(struct iio_dev *indio_dev,
|
||||||
struct iio_chan_spec const *ch, int *data)
|
struct iio_chan_spec const *ch, int *data)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
u8 *outdata;
|
u8 *outdata;
|
||||||
|
@ -554,13 +542,12 @@ static int st_sensors_read_axis_data(struct iio_dev *indio_dev,
|
||||||
|
|
||||||
byte_for_channel = DIV_ROUND_UP(ch->scan_type.realbits +
|
byte_for_channel = DIV_ROUND_UP(ch->scan_type.realbits +
|
||||||
ch->scan_type.shift, 8);
|
ch->scan_type.shift, 8);
|
||||||
outdata = kmalloc(byte_for_channel, GFP_KERNEL);
|
outdata = kmalloc(byte_for_channel, GFP_DMA | GFP_KERNEL);
|
||||||
if (!outdata)
|
if (!outdata)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
err = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
|
err = regmap_bulk_read(sdata->regmap, ch->address,
|
||||||
ch->address, byte_for_channel,
|
outdata, byte_for_channel);
|
||||||
outdata, sdata->multiread_bit);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto st_sensors_free_memory;
|
goto st_sensors_free_memory;
|
||||||
|
|
||||||
|
@ -645,13 +632,11 @@ EXPORT_SYMBOL(st_sensors_get_settings_index);
|
||||||
int st_sensors_verify_id(struct iio_dev *indio_dev)
|
int st_sensors_verify_id(struct iio_dev *indio_dev)
|
||||||
{
|
{
|
||||||
struct st_sensor_data *sdata = iio_priv(indio_dev);
|
struct st_sensor_data *sdata = iio_priv(indio_dev);
|
||||||
int err;
|
int wai, err;
|
||||||
u8 wai;
|
|
||||||
|
|
||||||
if (sdata->sensor_settings->wai_addr) {
|
if (sdata->sensor_settings->wai_addr) {
|
||||||
err = sdata->tf->read_byte(&sdata->tb, sdata->dev,
|
err = regmap_read(sdata->regmap,
|
||||||
sdata->sensor_settings->wai_addr,
|
sdata->sensor_settings->wai_addr, &wai);
|
||||||
&wai);
|
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(&indio_dev->dev,
|
dev_err(&indio_dev->dev,
|
||||||
"failed to read Who-Am-I register.\n");
|
"failed to read Who-Am-I register.\n");
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <linux/iio/iio.h>
|
#include <linux/iio/iio.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
|
||||||
#include <linux/iio/common/st_sensors_i2c.h>
|
#include <linux/iio/common/st_sensors_i2c.h>
|
||||||
|
|
||||||
|
@ -26,55 +27,51 @@ static unsigned int st_sensors_i2c_get_irq(struct iio_dev *indio_dev)
|
||||||
return to_i2c_client(sdata->dev)->irq;
|
return to_i2c_client(sdata->dev)->irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int st_sensors_i2c_read_byte(struct st_sensor_transfer_buffer *tb,
|
static const struct regmap_config st_sensors_i2c_regmap_config = {
|
||||||
struct device *dev, u8 reg_addr, u8 *res_byte)
|
.reg_bits = 8,
|
||||||
{
|
.val_bits = 8,
|
||||||
int err;
|
|
||||||
|
|
||||||
err = i2c_smbus_read_byte_data(to_i2c_client(dev), reg_addr);
|
|
||||||
if (err < 0)
|
|
||||||
goto st_accel_i2c_read_byte_error;
|
|
||||||
|
|
||||||
*res_byte = err & 0xff;
|
|
||||||
|
|
||||||
st_accel_i2c_read_byte_error:
|
|
||||||
return err < 0 ? err : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int st_sensors_i2c_read_multiple_byte(
|
|
||||||
struct st_sensor_transfer_buffer *tb, struct device *dev,
|
|
||||||
u8 reg_addr, int len, u8 *data, bool multiread_bit)
|
|
||||||
{
|
|
||||||
if (multiread_bit)
|
|
||||||
reg_addr |= ST_SENSORS_I2C_MULTIREAD;
|
|
||||||
|
|
||||||
return i2c_smbus_read_i2c_block_data_or_emulated(to_i2c_client(dev),
|
|
||||||
reg_addr, len, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int st_sensors_i2c_write_byte(struct st_sensor_transfer_buffer *tb,
|
|
||||||
struct device *dev, u8 reg_addr, u8 data)
|
|
||||||
{
|
|
||||||
return i2c_smbus_write_byte_data(to_i2c_client(dev), reg_addr, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct st_sensor_transfer_function st_sensors_tf_i2c = {
|
|
||||||
.read_byte = st_sensors_i2c_read_byte,
|
|
||||||
.write_byte = st_sensors_i2c_write_byte,
|
|
||||||
.read_multiple_byte = st_sensors_i2c_read_multiple_byte,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void st_sensors_i2c_configure(struct iio_dev *indio_dev,
|
static const struct regmap_config st_sensors_i2c_regmap_multiread_bit_config = {
|
||||||
struct i2c_client *client, struct st_sensor_data *sdata)
|
.reg_bits = 8,
|
||||||
|
.val_bits = 8,
|
||||||
|
.read_flag_mask = ST_SENSORS_I2C_MULTIREAD,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* st_sensors_i2c_configure() - configure I2C interface
|
||||||
|
* @indio_dev: IIO device reference.
|
||||||
|
* @client: i2c client reference.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, else a negative error code.
|
||||||
|
*/
|
||||||
|
int st_sensors_i2c_configure(struct iio_dev *indio_dev,
|
||||||
|
struct i2c_client *client)
|
||||||
{
|
{
|
||||||
|
struct st_sensor_data *sdata = iio_priv(indio_dev);
|
||||||
|
const struct regmap_config *config;
|
||||||
|
|
||||||
|
if (sdata->sensor_settings->multi_read_bit)
|
||||||
|
config = &st_sensors_i2c_regmap_multiread_bit_config;
|
||||||
|
else
|
||||||
|
config = &st_sensors_i2c_regmap_config;
|
||||||
|
|
||||||
|
sdata->regmap = devm_regmap_init_i2c(client, config);
|
||||||
|
if (IS_ERR(sdata->regmap)) {
|
||||||
|
dev_err(&client->dev, "Failed to register i2c regmap (%d)\n",
|
||||||
|
(int)PTR_ERR(sdata->regmap));
|
||||||
|
return PTR_ERR(sdata->regmap);
|
||||||
|
}
|
||||||
|
|
||||||
i2c_set_clientdata(client, indio_dev);
|
i2c_set_clientdata(client, indio_dev);
|
||||||
|
|
||||||
indio_dev->dev.parent = &client->dev;
|
indio_dev->dev.parent = &client->dev;
|
||||||
indio_dev->name = client->name;
|
indio_dev->name = client->name;
|
||||||
|
|
||||||
sdata->dev = &client->dev;
|
sdata->dev = &client->dev;
|
||||||
sdata->tf = &st_sensors_tf_i2c;
|
|
||||||
sdata->get_irq_data_ready = st_sensors_i2c_get_irq;
|
sdata->get_irq_data_ready = st_sensors_i2c_get_irq;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(st_sensors_i2c_configure);
|
EXPORT_SYMBOL(st_sensors_i2c_configure);
|
||||||
|
|
||||||
|
|
|
@ -11,12 +11,12 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/iio/iio.h>
|
#include <linux/iio/iio.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
|
||||||
#include <linux/iio/common/st_sensors_spi.h>
|
#include <linux/iio/common/st_sensors_spi.h>
|
||||||
|
#include "st_sensors_core.h"
|
||||||
|
|
||||||
#define ST_SENSORS_SPI_MULTIREAD 0xc0
|
#define ST_SENSORS_SPI_MULTIREAD 0xc0
|
||||||
#define ST_SENSORS_SPI_READ 0x80
|
|
||||||
|
|
||||||
static unsigned int st_sensors_spi_get_irq(struct iio_dev *indio_dev)
|
static unsigned int st_sensors_spi_get_irq(struct iio_dev *indio_dev)
|
||||||
{
|
{
|
||||||
|
@ -25,81 +25,15 @@ static unsigned int st_sensors_spi_get_irq(struct iio_dev *indio_dev)
|
||||||
return to_spi_device(sdata->dev)->irq;
|
return to_spi_device(sdata->dev)->irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int st_sensors_spi_read(struct st_sensor_transfer_buffer *tb,
|
static const struct regmap_config st_sensors_spi_regmap_config = {
|
||||||
struct device *dev, u8 reg_addr, int len, u8 *data, bool multiread_bit)
|
.reg_bits = 8,
|
||||||
{
|
.val_bits = 8,
|
||||||
int err;
|
};
|
||||||
|
|
||||||
struct spi_transfer xfers[] = {
|
static const struct regmap_config st_sensors_spi_regmap_multiread_bit_config = {
|
||||||
{
|
.reg_bits = 8,
|
||||||
.tx_buf = tb->tx_buf,
|
.val_bits = 8,
|
||||||
.bits_per_word = 8,
|
.read_flag_mask = ST_SENSORS_SPI_MULTIREAD,
|
||||||
.len = 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rx_buf = tb->rx_buf,
|
|
||||||
.bits_per_word = 8,
|
|
||||||
.len = len,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
mutex_lock(&tb->buf_lock);
|
|
||||||
if ((multiread_bit) && (len > 1))
|
|
||||||
tb->tx_buf[0] = reg_addr | ST_SENSORS_SPI_MULTIREAD;
|
|
||||||
else
|
|
||||||
tb->tx_buf[0] = reg_addr | ST_SENSORS_SPI_READ;
|
|
||||||
|
|
||||||
err = spi_sync_transfer(to_spi_device(dev), xfers, ARRAY_SIZE(xfers));
|
|
||||||
if (err)
|
|
||||||
goto acc_spi_read_error;
|
|
||||||
|
|
||||||
memcpy(data, tb->rx_buf, len);
|
|
||||||
mutex_unlock(&tb->buf_lock);
|
|
||||||
return len;
|
|
||||||
|
|
||||||
acc_spi_read_error:
|
|
||||||
mutex_unlock(&tb->buf_lock);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int st_sensors_spi_read_byte(struct st_sensor_transfer_buffer *tb,
|
|
||||||
struct device *dev, u8 reg_addr, u8 *res_byte)
|
|
||||||
{
|
|
||||||
return st_sensors_spi_read(tb, dev, reg_addr, 1, res_byte, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int st_sensors_spi_read_multiple_byte(
|
|
||||||
struct st_sensor_transfer_buffer *tb, struct device *dev,
|
|
||||||
u8 reg_addr, int len, u8 *data, bool multiread_bit)
|
|
||||||
{
|
|
||||||
return st_sensors_spi_read(tb, dev, reg_addr, len, data, multiread_bit);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int st_sensors_spi_write_byte(struct st_sensor_transfer_buffer *tb,
|
|
||||||
struct device *dev, u8 reg_addr, u8 data)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
|
|
||||||
struct spi_transfer xfers = {
|
|
||||||
.tx_buf = tb->tx_buf,
|
|
||||||
.bits_per_word = 8,
|
|
||||||
.len = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
mutex_lock(&tb->buf_lock);
|
|
||||||
tb->tx_buf[0] = reg_addr;
|
|
||||||
tb->tx_buf[1] = data;
|
|
||||||
|
|
||||||
err = spi_sync_transfer(to_spi_device(dev), &xfers, 1);
|
|
||||||
mutex_unlock(&tb->buf_lock);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct st_sensor_transfer_function st_sensors_tf_spi = {
|
|
||||||
.read_byte = st_sensors_spi_read_byte,
|
|
||||||
.write_byte = st_sensors_spi_write_byte,
|
|
||||||
.read_multiple_byte = st_sensors_spi_read_multiple_byte,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -155,6 +89,7 @@ int st_sensors_spi_configure(struct iio_dev *indio_dev,
|
||||||
struct spi_device *spi)
|
struct spi_device *spi)
|
||||||
{
|
{
|
||||||
struct st_sensor_data *sdata = iio_priv(indio_dev);
|
struct st_sensor_data *sdata = iio_priv(indio_dev);
|
||||||
|
const struct regmap_config *config;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (st_sensors_is_spi_3_wire(spi)) {
|
if (st_sensors_is_spi_3_wire(spi)) {
|
||||||
|
@ -164,13 +99,24 @@ int st_sensors_spi_configure(struct iio_dev *indio_dev,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sdata->sensor_settings->multi_read_bit)
|
||||||
|
config = &st_sensors_spi_regmap_multiread_bit_config;
|
||||||
|
else
|
||||||
|
config = &st_sensors_spi_regmap_config;
|
||||||
|
|
||||||
|
sdata->regmap = devm_regmap_init_spi(spi, config);
|
||||||
|
if (IS_ERR(sdata->regmap)) {
|
||||||
|
dev_err(&spi->dev, "Failed to register spi regmap (%d)\n",
|
||||||
|
(int)PTR_ERR(sdata->regmap));
|
||||||
|
return PTR_ERR(sdata->regmap);
|
||||||
|
}
|
||||||
|
|
||||||
spi_set_drvdata(spi, indio_dev);
|
spi_set_drvdata(spi, indio_dev);
|
||||||
|
|
||||||
indio_dev->dev.parent = &spi->dev;
|
indio_dev->dev.parent = &spi->dev;
|
||||||
indio_dev->name = spi->modalias;
|
indio_dev->name = spi->modalias;
|
||||||
|
|
||||||
sdata->dev = &spi->dev;
|
sdata->dev = &spi->dev;
|
||||||
sdata->tf = &st_sensors_tf_spi;
|
|
||||||
sdata->get_irq_data_ready = st_sensors_spi_get_irq;
|
sdata->get_irq_data_ready = st_sensors_spi_get_irq;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <linux/iio/iio.h>
|
#include <linux/iio/iio.h>
|
||||||
#include <linux/iio/trigger.h>
|
#include <linux/iio/trigger.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
#include <linux/iio/common/st_sensors.h>
|
#include <linux/iio/common/st_sensors.h>
|
||||||
#include "st_sensors_core.h"
|
#include "st_sensors_core.h"
|
||||||
|
|
||||||
|
@ -26,8 +27,7 @@
|
||||||
static int st_sensors_new_samples_available(struct iio_dev *indio_dev,
|
static int st_sensors_new_samples_available(struct iio_dev *indio_dev,
|
||||||
struct st_sensor_data *sdata)
|
struct st_sensor_data *sdata)
|
||||||
{
|
{
|
||||||
u8 status;
|
int ret, status;
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* How would I know if I can't check it? */
|
/* How would I know if I can't check it? */
|
||||||
if (!sdata->sensor_settings->drdy_irq.stat_drdy.addr)
|
if (!sdata->sensor_settings->drdy_irq.stat_drdy.addr)
|
||||||
|
@ -37,9 +37,9 @@ static int st_sensors_new_samples_available(struct iio_dev *indio_dev,
|
||||||
if (!indio_dev->active_scan_mask)
|
if (!indio_dev->active_scan_mask)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = sdata->tf->read_byte(&sdata->tb, sdata->dev,
|
ret = regmap_read(sdata->regmap,
|
||||||
sdata->sensor_settings->drdy_irq.stat_drdy.addr,
|
sdata->sensor_settings->drdy_irq.stat_drdy.addr,
|
||||||
&status);
|
&status);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(sdata->dev,
|
dev_err(sdata->dev,
|
||||||
"error checking samples available\n");
|
"error checking samples available\n");
|
||||||
|
|
|
@ -39,7 +39,8 @@ static int st_gyro_buffer_postenable(struct iio_dev *indio_dev)
|
||||||
int err;
|
int err;
|
||||||
struct st_sensor_data *gdata = iio_priv(indio_dev);
|
struct st_sensor_data *gdata = iio_priv(indio_dev);
|
||||||
|
|
||||||
gdata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
|
gdata->buffer_data = kmalloc(indio_dev->scan_bytes,
|
||||||
|
GFP_DMA | GFP_KERNEL);
|
||||||
if (gdata->buffer_data == NULL) {
|
if (gdata->buffer_data == NULL) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto allocate_memory_error;
|
goto allocate_memory_error;
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/mutex.h>
|
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
|
@ -394,7 +393,6 @@ int st_gyro_common_probe(struct iio_dev *indio_dev)
|
||||||
|
|
||||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||||
indio_dev->info = &gyro_info;
|
indio_dev->info = &gyro_info;
|
||||||
mutex_init(&gdata->tb.buf_lock);
|
|
||||||
|
|
||||||
err = st_sensors_power_enable(indio_dev);
|
err = st_sensors_power_enable(indio_dev);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -405,7 +403,6 @@ int st_gyro_common_probe(struct iio_dev *indio_dev)
|
||||||
goto st_gyro_power_off;
|
goto st_gyro_power_off;
|
||||||
|
|
||||||
gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS;
|
gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS;
|
||||||
gdata->multiread_bit = gdata->sensor_settings->multi_read_bit;
|
|
||||||
indio_dev->channels = gdata->sensor_settings->ch;
|
indio_dev->channels = gdata->sensor_settings->ch;
|
||||||
indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
|
indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,9 @@ static int st_gyro_i2c_probe(struct i2c_client *client,
|
||||||
gdata = iio_priv(indio_dev);
|
gdata = iio_priv(indio_dev);
|
||||||
gdata->sensor_settings = (struct st_sensor_settings *)settings;
|
gdata->sensor_settings = (struct st_sensor_settings *)settings;
|
||||||
|
|
||||||
st_sensors_i2c_configure(indio_dev, client, gdata);
|
err = st_sensors_i2c_configure(indio_dev, client);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
err = st_gyro_common_probe(indio_dev);
|
err = st_gyro_common_probe(indio_dev);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
|
|
@ -34,7 +34,8 @@ static int st_magn_buffer_postenable(struct iio_dev *indio_dev)
|
||||||
int err;
|
int err;
|
||||||
struct st_sensor_data *mdata = iio_priv(indio_dev);
|
struct st_sensor_data *mdata = iio_priv(indio_dev);
|
||||||
|
|
||||||
mdata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
|
mdata->buffer_data = kmalloc(indio_dev->scan_bytes,
|
||||||
|
GFP_DMA | GFP_KERNEL);
|
||||||
if (mdata->buffer_data == NULL) {
|
if (mdata->buffer_data == NULL) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto allocate_memory_error;
|
goto allocate_memory_error;
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/mutex.h>
|
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
|
@ -496,7 +495,6 @@ int st_magn_common_probe(struct iio_dev *indio_dev)
|
||||||
|
|
||||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||||
indio_dev->info = &magn_info;
|
indio_dev->info = &magn_info;
|
||||||
mutex_init(&mdata->tb.buf_lock);
|
|
||||||
|
|
||||||
err = st_sensors_power_enable(indio_dev);
|
err = st_sensors_power_enable(indio_dev);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -507,7 +505,6 @@ int st_magn_common_probe(struct iio_dev *indio_dev)
|
||||||
goto st_magn_power_off;
|
goto st_magn_power_off;
|
||||||
|
|
||||||
mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS;
|
mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS;
|
||||||
mdata->multiread_bit = mdata->sensor_settings->multi_read_bit;
|
|
||||||
indio_dev->channels = mdata->sensor_settings->ch;
|
indio_dev->channels = mdata->sensor_settings->ch;
|
||||||
indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
|
indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,9 @@ static int st_magn_i2c_probe(struct i2c_client *client,
|
||||||
mdata = iio_priv(indio_dev);
|
mdata = iio_priv(indio_dev);
|
||||||
mdata->sensor_settings = (struct st_sensor_settings *)settings;
|
mdata->sensor_settings = (struct st_sensor_settings *)settings;
|
||||||
|
|
||||||
st_sensors_i2c_configure(indio_dev, client, mdata);
|
err = st_sensors_i2c_configure(indio_dev, client);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
err = st_magn_common_probe(indio_dev);
|
err = st_magn_common_probe(indio_dev);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
|
|
@ -39,7 +39,8 @@ static int st_press_buffer_postenable(struct iio_dev *indio_dev)
|
||||||
int err;
|
int err;
|
||||||
struct st_sensor_data *press_data = iio_priv(indio_dev);
|
struct st_sensor_data *press_data = iio_priv(indio_dev);
|
||||||
|
|
||||||
press_data->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
|
press_data->buffer_data = kmalloc(indio_dev->scan_bytes,
|
||||||
|
GFP_DMA | GFP_KERNEL);
|
||||||
if (press_data->buffer_data == NULL) {
|
if (press_data->buffer_data == NULL) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto allocate_memory_error;
|
goto allocate_memory_error;
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/mutex.h>
|
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
|
@ -692,7 +691,6 @@ int st_press_common_probe(struct iio_dev *indio_dev)
|
||||||
|
|
||||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||||
indio_dev->info = &press_info;
|
indio_dev->info = &press_info;
|
||||||
mutex_init(&press_data->tb.buf_lock);
|
|
||||||
|
|
||||||
err = st_sensors_power_enable(indio_dev);
|
err = st_sensors_power_enable(indio_dev);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -709,7 +707,6 @@ int st_press_common_probe(struct iio_dev *indio_dev)
|
||||||
* element.
|
* element.
|
||||||
*/
|
*/
|
||||||
press_data->num_data_channels = press_data->sensor_settings->num_ch - 1;
|
press_data->num_data_channels = press_data->sensor_settings->num_ch - 1;
|
||||||
press_data->multiread_bit = press_data->sensor_settings->multi_read_bit;
|
|
||||||
indio_dev->channels = press_data->sensor_settings->ch;
|
indio_dev->channels = press_data->sensor_settings->ch;
|
||||||
indio_dev->num_channels = press_data->sensor_settings->num_ch;
|
indio_dev->num_channels = press_data->sensor_settings->num_ch;
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,9 @@ static int st_press_i2c_probe(struct i2c_client *client,
|
||||||
press_data = iio_priv(indio_dev);
|
press_data = iio_priv(indio_dev);
|
||||||
press_data->sensor_settings = (struct st_sensor_settings *)settings;
|
press_data->sensor_settings = (struct st_sensor_settings *)settings;
|
||||||
|
|
||||||
st_sensors_i2c_configure(indio_dev, client, press_data);
|
ret = st_sensors_i2c_configure(indio_dev, client);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
ret = st_press_common_probe(indio_dev);
|
ret = st_press_common_probe(indio_dev);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <linux/iio/trigger.h>
|
#include <linux/iio/trigger.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
|
||||||
#include <linux/platform_data/st_sensors_pdata.h>
|
#include <linux/platform_data/st_sensors_pdata.h>
|
||||||
|
|
||||||
|
@ -169,36 +170,6 @@ struct st_sensor_data_ready_irq {
|
||||||
} ig1;
|
} ig1;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* struct st_sensor_transfer_buffer - ST sensor device I/O buffer
|
|
||||||
* @buf_lock: Mutex to protect rx and tx buffers.
|
|
||||||
* @tx_buf: Buffer used by SPI transfer function to send data to the sensors.
|
|
||||||
* This buffer is used to avoid DMA not-aligned issue.
|
|
||||||
* @rx_buf: Buffer used by SPI transfer to receive data from sensors.
|
|
||||||
* This buffer is used to avoid DMA not-aligned issue.
|
|
||||||
*/
|
|
||||||
struct st_sensor_transfer_buffer {
|
|
||||||
struct mutex buf_lock;
|
|
||||||
u8 rx_buf[ST_SENSORS_RX_MAX_LENGTH];
|
|
||||||
u8 tx_buf[ST_SENSORS_TX_MAX_LENGTH] ____cacheline_aligned;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* struct st_sensor_transfer_function - ST sensor device I/O function
|
|
||||||
* @read_byte: Function used to read one byte.
|
|
||||||
* @write_byte: Function used to write one byte.
|
|
||||||
* @read_multiple_byte: Function used to read multiple byte.
|
|
||||||
*/
|
|
||||||
struct st_sensor_transfer_function {
|
|
||||||
int (*read_byte) (struct st_sensor_transfer_buffer *tb,
|
|
||||||
struct device *dev, u8 reg_addr, u8 *res_byte);
|
|
||||||
int (*write_byte) (struct st_sensor_transfer_buffer *tb,
|
|
||||||
struct device *dev, u8 reg_addr, u8 data);
|
|
||||||
int (*read_multiple_byte) (struct st_sensor_transfer_buffer *tb,
|
|
||||||
struct device *dev, u8 reg_addr, int len, u8 *data,
|
|
||||||
bool multiread_bit);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct st_sensor_settings - ST specific sensor settings
|
* struct st_sensor_settings - ST specific sensor settings
|
||||||
* @wai: Contents of WhoAmI register.
|
* @wai: Contents of WhoAmI register.
|
||||||
|
@ -242,16 +213,14 @@ struct st_sensor_settings {
|
||||||
* @current_fullscale: Maximum range of measure by the sensor.
|
* @current_fullscale: Maximum range of measure by the sensor.
|
||||||
* @vdd: Pointer to sensor's Vdd power supply
|
* @vdd: Pointer to sensor's Vdd power supply
|
||||||
* @vdd_io: Pointer to sensor's Vdd-IO power supply
|
* @vdd_io: Pointer to sensor's Vdd-IO power supply
|
||||||
|
* @regmap: Pointer to specific sensor regmap configuration.
|
||||||
* @enabled: Status of the sensor (false->off, true->on).
|
* @enabled: Status of the sensor (false->off, true->on).
|
||||||
* @multiread_bit: Use or not particular bit for [I2C/SPI] multiread.
|
|
||||||
* @buffer_data: Data used by buffer part.
|
* @buffer_data: Data used by buffer part.
|
||||||
* @odr: Output data rate of the sensor [Hz].
|
* @odr: Output data rate of the sensor [Hz].
|
||||||
* num_data_channels: Number of data channels used in buffer.
|
* num_data_channels: Number of data channels used in buffer.
|
||||||
* @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2).
|
* @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2).
|
||||||
* @int_pin_open_drain: Set the interrupt/DRDY to open drain.
|
* @int_pin_open_drain: Set the interrupt/DRDY to open drain.
|
||||||
* @get_irq_data_ready: Function to get the IRQ used for data ready signal.
|
* @get_irq_data_ready: Function to get the IRQ used for data ready signal.
|
||||||
* @tf: Transfer function structure used by I/O operations.
|
|
||||||
* @tb: Transfer buffers and mutex used by I/O operations.
|
|
||||||
* @edge_irq: the IRQ triggers on edges and need special handling.
|
* @edge_irq: the IRQ triggers on edges and need special handling.
|
||||||
* @hw_irq_trigger: if we're using the hardware interrupt on the sensor.
|
* @hw_irq_trigger: if we're using the hardware interrupt on the sensor.
|
||||||
* @hw_timestamp: Latest timestamp from the interrupt handler, when in use.
|
* @hw_timestamp: Latest timestamp from the interrupt handler, when in use.
|
||||||
|
@ -264,9 +233,9 @@ struct st_sensor_data {
|
||||||
struct st_sensor_fullscale_avl *current_fullscale;
|
struct st_sensor_fullscale_avl *current_fullscale;
|
||||||
struct regulator *vdd;
|
struct regulator *vdd;
|
||||||
struct regulator *vdd_io;
|
struct regulator *vdd_io;
|
||||||
|
struct regmap *regmap;
|
||||||
|
|
||||||
bool enabled;
|
bool enabled;
|
||||||
bool multiread_bit;
|
|
||||||
|
|
||||||
char *buffer_data;
|
char *buffer_data;
|
||||||
|
|
||||||
|
@ -278,9 +247,6 @@ struct st_sensor_data {
|
||||||
|
|
||||||
unsigned int (*get_irq_data_ready) (struct iio_dev *indio_dev);
|
unsigned int (*get_irq_data_ready) (struct iio_dev *indio_dev);
|
||||||
|
|
||||||
const struct st_sensor_transfer_function *tf;
|
|
||||||
struct st_sensor_transfer_buffer tb;
|
|
||||||
|
|
||||||
bool edge_irq;
|
bool edge_irq;
|
||||||
bool hw_irq_trigger;
|
bool hw_irq_trigger;
|
||||||
s64 hw_timestamp;
|
s64 hw_timestamp;
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
#include <linux/iio/common/st_sensors.h>
|
#include <linux/iio/common/st_sensors.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
|
||||||
void st_sensors_i2c_configure(struct iio_dev *indio_dev,
|
int st_sensors_i2c_configure(struct iio_dev *indio_dev,
|
||||||
struct i2c_client *client, struct st_sensor_data *sdata);
|
struct i2c_client *client);
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI
|
#ifdef CONFIG_ACPI
|
||||||
int st_sensors_match_acpi_device(struct device *dev);
|
int st_sensors_match_acpi_device(struct device *dev);
|
||||||
|
|
Loading…
Reference in New Issue