linux/drivers/iio/pressure/mpl115_spi.c
Akinobu Mita c984b9cbbd iio: pressure: mpl115: support MPL115A1
mpl115 driver currently supports i2c interface (MPL115A2).
There is also SPI version (MPL115A1).  The difference between them
is only physical transport so we can easily support both while sharing
most of the code.

Split the driver into a core support module and one module each for I2C
and SPI support.

Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Cc: Jonathan Cameron <jic23@kernel.org>
Cc: Hartmut Knaack <knaack.h@gmx.de>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Peter Meerwald <pmeerw@pmeerw.net>
Cc: linux-iio@vger.kernel.org
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2016-01-30 16:27:12 +00:00

107 lines
2.4 KiB
C

/*
* Freescale MPL115A1 pressure/temperature sensor
*
* Copyright (c) 2016 Akinobu Mita <akinobu.mita@gmail.com>
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*
* Datasheet: http://www.nxp.com/files/sensors/doc/data_sheet/MPL115A1.pdf
*/
#include <linux/module.h>
#include <linux/spi/spi.h>
#include "mpl115.h"
#define MPL115_SPI_WRITE(address) ((address) << 1)
#define MPL115_SPI_READ(address) (0x80 | (address) << 1)
struct mpl115_spi_buf {
u8 tx[4];
u8 rx[4];
};
static int mpl115_spi_init(struct device *dev)
{
struct spi_device *spi = to_spi_device(dev);
struct mpl115_spi_buf *buf;
buf = devm_kzalloc(dev, sizeof(*buf), GFP_KERNEL);
if (!buf)
return -ENOMEM;
spi_set_drvdata(spi, buf);
return 0;
}
static int mpl115_spi_read(struct device *dev, u8 address)
{
struct spi_device *spi = to_spi_device(dev);
struct mpl115_spi_buf *buf = spi_get_drvdata(spi);
struct spi_transfer xfer = {
.tx_buf = buf->tx,
.rx_buf = buf->rx,
.len = 4,
};
int ret;
buf->tx[0] = MPL115_SPI_READ(address);
buf->tx[2] = MPL115_SPI_READ(address + 1);
ret = spi_sync_transfer(spi, &xfer, 1);
if (ret)
return ret;
return (buf->rx[1] << 8) | buf->rx[3];
}
static int mpl115_spi_write(struct device *dev, u8 address, u8 value)
{
struct spi_device *spi = to_spi_device(dev);
struct mpl115_spi_buf *buf = spi_get_drvdata(spi);
struct spi_transfer xfer = {
.tx_buf = buf->tx,
.len = 2,
};
buf->tx[0] = MPL115_SPI_WRITE(address);
buf->tx[1] = value;
return spi_sync_transfer(spi, &xfer, 1);
}
static const struct mpl115_ops mpl115_spi_ops = {
.init = mpl115_spi_init,
.read = mpl115_spi_read,
.write = mpl115_spi_write,
};
static int mpl115_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
return mpl115_probe(&spi->dev, id->name, &mpl115_spi_ops);
}
static const struct spi_device_id mpl115_spi_ids[] = {
{ "mpl115", 0 },
{}
};
MODULE_DEVICE_TABLE(spi, mpl115_spi_ids);
static struct spi_driver mpl115_spi_driver = {
.driver = {
.name = "mpl115",
},
.probe = mpl115_spi_probe,
.id_table = mpl115_spi_ids,
};
module_spi_driver(mpl115_spi_driver);
MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>");
MODULE_DESCRIPTION("Freescale MPL115A1 pressure/temperature driver");
MODULE_LICENSE("GPL");