コード例 #1
0
/*
 * 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;
}
コード例 #2
0
/*
 * Initialise the accelerometer and the various subsystems.
 * Should be rather independent of the bus system.
 */
int lis3lv02d_init_device(struct lis3lv02d *dev)
{
	dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I);

	switch (dev->whoami) {
	case WAI_12B:
		printk(KERN_INFO DRIVER_NAME ": 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;
		break;
	case WAI_8B:
		printk(KERN_INFO DRIVER_NAME ": 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;
		break;
	default:
		printk(KERN_ERR DRIVER_NAME
			": unknown sensor type 0x%X\n", dev->whoami);
		return -EINVAL;
	}

	mutex_init(&dev->mutex);

	lis3lv02d_add_fs(dev);
	lis3lv02d_poweron(dev);

	if (lis3lv02d_joystick_enable())
		printk(KERN_ERR DRIVER_NAME ": 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 (p->click_flags && (dev->whoami == WAI_8B)) {
			dev->write(dev, CLICK_CFG, p->click_flags);
			dev->write(dev, CLICK_TIMELIMIT, p->click_time_limit);
			dev->write(dev, CLICK_LATENCY, p->click_latency);
			dev->write(dev, CLICK_WINDOW, p->click_window);
			dev->write(dev, CLICK_THSZ, p->click_thresh_z & 0xf);
			dev->write(dev, CLICK_THSY_X,
					(p->click_thresh_x & 0xf) |
					(p->click_thresh_y << 4));
		}

		if (p->wakeup_flags && (dev->whoami == WAI_8B)) {
			dev->write(dev, FF_WU_CFG_1, p->wakeup_flags);
			dev->write(dev, FF_WU_THS_1, p->wakeup_thresh & 0x7f);
			/* default to 2.5ms for now */
			dev->write(dev, FF_WU_DURATION_1, 1);
			/* enable high pass filter for both free-fall units */
			dev->write(dev, CTRL_REG2, HP_FF_WU1 | HP_FF_WU2);
		}

		if (p->irq_cfg)
			dev->write(dev, CTRL_REG3, p->irq_cfg);
	}

	/* bail if we did not get an IRQ from the bus layer */
	if (!dev->irq) {
		printk(KERN_ERR DRIVER_NAME
			": No IRQ. Disabling /dev/freefall\n");
		goto out;
	}

	if (misc_register(&lis3lv02d_misc_device))
		printk(KERN_ERR DRIVER_NAME ": misc_register failed\n");
out:
	return 0;
}