Commit | Line | Data |
---|---|---|
c984b9cb AM |
1 | /* |
2 | * Freescale MPL115A1 pressure/temperature sensor | |
3 | * | |
4 | * Copyright (c) 2016 Akinobu Mita <akinobu.mita@gmail.com> | |
5 | * | |
6 | * This file is subject to the terms and conditions of version 2 of | |
7 | * the GNU General Public License. See the file COPYING in the main | |
8 | * directory of this archive for more details. | |
9 | * | |
10 | * Datasheet: http://www.nxp.com/files/sensors/doc/data_sheet/MPL115A1.pdf | |
11 | */ | |
12 | ||
13 | #include <linux/module.h> | |
14 | #include <linux/spi/spi.h> | |
15 | ||
16 | #include "mpl115.h" | |
17 | ||
18 | #define MPL115_SPI_WRITE(address) ((address) << 1) | |
19 | #define MPL115_SPI_READ(address) (0x80 | (address) << 1) | |
20 | ||
21 | struct mpl115_spi_buf { | |
22 | u8 tx[4]; | |
23 | u8 rx[4]; | |
24 | }; | |
25 | ||
26 | static int mpl115_spi_init(struct device *dev) | |
27 | { | |
28 | struct spi_device *spi = to_spi_device(dev); | |
29 | struct mpl115_spi_buf *buf; | |
30 | ||
31 | buf = devm_kzalloc(dev, sizeof(*buf), GFP_KERNEL); | |
32 | if (!buf) | |
33 | return -ENOMEM; | |
34 | ||
35 | spi_set_drvdata(spi, buf); | |
36 | ||
37 | return 0; | |
38 | } | |
39 | ||
40 | static int mpl115_spi_read(struct device *dev, u8 address) | |
41 | { | |
42 | struct spi_device *spi = to_spi_device(dev); | |
43 | struct mpl115_spi_buf *buf = spi_get_drvdata(spi); | |
44 | struct spi_transfer xfer = { | |
45 | .tx_buf = buf->tx, | |
46 | .rx_buf = buf->rx, | |
47 | .len = 4, | |
48 | }; | |
49 | int ret; | |
50 | ||
51 | buf->tx[0] = MPL115_SPI_READ(address); | |
52 | buf->tx[2] = MPL115_SPI_READ(address + 1); | |
53 | ||
54 | ret = spi_sync_transfer(spi, &xfer, 1); | |
55 | if (ret) | |
56 | return ret; | |
57 | ||
58 | return (buf->rx[1] << 8) | buf->rx[3]; | |
59 | } | |
60 | ||
61 | static int mpl115_spi_write(struct device *dev, u8 address, u8 value) | |
62 | { | |
63 | struct spi_device *spi = to_spi_device(dev); | |
64 | struct mpl115_spi_buf *buf = spi_get_drvdata(spi); | |
65 | struct spi_transfer xfer = { | |
66 | .tx_buf = buf->tx, | |
67 | .len = 2, | |
68 | }; | |
69 | ||
70 | buf->tx[0] = MPL115_SPI_WRITE(address); | |
71 | buf->tx[1] = value; | |
72 | ||
73 | return spi_sync_transfer(spi, &xfer, 1); | |
74 | } | |
75 | ||
76 | static const struct mpl115_ops mpl115_spi_ops = { | |
77 | .init = mpl115_spi_init, | |
78 | .read = mpl115_spi_read, | |
79 | .write = mpl115_spi_write, | |
80 | }; | |
81 | ||
82 | static int mpl115_spi_probe(struct spi_device *spi) | |
83 | { | |
84 | const struct spi_device_id *id = spi_get_device_id(spi); | |
85 | ||
86 | return mpl115_probe(&spi->dev, id->name, &mpl115_spi_ops); | |
87 | } | |
88 | ||
89 | static const struct spi_device_id mpl115_spi_ids[] = { | |
90 | { "mpl115", 0 }, | |
91 | {} | |
92 | }; | |
93 | MODULE_DEVICE_TABLE(spi, mpl115_spi_ids); | |
94 | ||
95 | static struct spi_driver mpl115_spi_driver = { | |
96 | .driver = { | |
97 | .name = "mpl115", | |
98 | }, | |
99 | .probe = mpl115_spi_probe, | |
100 | .id_table = mpl115_spi_ids, | |
101 | }; | |
102 | module_spi_driver(mpl115_spi_driver); | |
103 | ||
104 | MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>"); | |
105 | MODULE_DESCRIPTION("Freescale MPL115A1 pressure/temperature driver"); | |
106 | MODULE_LICENSE("GPL"); |