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