| /* |
| * 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"); |