static ssize_t lis3lv02d_rate_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { unsigned long rate; if (strict_strtoul(buf, 0, &rate)) return -EINVAL; if (lis3lv02d_set_odr(rate)) return -EINVAL; return count; }
/* * Initialise the accelerometer and the various subsystems. * Should be rather independent of the bus system. */ int lis3lv02d_init_device(struct lis3lv02d *dev) { int err; irq_handler_t thread_fn; int irq_flags = 0; dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I); switch (dev->whoami) { case WAI_12B: pr_info("12 bits sensor found\n"); dev->read_data = lis3lv02d_read_12; dev->mdps_max_val = 2048; dev->pwron_delay = LIS3_PWRON_DELAY_WAI_12B; dev->odrs = lis3_12_rates; dev->odr_mask = CTRL1_DF0 | CTRL1_DF1; dev->scale = LIS3_SENSITIVITY_12B; dev->regs = lis3_wai12_regs; dev->regs_size = ARRAY_SIZE(lis3_wai12_regs); break; case WAI_8B: pr_info("8 bits sensor found\n"); dev->read_data = lis3lv02d_read_8; dev->mdps_max_val = 128; dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B; dev->odrs = lis3_8_rates; dev->odr_mask = CTRL1_DR; dev->scale = LIS3_SENSITIVITY_8B; dev->regs = lis3_wai8_regs; dev->regs_size = ARRAY_SIZE(lis3_wai8_regs); break; case WAI_3DC: pr_info("8 bits 3DC sensor found\n"); dev->read_data = lis3lv02d_read_8; dev->mdps_max_val = 128; dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B; dev->odrs = lis3_3dc_rates; dev->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3; dev->scale = LIS3_SENSITIVITY_8B; break; default: pr_err("unknown sensor type 0x%X\n", dev->whoami); return -EINVAL; } dev->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs), sizeof(lis3_wai12_regs)), GFP_KERNEL); if (dev->reg_cache == NULL) { printk(KERN_ERR DRIVER_NAME "out of memory\n"); return -ENOMEM; } mutex_init(&dev->mutex); atomic_set(&dev->wake_thread, 0); lis3lv02d_add_fs(dev); lis3lv02d_poweron(dev); if (dev->pm_dev) { pm_runtime_set_active(dev->pm_dev); pm_runtime_enable(dev->pm_dev); } if (lis3lv02d_joystick_enable()) pr_err("joystick initialization failed\n"); /* passing in platform specific data is purely optional and only * used by the SPI transport layer at the moment */ if (dev->pdata) { struct lis3lv02d_platform_data *p = dev->pdata; if (dev->whoami == WAI_8B) lis3lv02d_8b_configure(dev, p); irq_flags = p->irq_flags1 & IRQF_TRIGGER_MASK; dev->irq_cfg = p->irq_cfg; if (p->irq_cfg) dev->write(dev, CTRL_REG3, p->irq_cfg); if (p->default_rate) lis3lv02d_set_odr(p->default_rate); } /* bail if we did not get an IRQ from the bus layer */ if (!dev->irq) { pr_debug("No IRQ. Disabling /dev/freefall\n"); goto out; } /* * The sensor can generate interrupts for free-fall and direction * detection (distinguishable with FF_WU_SRC and DD_SRC) but to keep * the things simple and _fast_ we activate it only for free-fall, so * no need to read register (very slow with ACPI). For the same reason, * we forbid shared interrupts. * * IRQF_TRIGGER_RISING seems pointless on HP laptops because the * io-apic is not configurable (and generates a warning) but I keep it * in case of support for other hardware. */ if (dev->pdata && dev->whoami == WAI_8B) thread_fn = lis302dl_interrupt_thread1_8b; else thread_fn = NULL; err = request_threaded_irq(dev->irq, lis302dl_interrupt, thread_fn, IRQF_TRIGGER_RISING | IRQF_ONESHOT | irq_flags, DRIVER_NAME, &lis3_dev); if (err < 0) { pr_err("Cannot get IRQ\n"); goto out; } if (misc_register(&lis3lv02d_misc_device)) pr_err("misc_register failed\n"); out: return 0; }