Commit | Line | Data |
---|---|---|
23491b51 DC |
1 | /* |
2 | * STMicroelectronics sensors spi library driver | |
3 | * | |
4 | * Copyright 2012-2013 STMicroelectronics Inc. | |
5 | * | |
6 | * Denis Ciocca <denis.ciocca@st.com> | |
7 | * | |
8 | * Licensed under the GPL-2. | |
9 | */ | |
10 | ||
11 | #include <linux/kernel.h> | |
12 | #include <linux/module.h> | |
13 | #include <linux/slab.h> | |
14 | #include <linux/iio/iio.h> | |
15 | ||
16 | #include <linux/iio/common/st_sensors_spi.h> | |
17 | ||
18 | ||
19 | #define ST_SENSORS_SPI_MULTIREAD 0xc0 | |
20 | #define ST_SENSORS_SPI_READ 0x80 | |
21 | ||
22 | static unsigned int st_sensors_spi_get_irq(struct iio_dev *indio_dev) | |
23 | { | |
24 | struct st_sensor_data *sdata = iio_priv(indio_dev); | |
25 | ||
26 | return to_spi_device(sdata->dev)->irq; | |
27 | } | |
28 | ||
29 | static int st_sensors_spi_read(struct st_sensor_transfer_buffer *tb, | |
30 | struct device *dev, u8 reg_addr, int len, u8 *data, bool multiread_bit) | |
31 | { | |
23491b51 DC |
32 | int err; |
33 | ||
34 | struct spi_transfer xfers[] = { | |
35 | { | |
36 | .tx_buf = tb->tx_buf, | |
37 | .bits_per_word = 8, | |
38 | .len = 1, | |
39 | }, | |
40 | { | |
41 | .rx_buf = tb->rx_buf, | |
42 | .bits_per_word = 8, | |
43 | .len = len, | |
44 | } | |
45 | }; | |
46 | ||
47 | mutex_lock(&tb->buf_lock); | |
48 | if ((multiread_bit) && (len > 1)) | |
49 | tb->tx_buf[0] = reg_addr | ST_SENSORS_SPI_MULTIREAD; | |
50 | else | |
51 | tb->tx_buf[0] = reg_addr | ST_SENSORS_SPI_READ; | |
52 | ||
43bb786a | 53 | err = spi_sync_transfer(to_spi_device(dev), xfers, ARRAY_SIZE(xfers)); |
23491b51 DC |
54 | if (err) |
55 | goto acc_spi_read_error; | |
56 | ||
57 | memcpy(data, tb->rx_buf, len*sizeof(u8)); | |
58 | mutex_unlock(&tb->buf_lock); | |
59 | return len; | |
60 | ||
61 | acc_spi_read_error: | |
62 | mutex_unlock(&tb->buf_lock); | |
63 | return err; | |
64 | } | |
65 | ||
66 | static int st_sensors_spi_read_byte(struct st_sensor_transfer_buffer *tb, | |
67 | struct device *dev, u8 reg_addr, u8 *res_byte) | |
68 | { | |
69 | return st_sensors_spi_read(tb, dev, reg_addr, 1, res_byte, false); | |
70 | } | |
71 | ||
72 | static int st_sensors_spi_read_multiple_byte( | |
73 | struct st_sensor_transfer_buffer *tb, struct device *dev, | |
74 | u8 reg_addr, int len, u8 *data, bool multiread_bit) | |
75 | { | |
76 | return st_sensors_spi_read(tb, dev, reg_addr, len, data, multiread_bit); | |
77 | } | |
78 | ||
79 | static int st_sensors_spi_write_byte(struct st_sensor_transfer_buffer *tb, | |
80 | struct device *dev, u8 reg_addr, u8 data) | |
81 | { | |
23491b51 DC |
82 | int err; |
83 | ||
84 | struct spi_transfer xfers = { | |
85 | .tx_buf = tb->tx_buf, | |
86 | .bits_per_word = 8, | |
87 | .len = 2, | |
88 | }; | |
89 | ||
90 | mutex_lock(&tb->buf_lock); | |
91 | tb->tx_buf[0] = reg_addr; | |
92 | tb->tx_buf[1] = data; | |
93 | ||
43bb786a | 94 | err = spi_sync_transfer(to_spi_device(dev), &xfers, 1); |
23491b51 DC |
95 | mutex_unlock(&tb->buf_lock); |
96 | ||
97 | return err; | |
98 | } | |
99 | ||
100 | static const struct st_sensor_transfer_function st_sensors_tf_spi = { | |
101 | .read_byte = st_sensors_spi_read_byte, | |
102 | .write_byte = st_sensors_spi_write_byte, | |
103 | .read_multiple_byte = st_sensors_spi_read_multiple_byte, | |
104 | }; | |
105 | ||
106 | void st_sensors_spi_configure(struct iio_dev *indio_dev, | |
107 | struct spi_device *spi, struct st_sensor_data *sdata) | |
108 | { | |
109 | spi_set_drvdata(spi, indio_dev); | |
110 | ||
111 | indio_dev->dev.parent = &spi->dev; | |
112 | indio_dev->name = spi->modalias; | |
113 | ||
114 | sdata->tf = &st_sensors_tf_spi; | |
115 | sdata->get_irq_data_ready = st_sensors_spi_get_irq; | |
116 | } | |
117 | EXPORT_SYMBOL(st_sensors_spi_configure); | |
118 | ||
119 | MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>"); | |
120 | MODULE_DESCRIPTION("STMicroelectronics ST-sensors spi driver"); | |
121 | MODULE_LICENSE("GPL v2"); |