107 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			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");
 |