lis3: add skeletons for interrupt handlers
[deliverable/linux.git] / drivers / hwmon / lis3lv02d.c
1 /*
2 * lis3lv02d.c - ST LIS3LV02DL accelerometer driver
3 *
4 * Copyright (C) 2007-2008 Yan Burman
5 * Copyright (C) 2008 Eric Piel
6 * Copyright (C) 2008-2009 Pavel Machek
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23 #include <linux/kernel.h>
24 #include <linux/init.h>
25 #include <linux/dmi.h>
26 #include <linux/module.h>
27 #include <linux/types.h>
28 #include <linux/platform_device.h>
29 #include <linux/interrupt.h>
30 #include <linux/input-polldev.h>
31 #include <linux/delay.h>
32 #include <linux/wait.h>
33 #include <linux/poll.h>
34 #include <linux/freezer.h>
35 #include <linux/uaccess.h>
36 #include <linux/miscdevice.h>
37 #include <asm/atomic.h>
38 #include "lis3lv02d.h"
39
40 #define DRIVER_NAME "lis3lv02d"
41
42 /* joystick device poll interval in milliseconds */
43 #define MDPS_POLL_INTERVAL 50
44 /*
45 * The sensor can also generate interrupts (DRDY) but it's pretty pointless
46 * because they are generated even if the data do not change. So it's better
47 * to keep the interrupt for the free-fall event. The values are updated at
48 * 40Hz (at the lowest frequency), but as it can be pretty time consuming on
49 * some low processor, we poll the sensor only at 20Hz... enough for the
50 * joystick.
51 */
52
53 #define LIS3_PWRON_DELAY_WAI_12B (5000)
54 #define LIS3_PWRON_DELAY_WAI_8B (3000)
55
56 /*
57 * LIS3LV02D spec says 1024 LSBs corresponds 1 G -> 1LSB is 1000/1024 mG
58 * LIS302D spec says: 18 mG / digit
59 * LIS3_ACCURACY is used to increase accuracy of the intermediate
60 * calculation results.
61 */
62 #define LIS3_ACCURACY 1024
63 /* Sensitivity values for -2G +2G scale */
64 #define LIS3_SENSITIVITY_12B ((LIS3_ACCURACY * 1000) / 1024)
65 #define LIS3_SENSITIVITY_8B (18 * LIS3_ACCURACY)
66
67 #define LIS3_DEFAULT_FUZZ 3
68 #define LIS3_DEFAULT_FLAT 3
69
70 struct lis3lv02d lis3_dev = {
71 .misc_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lis3_dev.misc_wait),
72 };
73
74 EXPORT_SYMBOL_GPL(lis3_dev);
75
76 static s16 lis3lv02d_read_8(struct lis3lv02d *lis3, int reg)
77 {
78 s8 lo;
79 if (lis3->read(lis3, reg, &lo) < 0)
80 return 0;
81
82 return lo;
83 }
84
85 static s16 lis3lv02d_read_12(struct lis3lv02d *lis3, int reg)
86 {
87 u8 lo, hi;
88
89 lis3->read(lis3, reg - 1, &lo);
90 lis3->read(lis3, reg, &hi);
91 /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */
92 return (s16)((hi << 8) | lo);
93 }
94
95 /**
96 * lis3lv02d_get_axis - For the given axis, give the value converted
97 * @axis: 1,2,3 - can also be negative
98 * @hw_values: raw values returned by the hardware
99 *
100 * Returns the converted value.
101 */
102 static inline int lis3lv02d_get_axis(s8 axis, int hw_values[3])
103 {
104 if (axis > 0)
105 return hw_values[axis - 1];
106 else
107 return -hw_values[-axis - 1];
108 }
109
110 /**
111 * lis3lv02d_get_xyz - Get X, Y and Z axis values from the accelerometer
112 * @lis3: pointer to the device struct
113 * @x: where to store the X axis value
114 * @y: where to store the Y axis value
115 * @z: where to store the Z axis value
116 *
117 * Note that 40Hz input device can eat up about 10% CPU at 800MHZ
118 */
119 static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
120 {
121 int position[3];
122 int i;
123
124 mutex_lock(&lis3->mutex);
125 position[0] = lis3->read_data(lis3, OUTX);
126 position[1] = lis3->read_data(lis3, OUTY);
127 position[2] = lis3->read_data(lis3, OUTZ);
128 mutex_unlock(&lis3->mutex);
129
130 for (i = 0; i < 3; i++)
131 position[i] = (position[i] * lis3->scale) / LIS3_ACCURACY;
132
133 *x = lis3lv02d_get_axis(lis3->ac.x, position);
134 *y = lis3lv02d_get_axis(lis3->ac.y, position);
135 *z = lis3lv02d_get_axis(lis3->ac.z, position);
136 }
137
138 /* conversion btw sampling rate and the register values */
139 static int lis3_12_rates[4] = {40, 160, 640, 2560};
140 static int lis3_8_rates[2] = {100, 400};
141
142 /* ODR is Output Data Rate */
143 static int lis3lv02d_get_odr(void)
144 {
145 u8 ctrl;
146 int shift;
147
148 lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
149 ctrl &= lis3_dev.odr_mask;
150 shift = ffs(lis3_dev.odr_mask) - 1;
151 return lis3_dev.odrs[(ctrl >> shift)];
152 }
153
154 static int lis3lv02d_set_odr(int rate)
155 {
156 u8 ctrl;
157 int i, len, shift;
158
159 lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
160 ctrl &= ~lis3_dev.odr_mask;
161 len = 1 << hweight_long(lis3_dev.odr_mask); /* # of possible values */
162 shift = ffs(lis3_dev.odr_mask) - 1;
163
164 for (i = 0; i < len; i++)
165 if (lis3_dev.odrs[i] == rate) {
166 lis3_dev.write(&lis3_dev, CTRL_REG1,
167 ctrl | (i << shift));
168 return 0;
169 }
170 return -EINVAL;
171 }
172
173 static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
174 {
175 u8 reg;
176 s16 x, y, z;
177 u8 selftest;
178 int ret;
179
180 mutex_lock(&lis3->mutex);
181 if (lis3_dev.whoami == WAI_12B)
182 selftest = CTRL1_ST;
183 else
184 selftest = CTRL1_STP;
185
186 lis3->read(lis3, CTRL_REG1, &reg);
187 lis3->write(lis3, CTRL_REG1, (reg | selftest));
188 msleep(lis3->pwron_delay / lis3lv02d_get_odr());
189
190 /* Read directly to avoid axis remap */
191 x = lis3->read_data(lis3, OUTX);
192 y = lis3->read_data(lis3, OUTY);
193 z = lis3->read_data(lis3, OUTZ);
194
195 /* back to normal settings */
196 lis3->write(lis3, CTRL_REG1, reg);
197 msleep(lis3->pwron_delay / lis3lv02d_get_odr());
198
199 results[0] = x - lis3->read_data(lis3, OUTX);
200 results[1] = y - lis3->read_data(lis3, OUTY);
201 results[2] = z - lis3->read_data(lis3, OUTZ);
202
203 ret = 0;
204 if (lis3->pdata) {
205 int i;
206 for (i = 0; i < 3; i++) {
207 /* Check against selftest acceptance limits */
208 if ((results[i] < lis3->pdata->st_min_limits[i]) ||
209 (results[i] > lis3->pdata->st_max_limits[i])) {
210 ret = -EIO;
211 goto fail;
212 }
213 }
214 }
215
216 /* test passed */
217 fail:
218 mutex_unlock(&lis3->mutex);
219 return ret;
220 }
221
222 void lis3lv02d_poweroff(struct lis3lv02d *lis3)
223 {
224 /* disable X,Y,Z axis and power down */
225 lis3->write(lis3, CTRL_REG1, 0x00);
226 }
227 EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
228
229 void lis3lv02d_poweron(struct lis3lv02d *lis3)
230 {
231 u8 reg;
232
233 lis3->init(lis3);
234
235 /* LIS3 power on delay is quite long */
236 msleep(lis3->pwron_delay / lis3lv02d_get_odr());
237
238 /*
239 * Common configuration
240 * BDU: (12 bits sensors only) LSB and MSB values are not updated until
241 * both have been read. So the value read will always be correct.
242 */
243 if (lis3->whoami == WAI_12B) {
244 lis3->read(lis3, CTRL_REG2, &reg);
245 reg |= CTRL2_BDU;
246 lis3->write(lis3, CTRL_REG2, reg);
247 }
248 }
249 EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
250
251
252 static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
253 {
254 if (!test_bit(0, &lis3_dev.misc_opened))
255 goto out;
256
257 /*
258 * Be careful: on some HP laptops the bios force DD when on battery and
259 * the lid is closed. This leads to interrupts as soon as a little move
260 * is done.
261 */
262 atomic_inc(&lis3_dev.count);
263
264 wake_up_interruptible(&lis3_dev.misc_wait);
265 kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN);
266 out:
267 if (lis3_dev.whoami == WAI_8B && lis3_dev.idev &&
268 lis3_dev.idev->input->users)
269 return IRQ_WAKE_THREAD;
270 return IRQ_HANDLED;
271 }
272
273 static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
274 {
275 return IRQ_HANDLED;
276 }
277
278 static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
279 {
280 return IRQ_HANDLED;
281 }
282
283 static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
284 {
285 if (test_and_set_bit(0, &lis3_dev.misc_opened))
286 return -EBUSY; /* already open */
287
288 atomic_set(&lis3_dev.count, 0);
289 return 0;
290 }
291
292 static int lis3lv02d_misc_release(struct inode *inode, struct file *file)
293 {
294 fasync_helper(-1, file, 0, &lis3_dev.async_queue);
295 clear_bit(0, &lis3_dev.misc_opened); /* release the device */
296 return 0;
297 }
298
299 static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf,
300 size_t count, loff_t *pos)
301 {
302 DECLARE_WAITQUEUE(wait, current);
303 u32 data;
304 unsigned char byte_data;
305 ssize_t retval = 1;
306
307 if (count < 1)
308 return -EINVAL;
309
310 add_wait_queue(&lis3_dev.misc_wait, &wait);
311 while (true) {
312 set_current_state(TASK_INTERRUPTIBLE);
313 data = atomic_xchg(&lis3_dev.count, 0);
314 if (data)
315 break;
316
317 if (file->f_flags & O_NONBLOCK) {
318 retval = -EAGAIN;
319 goto out;
320 }
321
322 if (signal_pending(current)) {
323 retval = -ERESTARTSYS;
324 goto out;
325 }
326
327 schedule();
328 }
329
330 if (data < 255)
331 byte_data = data;
332 else
333 byte_data = 255;
334
335 /* make sure we are not going into copy_to_user() with
336 * TASK_INTERRUPTIBLE state */
337 set_current_state(TASK_RUNNING);
338 if (copy_to_user(buf, &byte_data, sizeof(byte_data)))
339 retval = -EFAULT;
340
341 out:
342 __set_current_state(TASK_RUNNING);
343 remove_wait_queue(&lis3_dev.misc_wait, &wait);
344
345 return retval;
346 }
347
348 static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait)
349 {
350 poll_wait(file, &lis3_dev.misc_wait, wait);
351 if (atomic_read(&lis3_dev.count))
352 return POLLIN | POLLRDNORM;
353 return 0;
354 }
355
356 static int lis3lv02d_misc_fasync(int fd, struct file *file, int on)
357 {
358 return fasync_helper(fd, file, on, &lis3_dev.async_queue);
359 }
360
361 static const struct file_operations lis3lv02d_misc_fops = {
362 .owner = THIS_MODULE,
363 .llseek = no_llseek,
364 .read = lis3lv02d_misc_read,
365 .open = lis3lv02d_misc_open,
366 .release = lis3lv02d_misc_release,
367 .poll = lis3lv02d_misc_poll,
368 .fasync = lis3lv02d_misc_fasync,
369 };
370
371 static struct miscdevice lis3lv02d_misc_device = {
372 .minor = MISC_DYNAMIC_MINOR,
373 .name = "freefall",
374 .fops = &lis3lv02d_misc_fops,
375 };
376
377 static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
378 {
379 int x, y, z;
380
381 lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
382 input_report_abs(pidev->input, ABS_X, x);
383 input_report_abs(pidev->input, ABS_Y, y);
384 input_report_abs(pidev->input, ABS_Z, z);
385 input_sync(pidev->input);
386 }
387
388 int lis3lv02d_joystick_enable(void)
389 {
390 struct input_dev *input_dev;
391 int err;
392 int max_val, fuzz, flat;
393
394 if (lis3_dev.idev)
395 return -EINVAL;
396
397 lis3_dev.idev = input_allocate_polled_device();
398 if (!lis3_dev.idev)
399 return -ENOMEM;
400
401 lis3_dev.idev->poll = lis3lv02d_joystick_poll;
402 lis3_dev.idev->poll_interval = MDPS_POLL_INTERVAL;
403 input_dev = lis3_dev.idev->input;
404
405 input_dev->name = "ST LIS3LV02DL Accelerometer";
406 input_dev->phys = DRIVER_NAME "/input0";
407 input_dev->id.bustype = BUS_HOST;
408 input_dev->id.vendor = 0;
409 input_dev->dev.parent = &lis3_dev.pdev->dev;
410
411 set_bit(EV_ABS, input_dev->evbit);
412 max_val = (lis3_dev.mdps_max_val * lis3_dev.scale) / LIS3_ACCURACY;
413 fuzz = (LIS3_DEFAULT_FUZZ * lis3_dev.scale) / LIS3_ACCURACY;
414 flat = (LIS3_DEFAULT_FLAT * lis3_dev.scale) / LIS3_ACCURACY;
415 input_set_abs_params(input_dev, ABS_X, -max_val, max_val, fuzz, flat);
416 input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat);
417 input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat);
418
419 err = input_register_polled_device(lis3_dev.idev);
420 if (err) {
421 input_free_polled_device(lis3_dev.idev);
422 lis3_dev.idev = NULL;
423 }
424
425 return err;
426 }
427 EXPORT_SYMBOL_GPL(lis3lv02d_joystick_enable);
428
429 void lis3lv02d_joystick_disable(void)
430 {
431 if (lis3_dev.irq)
432 free_irq(lis3_dev.irq, &lis3_dev);
433 if (lis3_dev.pdata && lis3_dev.pdata->irq2)
434 free_irq(lis3_dev.pdata->irq2, &lis3_dev);
435
436 if (!lis3_dev.idev)
437 return;
438
439 if (lis3_dev.irq)
440 misc_deregister(&lis3lv02d_misc_device);
441 input_unregister_polled_device(lis3_dev.idev);
442 input_free_polled_device(lis3_dev.idev);
443 lis3_dev.idev = NULL;
444 }
445 EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable);
446
447 /* Sysfs stuff */
448 static ssize_t lis3lv02d_selftest_show(struct device *dev,
449 struct device_attribute *attr, char *buf)
450 {
451 int result;
452 s16 values[3];
453
454 result = lis3lv02d_selftest(&lis3_dev, values);
455 return sprintf(buf, "%s %d %d %d\n", result == 0 ? "OK" : "FAIL",
456 values[0], values[1], values[2]);
457 }
458
459 static ssize_t lis3lv02d_position_show(struct device *dev,
460 struct device_attribute *attr, char *buf)
461 {
462 int x, y, z;
463
464 lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
465 return sprintf(buf, "(%d,%d,%d)\n", x, y, z);
466 }
467
468 static ssize_t lis3lv02d_rate_show(struct device *dev,
469 struct device_attribute *attr, char *buf)
470 {
471 return sprintf(buf, "%d\n", lis3lv02d_get_odr());
472 }
473
474 static ssize_t lis3lv02d_rate_set(struct device *dev,
475 struct device_attribute *attr, const char *buf,
476 size_t count)
477 {
478 unsigned long rate;
479
480 if (strict_strtoul(buf, 0, &rate))
481 return -EINVAL;
482
483 if (lis3lv02d_set_odr(rate))
484 return -EINVAL;
485
486 return count;
487 }
488
489 static DEVICE_ATTR(selftest, S_IRUSR, lis3lv02d_selftest_show, NULL);
490 static DEVICE_ATTR(position, S_IRUGO, lis3lv02d_position_show, NULL);
491 static DEVICE_ATTR(rate, S_IRUGO | S_IWUSR, lis3lv02d_rate_show,
492 lis3lv02d_rate_set);
493
494 static struct attribute *lis3lv02d_attributes[] = {
495 &dev_attr_selftest.attr,
496 &dev_attr_position.attr,
497 &dev_attr_rate.attr,
498 NULL
499 };
500
501 static struct attribute_group lis3lv02d_attribute_group = {
502 .attrs = lis3lv02d_attributes
503 };
504
505
506 static int lis3lv02d_add_fs(struct lis3lv02d *lis3)
507 {
508 lis3->pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
509 if (IS_ERR(lis3->pdev))
510 return PTR_ERR(lis3->pdev);
511
512 return sysfs_create_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
513 }
514
515 int lis3lv02d_remove_fs(struct lis3lv02d *lis3)
516 {
517 sysfs_remove_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
518 platform_device_unregister(lis3->pdev);
519 return 0;
520 }
521 EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
522
523 static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
524 struct lis3lv02d_platform_data *p)
525 {
526 int err;
527 int ctrl2 = p->hipass_ctrl;
528
529 if (p->click_flags) {
530 dev->write(dev, CLICK_CFG, p->click_flags);
531 dev->write(dev, CLICK_TIMELIMIT, p->click_time_limit);
532 dev->write(dev, CLICK_LATENCY, p->click_latency);
533 dev->write(dev, CLICK_WINDOW, p->click_window);
534 dev->write(dev, CLICK_THSZ, p->click_thresh_z & 0xf);
535 dev->write(dev, CLICK_THSY_X,
536 (p->click_thresh_x & 0xf) |
537 (p->click_thresh_y << 4));
538 }
539
540 if (p->wakeup_flags) {
541 dev->write(dev, FF_WU_CFG_1, p->wakeup_flags);
542 dev->write(dev, FF_WU_THS_1, p->wakeup_thresh & 0x7f);
543 /* default to 2.5ms for now */
544 dev->write(dev, FF_WU_DURATION_1, 1);
545 ctrl2 ^= HP_FF_WU1; /* Xor to keep compatible with old pdata*/
546 }
547
548 if (p->wakeup_flags2) {
549 dev->write(dev, FF_WU_CFG_2, p->wakeup_flags2);
550 dev->write(dev, FF_WU_THS_2, p->wakeup_thresh2 & 0x7f);
551 /* default to 2.5ms for now */
552 dev->write(dev, FF_WU_DURATION_2, 1);
553 ctrl2 ^= HP_FF_WU2; /* Xor to keep compatible with old pdata*/
554 }
555 /* Configure hipass filters */
556 dev->write(dev, CTRL_REG2, ctrl2);
557
558 if (p->irq2) {
559 err = request_threaded_irq(p->irq2,
560 NULL,
561 lis302dl_interrupt_thread2_8b,
562 IRQF_TRIGGER_RISING |
563 IRQF_ONESHOT,
564 DRIVER_NAME, &lis3_dev);
565 if (err < 0)
566 printk(KERN_ERR DRIVER_NAME
567 "No second IRQ. Limited functionality\n");
568 }
569 }
570
571 /*
572 * Initialise the accelerometer and the various subsystems.
573 * Should be rather independent of the bus system.
574 */
575 int lis3lv02d_init_device(struct lis3lv02d *dev)
576 {
577 int err;
578 irq_handler_t thread_fn;
579
580 dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I);
581
582 switch (dev->whoami) {
583 case WAI_12B:
584 printk(KERN_INFO DRIVER_NAME ": 12 bits sensor found\n");
585 dev->read_data = lis3lv02d_read_12;
586 dev->mdps_max_val = 2048;
587 dev->pwron_delay = LIS3_PWRON_DELAY_WAI_12B;
588 dev->odrs = lis3_12_rates;
589 dev->odr_mask = CTRL1_DF0 | CTRL1_DF1;
590 dev->scale = LIS3_SENSITIVITY_12B;
591 break;
592 case WAI_8B:
593 printk(KERN_INFO DRIVER_NAME ": 8 bits sensor found\n");
594 dev->read_data = lis3lv02d_read_8;
595 dev->mdps_max_val = 128;
596 dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
597 dev->odrs = lis3_8_rates;
598 dev->odr_mask = CTRL1_DR;
599 dev->scale = LIS3_SENSITIVITY_8B;
600 break;
601 default:
602 printk(KERN_ERR DRIVER_NAME
603 ": unknown sensor type 0x%X\n", dev->whoami);
604 return -EINVAL;
605 }
606
607 mutex_init(&dev->mutex);
608
609 lis3lv02d_add_fs(dev);
610 lis3lv02d_poweron(dev);
611
612 if (lis3lv02d_joystick_enable())
613 printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n");
614
615 /* passing in platform specific data is purely optional and only
616 * used by the SPI transport layer at the moment */
617 if (dev->pdata) {
618 struct lis3lv02d_platform_data *p = dev->pdata;
619
620 if (dev->whoami == WAI_8B)
621 lis3lv02d_8b_configure(dev, p);
622
623 if (p->irq_cfg)
624 dev->write(dev, CTRL_REG3, p->irq_cfg);
625 }
626
627 /* bail if we did not get an IRQ from the bus layer */
628 if (!dev->irq) {
629 printk(KERN_ERR DRIVER_NAME
630 ": No IRQ. Disabling /dev/freefall\n");
631 goto out;
632 }
633
634 /*
635 * The sensor can generate interrupts for free-fall and direction
636 * detection (distinguishable with FF_WU_SRC and DD_SRC) but to keep
637 * the things simple and _fast_ we activate it only for free-fall, so
638 * no need to read register (very slow with ACPI). For the same reason,
639 * we forbid shared interrupts.
640 *
641 * IRQF_TRIGGER_RISING seems pointless on HP laptops because the
642 * io-apic is not configurable (and generates a warning) but I keep it
643 * in case of support for other hardware.
644 */
645 if (dev->whoami == WAI_8B)
646 thread_fn = lis302dl_interrupt_thread1_8b;
647 else
648 thread_fn = NULL;
649
650 err = request_threaded_irq(dev->irq, lis302dl_interrupt,
651 thread_fn,
652 IRQF_TRIGGER_RISING | IRQF_ONESHOT,
653 DRIVER_NAME, &lis3_dev);
654
655 if (err < 0) {
656 printk(KERN_ERR DRIVER_NAME "Cannot get IRQ\n");
657 goto out;
658 }
659
660 if (misc_register(&lis3lv02d_misc_device))
661 printk(KERN_ERR DRIVER_NAME ": misc_register failed\n");
662 out:
663 return 0;
664 }
665 EXPORT_SYMBOL_GPL(lis3lv02d_init_device);
666
667 MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver");
668 MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
669 MODULE_LICENSE("GPL");
This page took 0.055281 seconds and 5 git commands to generate.