// SPDX-License-Identifier: GPL-2.0-only /* * Freescale MPL115A1 pressure/temperature sensor * * Copyright (c) 2016 Akinobu Mita <akinobu.mita@gmail.com> * * 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");