kxsd9.c (ab04f734b08a404550ba5f8391307bad2145acff) kxsd9.c (0d1fb2d52d8b4a1124cb2db7d22c4131ad5805cf)
1/*
2 * kxsd9.c simple support for the Kionix KXSD9 3D
3 * accelerometer.
4 *
5 * Copyright (c) 2008-2009 Jonathan Cameron <jic23@kernel.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as

--- 7 unchanged lines hidden (view full) ---

16 * heavily optimized ring buffer access function.
17 */
18
19#include <linux/device.h>
20#include <linux/kernel.h>
21#include <linux/sysfs.h>
22#include <linux/slab.h>
23#include <linux/module.h>
1/*
2 * kxsd9.c simple support for the Kionix KXSD9 3D
3 * accelerometer.
4 *
5 * Copyright (c) 2008-2009 Jonathan Cameron <jic23@kernel.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as

--- 7 unchanged lines hidden (view full) ---

16 * heavily optimized ring buffer access function.
17 */
18
19#include <linux/device.h>
20#include <linux/kernel.h>
21#include <linux/sysfs.h>
22#include <linux/slab.h>
23#include <linux/module.h>
24
24#include <linux/regmap.h>
25#include <linux/iio/iio.h>
26#include <linux/iio/sysfs.h>
27
28#include "kxsd9.h"
29
30#define KXSD9_REG_X 0x00
31#define KXSD9_REG_Y 0x02
32#define KXSD9_REG_Z 0x04

--- 8 unchanged lines hidden (view full) ---

41
42/**
43 * struct kxsd9_state - device related storage
44 * @transport: transport for the KXSD9
45 * @buf_lock: protect the rx and tx buffers.
46 * @us: spi device
47 **/
48struct kxsd9_state {
25#include <linux/iio/iio.h>
26#include <linux/iio/sysfs.h>
27
28#include "kxsd9.h"
29
30#define KXSD9_REG_X 0x00
31#define KXSD9_REG_Y 0x02
32#define KXSD9_REG_Z 0x04

--- 8 unchanged lines hidden (view full) ---

41
42/**
43 * struct kxsd9_state - device related storage
44 * @transport: transport for the KXSD9
45 * @buf_lock: protect the rx and tx buffers.
46 * @us: spi device
47 **/
48struct kxsd9_state {
49 struct kxsd9_transport *transport;
49 struct regmap *map;
50 struct mutex buf_lock;
51};
52
53#define KXSD9_SCALE_2G "0.011978"
54#define KXSD9_SCALE_4G "0.023927"
55#define KXSD9_SCALE_6G "0.035934"
56#define KXSD9_SCALE_8G "0.047853"
57
58/* reverse order */
59static const int kxsd9_micro_scales[4] = { 47853, 35934, 23927, 11978 };
60
61static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro)
62{
63 int ret, i;
64 struct kxsd9_state *st = iio_priv(indio_dev);
65 bool foundit = false;
50 struct mutex buf_lock;
51};
52
53#define KXSD9_SCALE_2G "0.011978"
54#define KXSD9_SCALE_4G "0.023927"
55#define KXSD9_SCALE_6G "0.035934"
56#define KXSD9_SCALE_8G "0.047853"
57
58/* reverse order */
59static const int kxsd9_micro_scales[4] = { 47853, 35934, 23927, 11978 };
60
61static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro)
62{
63 int ret, i;
64 struct kxsd9_state *st = iio_priv(indio_dev);
65 bool foundit = false;
66 unsigned int val;
66
67 for (i = 0; i < 4; i++)
68 if (micro == kxsd9_micro_scales[i]) {
69 foundit = true;
70 break;
71 }
72 if (!foundit)
73 return -EINVAL;
74
75 mutex_lock(&st->buf_lock);
67
68 for (i = 0; i < 4; i++)
69 if (micro == kxsd9_micro_scales[i]) {
70 foundit = true;
71 break;
72 }
73 if (!foundit)
74 return -EINVAL;
75
76 mutex_lock(&st->buf_lock);
76 ret = st->transport->readreg(st->transport,
77 KXSD9_REG_CTRL_C);
77 ret = regmap_read(st->map,
78 KXSD9_REG_CTRL_C,
79 &val);
78 if (ret < 0)
79 goto error_ret;
80 if (ret < 0)
81 goto error_ret;
80 ret = st->transport->writereg(st->transport,
81 KXSD9_REG_CTRL_C,
82 (ret & ~KXSD9_FS_MASK) | i);
82 ret = regmap_write(st->map,
83 KXSD9_REG_CTRL_C,
84 (val & ~KXSD9_FS_MASK) | i);
83error_ret:
84 mutex_unlock(&st->buf_lock);
85 return ret;
86}
87
88static int kxsd9_read(struct iio_dev *indio_dev, u8 address)
89{
90 int ret;
91 struct kxsd9_state *st = iio_priv(indio_dev);
85error_ret:
86 mutex_unlock(&st->buf_lock);
87 return ret;
88}
89
90static int kxsd9_read(struct iio_dev *indio_dev, u8 address)
91{
92 int ret;
93 struct kxsd9_state *st = iio_priv(indio_dev);
94 __be16 raw_val;
92
93 mutex_lock(&st->buf_lock);
95
96 mutex_lock(&st->buf_lock);
94 ret = st->transport->readval(st->transport, address);
97 ret = regmap_bulk_read(st->map, address, &raw_val, sizeof(raw_val));
98 if (ret)
99 goto out_fail_read;
95 /* Only 12 bits are valid */
100 /* Only 12 bits are valid */
96 ret &= 0xfff0;
101 ret = be16_to_cpu(raw_val) & 0xfff0;
102out_fail_read:
97 mutex_unlock(&st->buf_lock);
98 return ret;
99}
100
101static IIO_CONST_ATTR(accel_scale_available,
102 KXSD9_SCALE_2G " "
103 KXSD9_SCALE_4G " "
104 KXSD9_SCALE_6G " "

--- 23 unchanged lines hidden (view full) ---

128}
129
130static int kxsd9_read_raw(struct iio_dev *indio_dev,
131 struct iio_chan_spec const *chan,
132 int *val, int *val2, long mask)
133{
134 int ret = -EINVAL;
135 struct kxsd9_state *st = iio_priv(indio_dev);
103 mutex_unlock(&st->buf_lock);
104 return ret;
105}
106
107static IIO_CONST_ATTR(accel_scale_available,
108 KXSD9_SCALE_2G " "
109 KXSD9_SCALE_4G " "
110 KXSD9_SCALE_6G " "

--- 23 unchanged lines hidden (view full) ---

134}
135
136static int kxsd9_read_raw(struct iio_dev *indio_dev,
137 struct iio_chan_spec const *chan,
138 int *val, int *val2, long mask)
139{
140 int ret = -EINVAL;
141 struct kxsd9_state *st = iio_priv(indio_dev);
142 unsigned int regval;
136
137 switch (mask) {
138 case IIO_CHAN_INFO_RAW:
139 ret = kxsd9_read(indio_dev, chan->address);
140 if (ret < 0)
141 goto error_ret;
142 *val = ret;
143 ret = IIO_VAL_INT;
144 break;
145 case IIO_CHAN_INFO_SCALE:
143
144 switch (mask) {
145 case IIO_CHAN_INFO_RAW:
146 ret = kxsd9_read(indio_dev, chan->address);
147 if (ret < 0)
148 goto error_ret;
149 *val = ret;
150 ret = IIO_VAL_INT;
151 break;
152 case IIO_CHAN_INFO_SCALE:
146 ret = st->transport->readreg(st->transport,
147 KXSD9_REG_CTRL_C);
153 ret = regmap_read(st->map,
154 KXSD9_REG_CTRL_C,
155 &regval);
148 if (ret < 0)
149 goto error_ret;
150 *val = 0;
156 if (ret < 0)
157 goto error_ret;
158 *val = 0;
151 *val2 = kxsd9_micro_scales[ret & KXSD9_FS_MASK];
159 *val2 = kxsd9_micro_scales[regval & KXSD9_FS_MASK];
152 ret = IIO_VAL_INT_PLUS_MICRO;
153 break;
154 }
155
156error_ret:
157 return ret;
158};
159#define KXSD9_ACCEL_CHAN(axis) \

--- 19 unchanged lines hidden (view full) ---

179static const struct attribute_group kxsd9_attribute_group = {
180 .attrs = kxsd9_attributes,
181};
182
183static int kxsd9_power_up(struct kxsd9_state *st)
184{
185 int ret;
186
160 ret = IIO_VAL_INT_PLUS_MICRO;
161 break;
162 }
163
164error_ret:
165 return ret;
166};
167#define KXSD9_ACCEL_CHAN(axis) \

--- 19 unchanged lines hidden (view full) ---

187static const struct attribute_group kxsd9_attribute_group = {
188 .attrs = kxsd9_attributes,
189};
190
191static int kxsd9_power_up(struct kxsd9_state *st)
192{
193 int ret;
194
187 ret = st->transport->writereg(st->transport, KXSD9_REG_CTRL_B, 0x40);
195 ret = regmap_write(st->map, KXSD9_REG_CTRL_B, 0x40);
188 if (ret)
189 return ret;
196 if (ret)
197 return ret;
190 return st->transport->writereg(st->transport, KXSD9_REG_CTRL_C, 0x9b);
198 return regmap_write(st->map, KXSD9_REG_CTRL_C, 0x9b);
191};
192
193static const struct iio_info kxsd9_info = {
194 .read_raw = &kxsd9_read_raw,
195 .write_raw = &kxsd9_write_raw,
196 .attrs = &kxsd9_attribute_group,
197 .driver_module = THIS_MODULE,
198};
199
200int kxsd9_common_probe(struct device *parent,
199};
200
201static const struct iio_info kxsd9_info = {
202 .read_raw = &kxsd9_read_raw,
203 .write_raw = &kxsd9_write_raw,
204 .attrs = &kxsd9_attribute_group,
205 .driver_module = THIS_MODULE,
206};
207
208int kxsd9_common_probe(struct device *parent,
201 struct kxsd9_transport *transport,
209 struct regmap *map,
202 const char *name)
203{
204 struct iio_dev *indio_dev;
205 struct kxsd9_state *st;
206 int ret;
207
208 indio_dev = devm_iio_device_alloc(parent, sizeof(*st));
209 if (!indio_dev)
210 return -ENOMEM;
211
212 st = iio_priv(indio_dev);
210 const char *name)
211{
212 struct iio_dev *indio_dev;
213 struct kxsd9_state *st;
214 int ret;
215
216 indio_dev = devm_iio_device_alloc(parent, sizeof(*st));
217 if (!indio_dev)
218 return -ENOMEM;
219
220 st = iio_priv(indio_dev);
213 st->transport = transport;
221 st->map = map;
214
215 mutex_init(&st->buf_lock);
216 indio_dev->channels = kxsd9_channels;
217 indio_dev->num_channels = ARRAY_SIZE(kxsd9_channels);
218 indio_dev->name = name;
219 indio_dev->dev.parent = parent;
220 indio_dev->info = &kxsd9_info;
221 indio_dev->modes = INDIO_DIRECT_MODE;

--- 26 unchanged lines hidden ---
222
223 mutex_init(&st->buf_lock);
224 indio_dev->channels = kxsd9_channels;
225 indio_dev->num_channels = ARRAY_SIZE(kxsd9_channels);
226 indio_dev->name = name;
227 indio_dev->dev.parent = parent;
228 indio_dev->info = &kxsd9_info;
229 indio_dev->modes = INDIO_DIRECT_MODE;

--- 26 unchanged lines hidden ---