kxsd9.c (84e2f6f9583f195b9851a8f6340bb526749ea609) | kxsd9.c (0427a106a98adf94b53cc88607ceabc2ecebd2cc) |
---|---|
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 9 * published by the Free Software Foundation. 10 * 11 * The i2c interface is very similar, so shouldn't be a problem once 12 * I have a suitable wire made up. 13 * 14 * TODO: Support the motion detector | 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 9 * published by the Free Software Foundation. 10 * 11 * The i2c interface is very similar, so shouldn't be a problem once 12 * I have a suitable wire made up. 13 * 14 * TODO: Support the motion detector |
15 * Uses register address incrementing so could have a 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#include <linux/regmap.h> 25#include <linux/iio/iio.h> 26#include <linux/iio/sysfs.h> | 15 */ 16 17#include <linux/device.h> 18#include <linux/kernel.h> 19#include <linux/sysfs.h> 20#include <linux/slab.h> 21#include <linux/module.h> 22#include <linux/regmap.h> 23#include <linux/iio/iio.h> 24#include <linux/iio/sysfs.h> |
25#include <linux/iio/buffer.h> 26#include <linux/iio/triggered_buffer.h> 27#include <linux/iio/trigger_consumer.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 33#define KXSD9_REG_AUX 0x06 34#define KXSD9_REG_RESET 0x0a 35#define KXSD9_REG_CTRL_C 0x0c 36 37#define KXSD9_FS_MASK 0x03 38 39#define KXSD9_REG_CTRL_B 0x0d 40#define KXSD9_REG_CTRL_A 0x0e 41 42/** 43 * struct kxsd9_state - device related storage | 28 29#include "kxsd9.h" 30 31#define KXSD9_REG_X 0x00 32#define KXSD9_REG_Y 0x02 33#define KXSD9_REG_Z 0x04 34#define KXSD9_REG_AUX 0x06 35#define KXSD9_REG_RESET 0x0a 36#define KXSD9_REG_CTRL_C 0x0c 37 38#define KXSD9_FS_MASK 0x03 39 40#define KXSD9_REG_CTRL_B 0x0d 41#define KXSD9_REG_CTRL_A 0x0e 42 43/** 44 * struct kxsd9_state - device related storage |
45 * @dev: pointer to the parent device |
|
44 * @map: regmap to the device 45 */ 46struct kxsd9_state { | 46 * @map: regmap to the device 47 */ 48struct kxsd9_state { |
49 struct device *dev; |
|
47 struct regmap *map; 48}; 49 50#define KXSD9_SCALE_2G "0.011978" 51#define KXSD9_SCALE_4G "0.023927" 52#define KXSD9_SCALE_6G "0.035934" 53#define KXSD9_SCALE_8G "0.047853" 54 --- 95 unchanged lines hidden (view full) --- 150 *val2 = kxsd9_micro_scales[regval & KXSD9_FS_MASK]; 151 ret = IIO_VAL_INT_PLUS_MICRO; 152 break; 153 } 154 155error_ret: 156 return ret; 157}; | 50 struct regmap *map; 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 --- 95 unchanged lines hidden (view full) --- 153 *val2 = kxsd9_micro_scales[regval & KXSD9_FS_MASK]; 154 ret = IIO_VAL_INT_PLUS_MICRO; 155 break; 156 } 157 158error_ret: 159 return ret; 160}; |
158#define KXSD9_ACCEL_CHAN(axis) \ | 161 162static irqreturn_t kxsd9_trigger_handler(int irq, void *p) 163{ 164 const struct iio_poll_func *pf = p; 165 struct iio_dev *indio_dev = pf->indio_dev; 166 struct kxsd9_state *st = iio_priv(indio_dev); 167 int ret; 168 /* 4 * 16bit values AND timestamp */ 169 __be16 hw_values[8]; 170 171 ret = regmap_bulk_read(st->map, 172 KXSD9_REG_X, 173 &hw_values, 174 8); 175 if (ret) { 176 dev_err(st->dev, 177 "error reading data\n"); 178 return ret; 179 } 180 181 iio_push_to_buffers_with_timestamp(indio_dev, 182 hw_values, 183 iio_get_time_ns(indio_dev)); 184 iio_trigger_notify_done(indio_dev->trig); 185 186 return IRQ_HANDLED; 187} 188 189#define KXSD9_ACCEL_CHAN(axis, index) \ |
159 { \ 160 .type = IIO_ACCEL, \ 161 .modified = 1, \ 162 .channel2 = IIO_MOD_##axis, \ 163 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 164 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ 165 BIT(IIO_CHAN_INFO_OFFSET), \ 166 .address = KXSD9_REG_##axis, \ | 190 { \ 191 .type = IIO_ACCEL, \ 192 .modified = 1, \ 193 .channel2 = IIO_MOD_##axis, \ 194 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 195 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ 196 BIT(IIO_CHAN_INFO_OFFSET), \ 197 .address = KXSD9_REG_##axis, \ |
198 .scan_index = index, \ 199 .scan_type = { \ 200 .sign = 'u', \ 201 .realbits = 12, \ 202 .storagebits = 16, \ 203 .shift = 4, \ 204 .endianness = IIO_BE, \ 205 }, \ |
|
167 } 168 169static const struct iio_chan_spec kxsd9_channels[] = { | 206 } 207 208static const struct iio_chan_spec kxsd9_channels[] = { |
170 KXSD9_ACCEL_CHAN(X), KXSD9_ACCEL_CHAN(Y), KXSD9_ACCEL_CHAN(Z), | 209 KXSD9_ACCEL_CHAN(X, 0), 210 KXSD9_ACCEL_CHAN(Y, 1), 211 KXSD9_ACCEL_CHAN(Z, 2), |
171 { 172 .type = IIO_VOLTAGE, 173 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 174 .indexed = 1, 175 .address = KXSD9_REG_AUX, | 212 { 213 .type = IIO_VOLTAGE, 214 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 215 .indexed = 1, 216 .address = KXSD9_REG_AUX, |
176 } | 217 .scan_index = 3, 218 .scan_type = { 219 .sign = 'u', 220 .realbits = 12, 221 .storagebits = 16, 222 .shift = 4, 223 .endianness = IIO_BE, 224 }, 225 }, 226 IIO_CHAN_SOFT_TIMESTAMP(4), |
177}; 178 179static const struct attribute_group kxsd9_attribute_group = { 180 .attrs = kxsd9_attributes, 181}; 182 183static int kxsd9_power_up(struct kxsd9_state *st) 184{ --- 7 unchanged lines hidden (view full) --- 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 | 227}; 228 229static const struct attribute_group kxsd9_attribute_group = { 230 .attrs = kxsd9_attributes, 231}; 232 233static int kxsd9_power_up(struct kxsd9_state *st) 234{ --- 7 unchanged lines hidden (view full) --- 242 243static const struct iio_info kxsd9_info = { 244 .read_raw = &kxsd9_read_raw, 245 .write_raw = &kxsd9_write_raw, 246 .attrs = &kxsd9_attribute_group, 247 .driver_module = THIS_MODULE, 248}; 249 |
250/* Four channels apart from timestamp, scan mask = 0x0f */ 251static const unsigned long kxsd9_scan_masks[] = { 0xf, 0 }; 252 |
|
200int kxsd9_common_probe(struct device *parent, 201 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); | 253int kxsd9_common_probe(struct device *parent, 254 struct regmap *map, 255 const char *name) 256{ 257 struct iio_dev *indio_dev; 258 struct kxsd9_state *st; 259 int ret; 260 261 indio_dev = devm_iio_device_alloc(parent, sizeof(*st)); 262 if (!indio_dev) 263 return -ENOMEM; 264 265 st = iio_priv(indio_dev); |
266 st->dev = parent; |
|
213 st->map = map; 214 215 indio_dev->channels = kxsd9_channels; 216 indio_dev->num_channels = ARRAY_SIZE(kxsd9_channels); 217 indio_dev->name = name; 218 indio_dev->dev.parent = parent; 219 indio_dev->info = &kxsd9_info; 220 indio_dev->modes = INDIO_DIRECT_MODE; | 267 st->map = map; 268 269 indio_dev->channels = kxsd9_channels; 270 indio_dev->num_channels = ARRAY_SIZE(kxsd9_channels); 271 indio_dev->name = name; 272 indio_dev->dev.parent = parent; 273 indio_dev->info = &kxsd9_info; 274 indio_dev->modes = INDIO_DIRECT_MODE; |
275 indio_dev->available_scan_masks = kxsd9_scan_masks; |
|
221 222 kxsd9_power_up(st); 223 | 276 277 kxsd9_power_up(st); 278 |
279 ret = iio_triggered_buffer_setup(indio_dev, 280 iio_pollfunc_store_time, 281 kxsd9_trigger_handler, 282 NULL); 283 if (ret) { 284 dev_err(parent, "triggered buffer setup failed\n"); 285 return ret; 286 } 287 |
|
224 ret = iio_device_register(indio_dev); 225 if (ret) | 288 ret = iio_device_register(indio_dev); 289 if (ret) |
226 return ret; | 290 goto err_cleanup_buffer; |
227 228 dev_set_drvdata(parent, indio_dev); 229 230 return 0; | 291 292 dev_set_drvdata(parent, indio_dev); 293 294 return 0; |
295 296err_cleanup_buffer: 297 iio_triggered_buffer_cleanup(indio_dev); 298 299 return ret; |
|
231} 232EXPORT_SYMBOL(kxsd9_common_probe); 233 234int kxsd9_common_remove(struct device *parent) 235{ 236 struct iio_dev *indio_dev = dev_get_drvdata(parent); 237 | 300} 301EXPORT_SYMBOL(kxsd9_common_probe); 302 303int kxsd9_common_remove(struct device *parent) 304{ 305 struct iio_dev *indio_dev = dev_get_drvdata(parent); 306 |
307 iio_triggered_buffer_cleanup(indio_dev); |
|
238 iio_device_unregister(indio_dev); 239 240 return 0; 241} 242EXPORT_SYMBOL(kxsd9_common_remove); 243 244MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); 245MODULE_DESCRIPTION("Kionix KXSD9 driver"); 246MODULE_LICENSE("GPL v2"); | 308 iio_device_unregister(indio_dev); 309 310 return 0; 311} 312EXPORT_SYMBOL(kxsd9_common_remove); 313 314MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); 315MODULE_DESCRIPTION("Kionix KXSD9 driver"); 316MODULE_LICENSE("GPL v2"); |