aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2016-09-01 05:44:38 -0400
committerJonathan Cameron <jic23@kernel.org>2016-09-18 06:26:53 -0400
commitbf96f6e80cef4b9a234e8ce81aa2e333ca7ce599 (patch)
treed3861d639b33ec4309fe9114ed1617c8f1ac439e
parent154021a317564a600fb5b8e6eba9a76ca6888310 (diff)
iio: accel: kxsd9: Split out SPI transport
This moves the KXSD9 SPI transport out to its own file and Kconfig entry, so that we will be able to add another transport method. We export the common probe and add a local header file for the functionality shared between the main driver and the transport driver. We make the SPI transport the default for the driver if SPI is available and the KXSD9 driver was selected, so the oldconfig upgrade path will be clear. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r--drivers/iio/accel/Kconfig10
-rw-r--r--drivers/iio/accel/Makefile1
-rw-r--r--drivers/iio/accel/kxsd9-spi.c110
-rw-r--r--drivers/iio/accel/kxsd9.c147
-rw-r--r--drivers/iio/accel/kxsd9.h32
5 files changed, 173 insertions, 127 deletions
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 13b8a18785de..89bc5c5d6fd0 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -119,7 +119,6 @@ config IIO_ST_ACCEL_SPI_3AXIS
119 119
120config KXSD9 120config KXSD9
121 tristate "Kionix KXSD9 Accelerometer Driver" 121 tristate "Kionix KXSD9 Accelerometer Driver"
122 depends on SPI
123 help 122 help
124 Say yes here to build support for the Kionix KXSD9 accelerometer. 123 Say yes here to build support for the Kionix KXSD9 accelerometer.
125 Currently this only supports the device via an SPI interface. 124 Currently this only supports the device via an SPI interface.
@@ -127,6 +126,15 @@ config KXSD9
127 To compile this driver as a module, choose M here: the module 126 To compile this driver as a module, choose M here: the module
128 will be called kxsd9. 127 will be called kxsd9.
129 128
129config KXSD9_SPI
130 tristate "Kionix KXSD9 SPI transport"
131 depends on KXSD9
132 depends on SPI
133 default KXSD9
134 help
135 Say yes here to enable the Kionix KXSD9 accelerometer
136 SPI transport channel.
137
130config KXCJK1013 138config KXCJK1013
131 tristate "Kionix 3-Axis Accelerometer Driver" 139 tristate "Kionix 3-Axis Accelerometer Driver"
132 depends on I2C 140 depends on I2C
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index e974841ec9cf..2fe41d7ffb6e 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_DMARD09) += dmard09.o
13obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o 13obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
14obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o 14obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o
15obj-$(CONFIG_KXSD9) += kxsd9.o 15obj-$(CONFIG_KXSD9) += kxsd9.o
16obj-$(CONFIG_KXSD9_SPI) += kxsd9-spi.o
16 17
17obj-$(CONFIG_MMA7455) += mma7455_core.o 18obj-$(CONFIG_MMA7455) += mma7455_core.o
18obj-$(CONFIG_MMA7455_I2C) += mma7455_i2c.o 19obj-$(CONFIG_MMA7455_I2C) += mma7455_i2c.o
diff --git a/drivers/iio/accel/kxsd9-spi.c b/drivers/iio/accel/kxsd9-spi.c
new file mode 100644
index 000000000000..ec9d00d5340f
--- /dev/null
+++ b/drivers/iio/accel/kxsd9-spi.c
@@ -0,0 +1,110 @@
1#include <linux/device.h>
2#include <linux/kernel.h>
3#include <linux/spi/spi.h>
4#include <linux/module.h>
5#include <linux/slab.h>
6
7#include "kxsd9.h"
8
9#define KXSD9_READ(a) (0x80 | (a))
10#define KXSD9_WRITE(a) (a)
11
12static int kxsd9_spi_readreg(struct kxsd9_transport *tr, u8 address)
13{
14 struct spi_device *spi = tr->trdev;
15
16 return spi_w8r8(spi, KXSD9_READ(address));
17}
18
19static int kxsd9_spi_writereg(struct kxsd9_transport *tr, u8 address, u8 val)
20{
21 struct spi_device *spi = tr->trdev;
22
23 tr->tx[0] = KXSD9_WRITE(address),
24 tr->tx[1] = val;
25 return spi_write(spi, tr->tx, 2);
26}
27
28static int kxsd9_spi_write2(struct kxsd9_transport *tr, u8 b1, u8 b2)
29{
30 struct spi_device *spi = tr->trdev;
31
32 tr->tx[0] = b1;
33 tr->tx[1] = b2;
34 return spi_write(spi, tr->tx, 2);
35}
36
37static int kxsd9_spi_readval(struct kxsd9_transport *tr, u8 address)
38{
39 struct spi_device *spi = tr->trdev;
40 struct spi_transfer xfers[] = {
41 {
42 .bits_per_word = 8,
43 .len = 1,
44 .delay_usecs = 200,
45 .tx_buf = tr->tx,
46 }, {
47 .bits_per_word = 8,
48 .len = 2,
49 .rx_buf = tr->rx,
50 },
51 };
52 int ret;
53
54 tr->tx[0] = KXSD9_READ(address);
55 ret = spi_sync_transfer(spi, xfers, ARRAY_SIZE(xfers));
56 if (!ret)
57 ret = (((u16)(tr->rx[0])) << 8) | (tr->rx[1]);
58 return ret;
59}
60
61static int kxsd9_spi_probe(struct spi_device *spi)
62{
63 struct kxsd9_transport *transport;
64 int ret;
65
66 transport = devm_kzalloc(&spi->dev, sizeof(*transport), GFP_KERNEL);
67 if (!transport)
68 return -ENOMEM;
69
70 transport->trdev = spi;
71 transport->readreg = kxsd9_spi_readreg;
72 transport->writereg = kxsd9_spi_writereg;
73 transport->write2 = kxsd9_spi_write2;
74 transport->readval = kxsd9_spi_readval;
75 spi->mode = SPI_MODE_0;
76 spi_setup(spi);
77
78 ret = kxsd9_common_probe(&spi->dev,
79 transport,
80 spi_get_device_id(spi)->name);
81 if (ret)
82 return ret;
83
84 return 0;
85}
86
87static int kxsd9_spi_remove(struct spi_device *spi)
88{
89 return kxsd9_common_remove(&spi->dev);
90}
91
92static const struct spi_device_id kxsd9_spi_id[] = {
93 {"kxsd9", 0},
94 { },
95};
96MODULE_DEVICE_TABLE(spi, kxsd9_spi_id);
97
98static struct spi_driver kxsd9_spi_driver = {
99 .driver = {
100 .name = "kxsd9",
101 },
102 .probe = kxsd9_spi_probe,
103 .remove = kxsd9_spi_remove,
104 .id_table = kxsd9_spi_id,
105};
106module_spi_driver(kxsd9_spi_driver);
107
108MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
109MODULE_DESCRIPTION("Kionix KXSD9 SPI driver");
110MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c
index 1f9e9a867f34..e2033374bfef 100644
--- a/drivers/iio/accel/kxsd9.c
+++ b/drivers/iio/accel/kxsd9.c
@@ -18,7 +18,6 @@
18 18
19#include <linux/device.h> 19#include <linux/device.h>
20#include <linux/kernel.h> 20#include <linux/kernel.h>
21#include <linux/spi/spi.h>
22#include <linux/sysfs.h> 21#include <linux/sysfs.h>
23#include <linux/slab.h> 22#include <linux/slab.h>
24#include <linux/module.h> 23#include <linux/module.h>
@@ -26,6 +25,8 @@
26#include <linux/iio/iio.h> 25#include <linux/iio/iio.h>
27#include <linux/iio/sysfs.h> 26#include <linux/iio/sysfs.h>
28 27
28#include "kxsd9.h"
29
29#define KXSD9_REG_X 0x00 30#define KXSD9_REG_X 0x00
30#define KXSD9_REG_Y 0x02 31#define KXSD9_REG_Y 0x02
31#define KXSD9_REG_Z 0x04 32#define KXSD9_REG_Z 0x04
@@ -38,32 +39,6 @@
38#define KXSD9_REG_CTRL_B 0x0d 39#define KXSD9_REG_CTRL_B 0x0d
39#define KXSD9_REG_CTRL_A 0x0e 40#define KXSD9_REG_CTRL_A 0x0e
40 41
41#define KXSD9_READ(a) (0x80 | (a))
42#define KXSD9_WRITE(a) (a)
43
44#define KXSD9_STATE_RX_SIZE 2
45#define KXSD9_STATE_TX_SIZE 2
46
47struct kxsd9_transport;
48
49/**
50 * struct kxsd9_transport - transport adapter for SPI or I2C
51 * @trdev: transport device such as SPI or I2C
52 * @write1(): function to write a byte to the device
53 * @write2(): function to write two consecutive bytes to the device
54 * @readval(): function to read a 16bit value from the device
55 * @rx: cache aligned read buffer
56 * @tx: cache aligned write buffer
57 */
58struct kxsd9_transport {
59 void *trdev;
60 int (*write1) (struct kxsd9_transport *tr, u8 byte);
61 int (*write2) (struct kxsd9_transport *tr, u8 b1, u8 b2);
62 int (*readval) (struct kxsd9_transport *tr, u8 address);
63 u8 rx[KXSD9_STATE_RX_SIZE] ____cacheline_aligned;
64 u8 tx[KXSD9_STATE_TX_SIZE];
65};
66
67/** 42/**
68 * struct kxsd9_state - device related storage 43 * struct kxsd9_state - device related storage
69 * @transport: transport for the KXSD9 44 * @transport: transport for the KXSD9
@@ -98,12 +73,13 @@ static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro)
98 return -EINVAL; 73 return -EINVAL;
99 74
100 mutex_lock(&st->buf_lock); 75 mutex_lock(&st->buf_lock);
101 ret = st->transport->write1(st->transport, KXSD9_READ(KXSD9_REG_CTRL_C)); 76 ret = st->transport->readreg(st->transport,
102 if (ret) 77 KXSD9_REG_CTRL_C);
78 if (ret < 0)
103 goto error_ret; 79 goto error_ret;
104 ret = st->transport->write2(st->transport, 80 ret = st->transport->writereg(st->transport,
105 KXSD9_WRITE(KXSD9_REG_CTRL_C), 81 KXSD9_REG_CTRL_C,
106 (ret & ~KXSD9_FS_MASK) | i); 82 (ret & ~KXSD9_FS_MASK) | i);
107error_ret: 83error_ret:
108 mutex_unlock(&st->buf_lock); 84 mutex_unlock(&st->buf_lock);
109 return ret; 85 return ret;
@@ -115,7 +91,9 @@ static int kxsd9_read(struct iio_dev *indio_dev, u8 address)
115 struct kxsd9_state *st = iio_priv(indio_dev); 91 struct kxsd9_state *st = iio_priv(indio_dev);
116 92
117 mutex_lock(&st->buf_lock); 93 mutex_lock(&st->buf_lock);
118 ret = st->transport->readval(st->transport, KXSD9_READ(address)); 94 ret = st->transport->readval(st->transport, address);
95 /* Only 12 bits are valid */
96 ret &= 0xfff0;
119 mutex_unlock(&st->buf_lock); 97 mutex_unlock(&st->buf_lock);
120 return ret; 98 return ret;
121} 99}
@@ -165,8 +143,9 @@ static int kxsd9_read_raw(struct iio_dev *indio_dev,
165 ret = IIO_VAL_INT; 143 ret = IIO_VAL_INT;
166 break; 144 break;
167 case IIO_CHAN_INFO_SCALE: 145 case IIO_CHAN_INFO_SCALE:
168 ret = st->transport->write1(st->transport, KXSD9_READ(KXSD9_REG_CTRL_C)); 146 ret = st->transport->readreg(st->transport,
169 if (ret) 147 KXSD9_REG_CTRL_C);
148 if (ret < 0)
170 goto error_ret; 149 goto error_ret;
171 *val = 0; 150 *val = 0;
172 *val2 = kxsd9_micro_scales[ret & KXSD9_FS_MASK]; 151 *val2 = kxsd9_micro_scales[ret & KXSD9_FS_MASK];
@@ -218,9 +197,9 @@ static const struct iio_info kxsd9_info = {
218 .driver_module = THIS_MODULE, 197 .driver_module = THIS_MODULE,
219}; 198};
220 199
221static int kxsd9_common_probe(struct device *parent, 200int kxsd9_common_probe(struct device *parent,
222 struct kxsd9_transport *transport, 201 struct kxsd9_transport *transport,
223 const char *name) 202 const char *name)
224{ 203{
225 struct iio_dev *indio_dev; 204 struct iio_dev *indio_dev;
226 struct kxsd9_state *st; 205 struct kxsd9_state *st;
@@ -251,8 +230,9 @@ static int kxsd9_common_probe(struct device *parent,
251 230
252 return 0; 231 return 0;
253} 232}
233EXPORT_SYMBOL(kxsd9_common_probe);
254 234
255static int kxsd9_common_remove(struct device *parent) 235int kxsd9_common_remove(struct device *parent)
256{ 236{
257 struct iio_dev *indio_dev = dev_get_drvdata(parent); 237 struct iio_dev *indio_dev = dev_get_drvdata(parent);
258 238
@@ -260,93 +240,8 @@ static int kxsd9_common_remove(struct device *parent)
260 240
261 return 0; 241 return 0;
262} 242}
263 243EXPORT_SYMBOL(kxsd9_common_remove);
264static int kxsd9_spi_write1(struct kxsd9_transport *tr, u8 byte)
265{
266 struct spi_device *spi = tr->trdev;
267
268 return spi_w8r8(spi, byte);
269}
270
271static int kxsd9_spi_write2(struct kxsd9_transport *tr, u8 b1, u8 b2)
272{
273 struct spi_device *spi = tr->trdev;
274
275 tr->tx[0] = b1;
276 tr->tx[1] = b2;
277 return spi_write(spi, tr->tx, 2);
278}
279
280static int kxsd9_spi_readval(struct kxsd9_transport *tr, u8 address)
281{
282 struct spi_device *spi = tr->trdev;
283 struct spi_transfer xfers[] = {
284 {
285 .bits_per_word = 8,
286 .len = 1,
287 .delay_usecs = 200,
288 .tx_buf = tr->tx,
289 }, {
290 .bits_per_word = 8,
291 .len = 2,
292 .rx_buf = tr->rx,
293 },
294 };
295 int ret;
296
297 tr->tx[0] = address;
298 ret = spi_sync_transfer(spi, xfers, ARRAY_SIZE(xfers));
299 if (!ret)
300 ret = (((u16)(tr->rx[0])) << 8) | (tr->rx[1] & 0xF0);
301 return ret;
302}
303
304static int kxsd9_spi_probe(struct spi_device *spi)
305{
306 struct kxsd9_transport *transport;
307 int ret;
308
309 transport = devm_kzalloc(&spi->dev, sizeof(*transport), GFP_KERNEL);
310 if (!transport)
311 return -ENOMEM;
312
313 transport->trdev = spi;
314 transport->write1 = kxsd9_spi_write1;
315 transport->write2 = kxsd9_spi_write2;
316 transport->readval = kxsd9_spi_readval;
317 spi->mode = SPI_MODE_0;
318 spi_setup(spi);
319
320 ret = kxsd9_common_probe(&spi->dev,
321 transport,
322 spi_get_device_id(spi)->name);
323 if (ret)
324 return ret;
325
326 return 0;
327}
328
329static int kxsd9_spi_remove(struct spi_device *spi)
330{
331 return kxsd9_common_remove(&spi->dev);
332}
333
334static const struct spi_device_id kxsd9_spi_id[] = {
335 {"kxsd9", 0},
336 { },
337};
338MODULE_DEVICE_TABLE(spi, kxsd9_spi_id);
339
340static struct spi_driver kxsd9_spi_driver = {
341 .driver = {
342 .name = "kxsd9",
343 },
344 .probe = kxsd9_spi_probe,
345 .remove = kxsd9_spi_remove,
346 .id_table = kxsd9_spi_id,
347};
348module_spi_driver(kxsd9_spi_driver);
349 244
350MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); 245MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
351MODULE_DESCRIPTION("Kionix KXSD9 SPI driver"); 246MODULE_DESCRIPTION("Kionix KXSD9 driver");
352MODULE_LICENSE("GPL v2"); 247MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/accel/kxsd9.h b/drivers/iio/accel/kxsd9.h
new file mode 100644
index 000000000000..28845c3440e9
--- /dev/null
+++ b/drivers/iio/accel/kxsd9.h
@@ -0,0 +1,32 @@
1#include <linux/device.h>
2#include <linux/kernel.h>
3
4#define KXSD9_STATE_RX_SIZE 2
5#define KXSD9_STATE_TX_SIZE 2
6
7struct kxsd9_transport;
8
9/**
10 * struct kxsd9_transport - transport adapter for SPI or I2C
11 * @trdev: transport device such as SPI or I2C
12 * @readreg(): function to read a byte from an address in the device
13 * @writereg(): function to write a byte to an address in the device
14 * @write2(): function to write two consecutive bytes to the device
15 * @readval(): function to read a 16bit value from the device
16 * @rx: cache aligned read buffer
17 * @tx: cache aligned write buffer
18 */
19struct kxsd9_transport {
20 void *trdev;
21 int (*readreg) (struct kxsd9_transport *tr, u8 address);
22 int (*writereg) (struct kxsd9_transport *tr, u8 address, u8 val);
23 int (*write2) (struct kxsd9_transport *tr, u8 b1, u8 b2);
24 int (*readval) (struct kxsd9_transport *tr, u8 address);
25 u8 rx[KXSD9_STATE_RX_SIZE] ____cacheline_aligned;
26 u8 tx[KXSD9_STATE_TX_SIZE];
27};
28
29int kxsd9_common_probe(struct device *parent,
30 struct kxsd9_transport *transport,
31 const char *name);
32int kxsd9_common_remove(struct device *parent);