Пример #1
0
static int __devinit bh1721fvc_probe(struct i2c_client *client,
					const struct i2c_device_id *id)
{
	int err = 0;
	struct bh1721fvc_data *bh1721fvc;
	struct input_dev *input_dev;
	struct bh1721fvc_platform_data *pdata = client->dev.platform_data;
	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);

	pr_info("%s: is started!\n", __func__);
	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
		return -EIO;

	bh1721fvc = kzalloc(sizeof(*bh1721fvc), GFP_KERNEL);
	if (!bh1721fvc) {
		pr_err("%s, failed to alloc memory for module data\n",
			__func__);
		return -ENOMEM;
	}

	if (pdata != NULL) {
		bh1721fvc->reset = pdata->reset;
		if (!bh1721fvc->reset) {
			pr_err("%s: reset callback is null\n", __func__);
			err = -EIO;
			goto err_reset_null;
		}

		err = bh1721fvc->reset();
		if (err) {
			pr_err("%s: Failed to reset\n", __func__);
			goto err_reset_failed;
		}
	}

	bh1721fvc->client = client;
	i2c_set_clientdata(client, bh1721fvc);

	mutex_init(&bh1721fvc->lock);
	bh1721fvc->state = POWER_DOWN;
	bh1721fvc->measure_mode = AUTO_MEASURE;

	err = bh1721fvc_test_luxvalue(bh1721fvc);
	if (err < 0) {
		pr_err("%s: No search bh1721fvc lightsensor!\n", __func__);
		goto err_test_lightsensor;
	} else {
		printk(KERN_ERR"Lux : %d\n", err);
	}

	hrtimer_init(&bh1721fvc->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);

	bh1721fvc->light_poll_delay = ns_to_ktime(200 * NSEC_PER_MSEC);
	bh1721fvc->timer.function = bh1721fvc_timer_func;

	bh1721fvc->wq = alloc_workqueue("bh1721fvc_wq",
		WQ_UNBOUND | WQ_RESCUER, 1);
	if (!bh1721fvc->wq) {
		err = -ENOMEM;
		pr_err("%s: could not create workqueue\n", __func__);
		goto err_create_workqueue;
	}

	INIT_WORK(&bh1721fvc->work_light, bh1721fvc_work_func_light);

	input_dev = input_allocate_device();
	if (!input_dev) {
		pr_err("%s: could not allocate input device\n", __func__);
		err = -ENOMEM;
		goto err_input_allocate_device_light;
	}
	input_set_drvdata(input_dev, bh1721fvc);
	input_dev->name = "light_sensor";
#if 0
	input_set_capability(input_dev, EV_ABS, ABS_MISC);
	input_set_abs_params(input_dev, ABS_MISC,
		LUX_MIN_VALUE, LUX_MAX_VALUE, 0, 0);
#else
	input_set_capability(input_dev, EV_REL, REL_MISC);
#endif
	bh1721fvc_dbmsg("registering lightsensor-level input device\n");
	err = input_register_device(input_dev);
	if (err < 0) {
		pr_err("%s: could not register input device\n", __func__);
		input_free_device(input_dev);
		goto err_input_register_device_light;
	}
	bh1721fvc->input_dev = input_dev;
	err = sysfs_create_group(&input_dev->dev.kobj,
		&bh1721fvc_attribute_group);
	if (err) {
		pr_err("%s: could not create sysfs group\n", __func__);
		goto err_sysfs_create_group_light;
	}

	/* set sysfs for light sensor */
	bh1721fvc->light_dev = sensors_classdev_register("light_sensor");
	if (IS_ERR(bh1721fvc->light_dev)) {
		pr_err("%s: could not create light_dev\n", __func__);
		goto err_light_device_create;
	}

	if (device_create_file(bh1721fvc->light_dev, &dev_attr_raw_data) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
		       dev_attr_raw_data.attr.name);
		goto err_light_device_create_file1;
	}

	if (device_create_file(bh1721fvc->light_dev, &dev_attr_vendor) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
		       dev_attr_vendor.attr.name);
		goto err_light_device_create_file2;
	}

	if (device_create_file(bh1721fvc->light_dev, &dev_attr_name) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
		       dev_attr_name.attr.name);
		goto err_light_device_create_file3;
	}

	dev_set_drvdata(bh1721fvc->light_dev, bh1721fvc);
	pr_info("%s: success!\n", __func__);


	goto done;

err_light_device_create_file3:
	device_remove_file(bh1721fvc->light_dev, &dev_attr_vendor);
err_light_device_create_file2:
	device_remove_file(bh1721fvc->light_dev, &dev_attr_raw_data);
err_light_device_create_file1:
	sensors_classdev_unregister(bh1721fvc->light_dev);
err_light_device_create:
	sysfs_remove_group(&bh1721fvc->input_dev->dev.kobj,
				&bh1721fvc_attribute_group);
err_sysfs_create_group_light:
	input_unregister_device(bh1721fvc->input_dev);
err_input_register_device_light:
err_input_allocate_device_light:
	destroy_workqueue(bh1721fvc->wq);
err_create_workqueue:
err_test_lightsensor:
	mutex_destroy(&bh1721fvc->lock);
err_reset_failed:
err_reset_null:
	kfree(bh1721fvc);
done:
	return err;
}
Пример #2
0
static int lsm330dlc_gyro_probe(struct i2c_client *client,
			       const struct i2c_device_id *devid)
{
	int ret;
	int err = 0;
	struct lsm330dlc_gyro_data *data;
	struct input_dev *input_dev;

	pr_info("%s, started", __func__);
	data = kzalloc(sizeof(*data), GFP_KERNEL);
	if (data == NULL) {
		dev_err(&client->dev,
			"failed to allocate memory for module data\n");
		err = -ENOMEM;
		goto exit;
	}

	data->client = client;
	data->drop_next_event = 0;

	/* read chip id */
	ret = i2c_smbus_read_byte_data(client, WHO_AM_I);
	if (ret != DEVICE_ID) {
		if (ret < 0) {
			pr_err("%s: i2c for reading chip id failed\n",
								__func__);
			err = ret;
		} else {
			pr_err("%s : Device identification failed\n",
								__func__);
			err = -ENODEV;
		}
		goto err_read_reg;
	}

	mutex_init(&data->lock);
	atomic_set(&data->opened, 0);
	init_completion(&data->data_ready);

	/* allocate gyro input_device */
	input_dev = input_allocate_device();
	if (!input_dev) {
		pr_err("%s: could not allocate input device\n", __func__);
		err = -ENOMEM;
		goto err_input_allocate_device;
	}

	data->input_dev = input_dev;
	input_set_drvdata(input_dev, data);
	input_dev->name = L3GD20_GYR_INPUT_NAME;
	/* X */
	input_set_capability(input_dev, EV_REL, REL_RX);
	/* Y */
	input_set_capability(input_dev, EV_REL, REL_RY);
	/* Z */
	input_set_capability(input_dev, EV_REL, REL_RZ);

	err = input_register_device(input_dev);
	if (err < 0) {
		pr_err("%s: could not register input device\n", __func__);
		input_free_device(data->input_dev);
		goto err_input_register_device;
	}

	i2c_set_clientdata(client, data);
	dev_set_drvdata(&input_dev->dev, data);

	if (data->client->irq >= 0) { /* interrupt */
		memcpy(&data->ctrl_regs, &default_ctrl_regs_fifo,
			sizeof(default_ctrl_regs_fifo));
		data->interruptible = true;
		data->entries = 1;
		err = request_threaded_irq(data->client->irq, NULL,
			lsm330dlc_gyro_interrupt_thread\
			, IRQF_TRIGGER_RISING | IRQF_ONESHOT,\
				"lsm330dlc_gyro", data);
		if (err < 0) {
			pr_err("%s: can't allocate irq.\n", __func__);
			goto err_request_irq;
		}
		disable_irq(data->client->irq);
	} else { /* polling */
		memcpy(&data->ctrl_regs, &default_ctrl_regs_bypass,
			sizeof(default_ctrl_regs_bypass));
		data->ctrl_regs[2] = 0x00; /* disable interrupt */
		/* hrtimer settings.  we poll for gyro values using a timer. */
		hrtimer_init(&data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
		data->polling_delay = ns_to_ktime(200 * NSEC_PER_MSEC);
		data->timer.function = lsm330dlc_gyro_timer_func;

		/* the timer just fires off a work queue request.
		   We need a thread to read i2c (can be slow and blocking). */
		data->lsm330dlc_gyro_wq \
		= create_singlethread_workqueue("lsm330dlc_gyro_wq");
		if (!data->lsm330dlc_gyro_wq) {
			err = -ENOMEM;
			pr_err("%s: could not create workqueue\n", __func__);
			goto err_create_workqueue;
		}
		/* this is the thread function we run on the work queue */
		INIT_WORK(&data->work, lsm330dlc_gyro_work_func);
	}

	if (device_create_file(&input_dev->dev,
				&dev_attr_enable) < 0) {
		pr_err("%s: Failed to create device file(%s)!\n", __func__,
				dev_attr_enable.attr.name);
		goto err_device_create_file;
	}

	if (device_create_file(&input_dev->dev,
				&dev_attr_poll_delay) < 0) {
		pr_err("%s: Failed to create device file(%s)!\n", __func__,
				dev_attr_poll_delay.attr.name);
		goto err_device_create_file2;
	}

	/* create device node for lsm330dlc_gyro digital gyroscope */
	data->dev = sensors_classdev_register("gyro_sensor");

	if (IS_ERR(data->dev)) {
		pr_err("%s: Failed to create device(gyro)\n", __func__);
		err = PTR_ERR(data->dev);
		goto err_device_create;
	}

	if (device_create_file(data->dev, &dev_attr_power_on) < 0) {
		pr_err("%s: Failed to create device file(%s)!\n", __func__,
			dev_attr_power_on.attr.name);
		goto err_device_create_file3;
	}

	if (device_create_file(data->dev, &dev_attr_power_off) < 0) {
		pr_err("%s: Failed to create device file(%s)!\n", __func__,
			dev_attr_power_off.attr.name);
		goto err_device_create_file4;
	}

	if (device_create_file(data->dev, &dev_attr_temperature) < 0) {
		pr_err("%s: Failed to create device file(%s)!\n", __func__,
			dev_attr_temperature.attr.name);
		goto err_device_create_file5;
	}

	if (device_create_file(data->dev, &dev_attr_selftest) < 0) {
		pr_err("%s: Failed to create device file(%s)!\n", __func__,
			dev_attr_selftest.attr.name);
		goto err_device_create_file6;
	}

	if (device_create_file(data->dev, &dev_attr_selftest_dps) < 0) {
		pr_err("%s: Failed to create device file(%s)!\n", __func__,
			dev_attr_selftest_dps.attr.name);
		goto err_device_create_file7;
	}

	if (device_create_file(data->dev, &dev_attr_vendor) < 0) {
		pr_err("%s: Failed to create device file(%s)!\n", __func__,
			dev_attr_vendor.attr.name);
		goto err_device_create_file8;
	}

	if (device_create_file(data->dev, &dev_attr_name) < 0) {
		pr_err("%s: Failed to create device file(%s)!\n", __func__,
			dev_attr_name.attr.name);
		goto err_device_create_file9;
	}

#ifdef DEBUG_REGISTER
	if (device_create_file(data->dev, &dev_attr_reg_data) < 0) {
		pr_err("%s: Failed to create device file(%s)!\n", __func__,
			dev_attr_reg_data.attr.name);
		goto err_device_create_file10;
	}
#endif

	dev_set_drvdata(data->dev, data);
	pr_info("%s, successful", __func__);

	return 0;

#ifdef DEBUG_REGISTER
err_device_create_file10:
	device_remove_file(data->dev, &dev_attr_name);
#endif
err_device_create_file9:
	device_remove_file(data->dev, &dev_attr_vendor);
err_device_create_file8:
	device_remove_file(data->dev, &dev_attr_selftest_dps);
err_device_create_file7:
	device_remove_file(data->dev, &dev_attr_selftest);
err_device_create_file6:
	device_remove_file(data->dev, &dev_attr_temperature);
err_device_create_file5:
	device_remove_file(data->dev, &dev_attr_power_off);
err_device_create_file4:
	device_remove_file(data->dev, &dev_attr_power_on);
err_device_create_file3:
	sensors_classdev_unregister(data->dev);
err_device_create:
	device_remove_file(&input_dev->dev, &dev_attr_poll_delay);
err_device_create_file2:
	device_remove_file(&input_dev->dev, &dev_attr_enable);
err_device_create_file:
	if (data->interruptible)
		free_irq(data->client->irq, data);
	else
		destroy_workqueue(data->lsm330dlc_gyro_wq);
err_create_workqueue:
err_request_irq:
	input_unregister_device(data->input_dev);
err_input_register_device:
err_input_allocate_device:
	mutex_destroy(&data->lock);
err_read_reg:
	kfree(data);
exit:
	return err;
}
Пример #3
0
static int cm3323_i2c_probe(struct i2c_client *client,
			     const struct i2c_device_id *id)
{
	int ret = -ENODEV;
	struct cm3323_data *cm3323 = NULL;

	pr_info("%s is called.\n", __func__);
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		pr_err("%s: i2c functionality check failed!\n", __func__);
		return ret;
	}

	cm3323 = kzalloc(sizeof(struct cm3323_data), GFP_KERNEL);
	if (!cm3323) {
		pr_err
		    ("%s: failed to alloc memory for RGB sensor module data\n",
		     __func__);
		return -ENOMEM;
	}

	cm3323->i2c_client = client;
	i2c_set_clientdata(client, cm3323);
	mutex_init(&cm3323->power_lock);
	mutex_init(&cm3323->read_lock);

	/* Check if the device is there or not. */
	ret = cm3323_setup_reg(cm3323);
	if (ret < 0) {
		pr_err("%s: could not setup regs\n", __func__);
		goto err_setup_reg;
	}

	/* allocate lightsensor input_device */
	cm3323->light_input_dev = input_allocate_device();
	if (!cm3323->light_input_dev) {
		pr_err("%s: could not allocate light input device\n", __func__);
		goto err_input_allocate_device_light;
	}

	input_set_drvdata(cm3323->light_input_dev, cm3323);
	cm3323->light_input_dev->name = "light_sensor";
	input_set_capability(cm3323->light_input_dev, EV_REL, REL_RED);
	input_set_capability(cm3323->light_input_dev, EV_REL, REL_GREEN);
	input_set_capability(cm3323->light_input_dev, EV_REL, REL_BLUE);
	input_set_capability(cm3323->light_input_dev, EV_REL, REL_WHITE);

	ret = input_register_device(cm3323->light_input_dev);
	if (ret < 0) {
		input_free_device(cm3323->light_input_dev);
		pr_err("%s: could not register input device\n", __func__);
		goto err_input_register_device_light;
	}

	ret = sysfs_create_group(&cm3323->light_input_dev->dev.kobj,
				 &light_attribute_group);
	if (ret) {
		pr_err("%s: could not create sysfs group\n", __func__);
		goto err_sysfs_create_group_light;
	}

	/* light_timer settings. we poll for light values using a timer. */
	hrtimer_init(&cm3323->light_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	cm3323->light_poll_delay = ns_to_ktime(200 * NSEC_PER_MSEC);
	cm3323->light_timer.function = cm3323_light_timer_func;

	/* the timer just fires off a work queue request.  we need a thread
	   to read the i2c (can be slow and blocking). */
	cm3323->light_wq = create_singlethread_workqueue("cm3323_light_wq");
	if (!cm3323->light_wq) {
		ret = -ENOMEM;
		pr_err("%s: could not create light workqueue\n", __func__);
		goto err_create_light_workqueue;
	}

	/* this is the thread function we run on the work queue */
	INIT_WORK(&cm3323->work_light, cm3323_work_func_light);

	/* set sysfs for light sensor */
	cm3323->light_dev = sensors_classdev_register("light_sensor");
	if (IS_ERR(cm3323->light_dev)) {
		pr_err("%s: could not create light_dev\n", __func__);
		goto err_light_device_create;
	}

	if (device_create_file(cm3323->light_dev, &dev_attr_lux) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
		       dev_attr_lux.attr.name);
		goto err_light_device_create_file1;
	}

	if (device_create_file(cm3323->light_dev, &dev_attr_raw_data) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
		       dev_attr_raw_data.attr.name);
		goto err_light_device_create_file2;
	}

	if (device_create_file(cm3323->light_dev, &dev_attr_vendor) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
		       dev_attr_vendor.attr.name);
		goto err_light_device_create_file3;
	}

	if (device_create_file(cm3323->light_dev, &dev_attr_name) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
		       dev_attr_name.attr.name);
		goto err_light_device_create_file4;
	}

	dev_set_drvdata(cm3323->light_dev, cm3323);

	pr_info("%s is success.\n", __func__);
	goto done;

/* error, unwind it all */
err_light_device_create_file4:
	device_remove_file(cm3323->light_dev, &dev_attr_vendor);
err_light_device_create_file3:
	device_remove_file(cm3323->light_dev, &dev_attr_raw_data);
err_light_device_create_file2:
	device_remove_file(cm3323->light_dev, &dev_attr_lux);
err_light_device_create_file1:
	sensors_classdev_unregister(cm3323->light_dev);
err_light_device_create:
	destroy_workqueue(cm3323->light_wq);
err_create_light_workqueue:
	sysfs_remove_group(&cm3323->light_input_dev->dev.kobj,
			   &light_attribute_group);
err_sysfs_create_group_light:
	input_unregister_device(cm3323->light_input_dev);
err_input_register_device_light:
err_input_allocate_device_light:
err_setup_reg:
	mutex_destroy(&cm3323->read_lock);
	mutex_destroy(&cm3323->power_lock);
	kfree(cm3323);
done:
	return ret;
}
static int gp2a_opt_probe(struct platform_device *pdev)
{
	struct gp2a_data *gp2a;
	struct gp2a_platform_data *pdata = pdev->dev.platform_data;
	u8 value = 0;
	int err = 0;

	gprintk("probe start!\n");

	if (!pdata) {
		pr_err("%s: missing pdata!\n", __func__);
		return err;
	}

	if (!pdata->gp2a_led_on) {
		pr_err("%s: incomplete pdata!\n", __func__);
		return err;
	}
	/* gp2a power on */
	pdata->gp2a_led_on(true);

	if (pdata->gp2a_get_threshold) {
		gp2a_update_threshold(is_gp2a030a() ?
			gp2a_original_image_030a : gp2a_original_image,
			pdata->gp2a_get_threshold(), false);
	}

	/* allocate driver_data */
	gp2a = kzalloc(sizeof(struct gp2a_data), GFP_KERNEL);
	if (!gp2a) {
		pr_err("kzalloc error\n");
		return -ENOMEM;
	}

	proximity_enable = 0;
	proximity_sensor_detection = 0;
	proximity_avg_on = 0;
	gp2a->enabled = 0;
	gp2a->pdata = pdata;

	/* prox_timer settings. we poll for prox_avg values using a timer. */
	hrtimer_init(&gp2a->prox_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	gp2a->prox_poll_delay = ns_to_ktime(2000 * NSEC_PER_MSEC);
	gp2a->prox_timer.function = gp2a_prox_timer_func;

	gp2a->prox_wq = create_singlethread_workqueue("gp2a_prox_wq");
	if (!gp2a->prox_wq) {
		err = -ENOMEM;
		pr_err("%s: could not create prox workqueue\n", __func__);
		goto err_create_prox_workqueue;
	}

	INIT_WORK(&gp2a->work_prox, gp2a_work_func_prox_avg);
	INIT_WORK(&gp2a->work, gp2a_work_func_prox);

	err = proximity_input_init(gp2a);
	if (err < 0)
		goto error_setup_reg;

	err = sysfs_create_group(&gp2a->input_dev->dev.kobj,
				 &proximity_attribute_group);
	if (err < 0)
		goto err_sysfs_create_group_proximity;

	/* set platdata */
	platform_set_drvdata(pdev, gp2a);

	/* wake lock init */
	wake_lock_init(&gp2a->prx_wake_lock, WAKE_LOCK_SUSPEND,
		       "prx_wake_lock");

	/* init i2c */
	opt_i2c_init();

	if (opt_i2c_client == NULL) {
		pr_err("opt_probe failed : i2c_client is NULL\n");
		goto err_no_device;
	} else
		printk(KERN_INFO "opt_i2c_client : (0x%p), address = %x\n",
		       opt_i2c_client, opt_i2c_client->addr);

	/* GP2A Regs INIT SETTINGS  and Check I2C communication */
	value = 0x00;
	/* shutdown mode op[3]=0 */
	err = opt_i2c_write((u8) (COMMAND1), &value);

	if (err < 0) {
		pr_err("%s failed : threre is no such device.\n", __func__);
		goto err_no_device;
	}

	/* Setup irq */
	err = gp2a_setup_irq(gp2a);
	if (err) {
		pr_err("%s: could not setup irq\n", __func__);
		goto err_setup_irq;
	}

	/* set sysfs for proximity sensor */
	gp2a->proximity_dev = sensors_classdev_register("proximity_sensor");
	if (IS_ERR(gp2a->proximity_dev)) {
		pr_err("%s: could not create proximity_dev\n", __func__);
		goto err_proximity_device_create;
	}

	if (device_create_file(gp2a->proximity_dev, &dev_attr_state) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
		       dev_attr_state.attr.name);
		goto err_proximity_device_create_file1;
	}

	if (device_create_file(gp2a->proximity_dev, &dev_attr_prox_avg) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
		       dev_attr_prox_avg.attr.name);
		goto err_proximity_device_create_file2;
	}

	if (device_create_file(gp2a->proximity_dev,
						&dev_attr_prox_thresh) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
		       dev_attr_prox_thresh.attr.name);
		goto err_proximity_device_create_file3;
	}

	if (device_create_file(gp2a->proximity_dev,
						&dev_attr_vendor) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
		       dev_attr_vendor.attr.name);
		goto err_proximity_device_create_file4;
	}

	if (device_create_file(gp2a->proximity_dev,
						&dev_attr_name) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
		       dev_attr_name.attr.name);
		goto err_proximity_device_create_file5;
	}

	if (device_create_file(gp2a->proximity_dev, &dev_attr_raw_data) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
		       dev_attr_raw_data.attr.name);
		goto err_proximity_device_create_file6;
	}

#ifdef CONFIG_SLP
	device_init_wakeup(gp2a->proximity_dev, true);
#endif
	dev_set_drvdata(gp2a->proximity_dev, gp2a);

	device_init_wakeup(&pdev->dev, 1);

	gprintk("probe success!\n");

	return 0;

err_proximity_device_create_file6:
	device_remove_file(gp2a->proximity_dev, &dev_attr_raw_data);
err_proximity_device_create_file5:
	device_remove_file(gp2a->proximity_dev, &dev_attr_name);
err_proximity_device_create_file4:
	device_remove_file(gp2a->proximity_dev, &dev_attr_vendor);
err_proximity_device_create_file3:
	device_remove_file(gp2a->proximity_dev, &dev_attr_prox_avg);
err_proximity_device_create_file2:
	device_remove_file(gp2a->proximity_dev, &dev_attr_state);
err_proximity_device_create_file1:
	sensors_classdev_unregister(gp2a->proximity_dev);
err_proximity_device_create:
	gpio_free(pdata->p_out);
err_setup_irq:
err_no_device:
	sysfs_remove_group(&gp2a->input_dev->dev.kobj,
			   &proximity_attribute_group);
	wake_lock_destroy(&gp2a->prx_wake_lock);
err_sysfs_create_group_proximity:
	input_unregister_device(gp2a->input_dev);
error_setup_reg:
	destroy_workqueue(gp2a->prox_wq);
err_create_prox_workqueue:
	kfree(gp2a);
	return err;
}
static int cm3663_i2c_probe(struct i2c_client *client,
			  const struct i2c_device_id *id)
{
	int ret = -ENODEV;
	struct input_dev *input_dev;
	struct cm3663_data *cm3663;

	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		pr_err("%s: i2c functionality check failed!\n", __func__);
		return ret;
	}

	cm3663 = kzalloc(sizeof(struct cm3663_data), GFP_KERNEL);
	if (!cm3663) {
		pr_err("%s: failed to alloc memory for module data\n",
		       __func__);
		return -ENOMEM;
	}

	cm3663->pdata = client->dev.platform_data;
	cm3663->i2c_client = client;
	i2c_set_clientdata(client, cm3663);

	/* wake lock init */
	wake_lock_init(&cm3663->prx_wake_lock, WAKE_LOCK_SUSPEND,
		       "prx_wake_lock");
	mutex_init(&cm3663->power_lock);

	/* setup initial registers */
	ret = cm3663_setup_reg(cm3663);
	if (ret < 0) {
		pr_err("%s: could not setup regs\n", __func__);
		goto err_setup_reg;
	}

	ret = cm3663_setup_irq(cm3663);
	if (ret) {
		pr_err("%s: could not setup irq\n", __func__);
		goto err_setup_irq;
	}

	/* allocate proximity input_device */
	input_dev = input_allocate_device();
	if (!input_dev) {
		pr_err("%s: could not allocate input device\n", __func__);
		goto err_input_allocate_device_proximity;
	}
	cm3663->proximity_input_dev = input_dev;
	input_set_drvdata(input_dev, cm3663);
	input_dev->name = "proximity_sensor";
	input_set_capability(input_dev, EV_ABS, ABS_DISTANCE);
	input_set_abs_params(input_dev, ABS_DISTANCE, 0, 1, 0, 0);

	ret = input_register_device(input_dev);
	if (ret < 0) {
		pr_err("%s: could not register input device\n", __func__);
		input_free_device(input_dev);
		goto err_input_register_device_proximity;
	}
	ret = sysfs_create_group(&input_dev->dev.kobj,
				 &proximity_attribute_group);
	if (ret) {
		pr_err("%s: could not create sysfs group\n", __func__);
		goto err_sysfs_create_group_proximity;
	}

	/* light_timer settings. we poll for light values using a timer. */
	hrtimer_init(&cm3663->light_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	cm3663->light_poll_delay = ns_to_ktime(200 * NSEC_PER_MSEC);
	cm3663->light_timer.function = cm3663_light_timer_func;

	/* prox_timer settings. we poll for light values using a timer. */
	hrtimer_init(&cm3663->prox_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	cm3663->prox_poll_delay = ns_to_ktime(2000 * NSEC_PER_MSEC);
	cm3663->prox_timer.function = cm3663_prox_timer_func;

	/* the timer just fires off a work queue request.  we need a thread
	   to read the i2c (can be slow and blocking). */
	cm3663->light_wq = create_singlethread_workqueue("cm3663_light_wq");
	if (!cm3663->light_wq) {
		ret = -ENOMEM;
		pr_err("%s: could not create light workqueue\n", __func__);
		goto err_create_light_workqueue;
	}
	cm3663->prox_wq = create_singlethread_workqueue("cm3663_prox_wq");
	if (!cm3663->prox_wq) {
		ret = -ENOMEM;
		pr_err("%s: could not create prox workqueue\n", __func__);
		goto err_create_prox_workqueue;
	}

	/* this is the thread function we run on the work queue */
	INIT_WORK(&cm3663->work_light, cm3663_work_func_light);
	INIT_WORK(&cm3663->work_prox, cm3663_work_func_prox);

	/* allocate lightsensor-level input_device */
	input_dev = input_allocate_device();
	if (!input_dev) {
		pr_err("%s: could not allocate input device\n", __func__);
		ret = -ENOMEM;
		goto err_input_allocate_device_light;
	}
	input_set_drvdata(input_dev, cm3663);
	input_dev->name = "light_sensor";
#if defined(CONFIG_MACH_S2PLUS)
	input_set_capability(input_dev, EV_REL, REL_MISC);
#else
	input_set_capability(input_dev, EV_ABS, ABS_MISC);
	input_set_abs_params(input_dev, ABS_MISC, 0, 1, 0, 0);
#endif

	ret = input_register_device(input_dev);
	if (ret < 0) {
		pr_err("%s: could not register input device\n", __func__);
		input_free_device(input_dev);
		goto err_input_register_device_light;
	}
	cm3663->light_input_dev = input_dev;
	ret = sysfs_create_group(&input_dev->dev.kobj,
				 &light_attribute_group);
	if (ret) {
		pr_err("%s: could not create sysfs group\n", __func__);
		goto err_sysfs_create_group_light;
	}

#if defined(CONFIG_MACH_S2PLUS)
	/* set sysfs for proximity sensor */
	cm3663->proximity_dev = sensors_classdev_register("proximity_sensor");
	if (IS_ERR(cm3663->proximity_dev)) {
		pr_err("%s: could not create proximity_dev\n", __func__);
		goto err_proximity_classdev_create;
	}

	if (device_create_file(cm3663->proximity_dev,
		&dev_attr_state) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
			dev_attr_state.attr.name);
		goto err_proximity_device_create_file1;
	}

	if (device_create_file(cm3663->proximity_dev,
		&dev_attr_prox_avg) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
			dev_attr_prox_avg.attr.name);
		goto err_proximity_device_create_file2;
	}
	dev_set_drvdata(cm3663->proximity_dev, cm3663);

	/* set sysfs for light sensor */
	cm3663->switch_cmd_dev = sensors_classdev_register("light_sensor");
	if (IS_ERR(cm3663->switch_cmd_dev)) {
		pr_err("%s: could not create switch_cmd_dev\n", __func__);
		goto err_light_classdev_create;
	}
	if (device_create_file(cm3663->switch_cmd_dev,
		&dev_attr_lux) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
			dev_attr_lux.attr.name);
		goto err_light_device_create_file;
	}
	dev_set_drvdata(cm3663->switch_cmd_dev, cm3663);
#else
	/* set sysfs for proximity sensor */
	cm3663->proximity_class = class_create(THIS_MODULE, "proximity");
	if (IS_ERR(cm3663->proximity_class)) {
		pr_err("%s: could not create proximity_class\n", __func__);
		goto err_proximity_class_create;
	}

	cm3663->proximity_dev = device_create(cm3663->proximity_class,
						NULL, 0, NULL, "proximity");
	if (IS_ERR(cm3663->proximity_dev)) {
		pr_err("%s: could not create proximity_dev\n", __func__);
		goto err_proximity_device_create;
	}

	if (device_create_file(cm3663->proximity_dev,
		&dev_attr_proximity_state) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
			dev_attr_proximity_state.attr.name);
		goto err_proximity_device_create_file1;
	}

	if (device_create_file(cm3663->proximity_dev,
		&dev_attr_proximity_avg) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
			dev_attr_proximity_avg.attr.name);
		goto err_proximity_device_create_file2;
	}
	dev_set_drvdata(cm3663->proximity_dev, cm3663);

	/* set sysfs for light sensor */
	cm3663->lightsensor_class = class_create(THIS_MODULE, "lightsensor");
	if (IS_ERR(cm3663->lightsensor_class)) {
		pr_err("%s: could not create lightsensor_class\n", __func__);
		goto err_light_class_create;
	}

	cm3663->switch_cmd_dev = device_create(cm3663->lightsensor_class,
						NULL, 0, NULL, "switch_cmd");
	if (IS_ERR(cm3663->switch_cmd_dev)) {
		pr_err("%s: could not create switch_cmd_dev\n", __func__);
		goto err_light_device_create;
	}

	if (device_create_file(cm3663->switch_cmd_dev,
		&dev_attr_lightsensor_file_state) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
			dev_attr_lightsensor_file_state.attr.name);
		goto err_light_device_create_file;
	}
	dev_set_drvdata(cm3663->switch_cmd_dev, cm3663);
#endif

    /* set initial proximity value (far) */
    input_report_abs(cm3663->proximity_input_dev, ABS_DISTANCE, 1);
    input_sync(cm3663->proximity_input_dev);

	goto done;

/* error, unwind it all */
#if defined(CONFIG_MACH_S2PLUS)
err_light_device_create_file:
	sensors_classdev_unregister(cm3663->switch_cmd_dev);
err_light_classdev_create:
	device_remove_file(cm3663->proximity_dev, &dev_attr_prox_avg);
err_proximity_device_create_file2:
	device_remove_file(cm3663->proximity_dev, &dev_attr_state);
err_proximity_device_create_file1:
	sensors_classdev_unregister(cm3663->proximity_dev);
err_proximity_classdev_create:
#else
err_light_device_create_file:
	device_destroy(cm3663->lightsensor_class, 0);
err_light_device_create:
	class_destroy(cm3663->lightsensor_class);
err_light_class_create:
	device_remove_file(cm3663->proximity_dev, &dev_attr_proximity_avg);
err_proximity_device_create_file2:
	device_remove_file(cm3663->proximity_dev, &dev_attr_proximity_state);
err_proximity_device_create_file1:
	device_destroy(cm3663->proximity_class, 0);
err_proximity_device_create:
	class_destroy(cm3663->proximity_class);
err_proximity_class_create:
#endif
	sysfs_remove_group(&input_dev->dev.kobj,
			&light_attribute_group);
err_sysfs_create_group_light:
	input_unregister_device(cm3663->light_input_dev);
err_input_register_device_light:
err_input_allocate_device_light:
	destroy_workqueue(cm3663->prox_wq);
err_create_prox_workqueue:
	destroy_workqueue(cm3663->light_wq);
err_create_light_workqueue:
	sysfs_remove_group(&cm3663->proximity_input_dev->dev.kobj,
			   &proximity_attribute_group);
err_sysfs_create_group_proximity:
	input_unregister_device(cm3663->proximity_input_dev);
err_input_register_device_proximity:
err_input_allocate_device_proximity:
	free_irq(cm3663->irq, 0);
err_setup_irq:
err_setup_reg:
	mutex_destroy(&cm3663->power_lock);
	wake_lock_destroy(&cm3663->prx_wake_lock);
	kfree(cm3663);
done:
	return ret;
}
int akm8963_probe(struct i2c_client *client,
                  const struct i2c_device_id *devid)
{
    struct akm8963_data *akm;
    int err;

    pr_info("%s is called.\n", __func__);
    if (client->dev.platform_data == NULL && client->irq == 0) {
        dev_err(&client->dev, "platform data & irq are NULL.\n");
        err = -ENODEV;
        goto exit_platform_data_null;
    }

    if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
        dev_err(&client->dev, "I2C check failed, exiting.\n");
        err = -ENODEV;
        goto exit_check_functionality_failed;
    }

    akm = kzalloc(sizeof(struct akm8963_data), GFP_KERNEL);
    if (!akm) {
        dev_err(&client->dev,
                "failed to allocate memory for module data\n");
        err = -ENOMEM;
        goto exit_alloc_data_failed;
    }

    akm->pdata = client->dev.platform_data;
    mutex_init(&akm->lock);
    init_completion(&akm->data_ready);

    i2c_set_clientdata(client, akm);
    akm->this_client = client;

    err = akm8963_ecs_set_mode_power_down(akm);
    if (err < 0) {
        pr_err("%s: akm8963_ecs_set_mode_power_down fail(err=%d)\n",
               __func__, err);
        goto exit_set_mode_power_down_failed;
    }

    err = akm8963_setup_irq(akm);
    if (err) {
        pr_err("%s: could not setup irq\n", __func__);
        goto exit_setup_irq;
    }

    akm->akmd_device.minor = MISC_DYNAMIC_MINOR;
    akm->akmd_device.name = "akm8963";
    akm->akmd_device.fops = &akmd_fops;

    err = misc_register(&akm->akmd_device);
    if (err) {
        pr_err("%s, misc_register failed.\n", __func__);
        goto exit_akmd_device_register_failed;
    }

    init_waitqueue_head(&akm->state_wq);

    /* put into fuse access mode to read asa data */
    err = i2c_smbus_write_byte_data(client, AK8963_REG_CNTL1,
                                    AK8963_CNTL1_FUSE_ACCESS);
    if (err) {
        pr_err("%s: unable to enter fuse rom mode\n", __func__);
        goto exit_i2c_failed;
    }

    err = i2c_smbus_read_i2c_block_data(client, AK8963_FUSE_ASAX,
                                        sizeof(akm->asa), akm->asa);
    if (err != sizeof(akm->asa)) {
        pr_err("%s: unable to load factory sensitivity adjust values\n",
               __func__);
        goto exit_i2c_failed;
    } else
        pr_info("%s: asa_x = %d, asa_y = %d, asa_z = %d\n", __func__,
                akm->asa[0], akm->asa[1], akm->asa[2]);

    err = i2c_smbus_write_byte_data(client, AK8963_REG_CNTL1,
                                    AK8963_CNTL1_POWER_DOWN);
    if (err) {
        dev_err(&client->dev, "Error in setting power down mode\n");
        goto exit_i2c_failed;
    }

    akm->dev = sensors_classdev_register("magnetic_sensor");
    if (IS_ERR(akm->dev)) {
        pr_err("Failed to create device!");
        goto exit_class_create_failed;
    }

    if (device_create_file(akm->dev, &dev_attr_raw_data) < 0) {
        pr_err("Failed to create device file(%s)!\n",
               dev_attr_raw_data.attr.name);
        goto exit_device_create_raw_data;
    }

    if (device_create_file(akm->dev, &dev_attr_vendor) < 0) {
        pr_err("Failed to create device file(%s)!\n",
               dev_attr_name.attr.name);
        goto exit_device_create_vendor;
    }

    if (device_create_file(akm->dev, &dev_attr_name) < 0) {
        pr_err("Failed to create device file(%s)!\n",
               dev_attr_raw_data.attr.name);
        goto exit_device_create_name;
    }

#ifdef FACTORY_TEST
    if (device_create_file(akm->dev, &dev_attr_adc) < 0) {
        pr_err("Failed to create device file(%s)!\n",
               dev_attr_adc.attr.name);
        goto exit_device_create_file1;
    }

    if (device_create_file(akm->dev, &dev_attr_status) < 0) {
        pr_err("Failed to create device file(%s)!\n",
               dev_attr_status.attr.name);
        goto exit_device_create_file2;
    }

    if (device_create_file(akm->dev, &dev_attr_asa) < 0) {
        pr_err("Failed to create device file(%s)!\n",
               dev_attr_asa.attr.name);
        goto exit_device_create_file3;
    }
    if (device_create_file(akm->dev, &dev_attr_selftest) < 0) {
        pr_err("Failed to create device file(%s)!\n",
               dev_attr_selftest.attr.name);
        goto exit_device_create_file4;
    }
    if (device_create_file(akm->dev,
                           &dev_attr_chk_registers) < 0) {
        pr_err("Failed to create device file(%s)!\n",
               dev_attr_chk_registers.attr.name);
        goto exit_device_create_file5;
    }
    if (device_create_file(akm->dev, &dev_attr_dac) < 0) {
        pr_err("Failed to create device file(%s)!\n",
               dev_attr_dac.attr.name);
        goto exit_device_create_file6;
    }
#endif
    dev_set_drvdata(akm->dev, akm);

    pr_info("%s is successful.\n", __func__);
    return 0;

#ifdef FACTORY_TEST
exit_device_create_file6:
    device_remove_file(akm->dev, &dev_attr_chk_registers);
exit_device_create_file5:
    device_remove_file(akm->dev, &dev_attr_selftest);
exit_device_create_file4:
    device_remove_file(akm->dev, &dev_attr_asa);
exit_device_create_file3:
    device_remove_file(akm->dev, &dev_attr_status);
exit_device_create_file2:
    device_remove_file(akm->dev, &dev_attr_adc);
exit_device_create_file1:
    device_remove_file(akm->dev, &dev_attr_name);
#endif
exit_device_create_name:
    device_remove_file(akm->dev, &dev_attr_vendor);
exit_device_create_vendor:
    device_remove_file(akm->dev, &dev_attr_raw_data);
exit_device_create_raw_data:
    sensors_classdev_unregister(akm->dev);
exit_class_create_failed:
exit_i2c_failed:
    misc_deregister(&akm->akmd_device);
exit_akmd_device_register_failed:
    free_irq(akm->irq, akm);
    gpio_free(akm->pdata->gpio_data_ready_int);
exit_setup_irq:
exit_set_mode_power_down_failed:
    mutex_destroy(&akm->lock);
    kfree(akm);
exit_alloc_data_failed:
exit_check_functionality_failed:
exit_platform_data_null:
    return err;
}
Пример #7
0
static int lightsensor_probe(struct platform_device *pdev)
{
	struct sensor_data *data = NULL;
	int rt = -ENXIO;
	unsigned char get_data = 0;

	pr_info("%s, is called\n", __func__);
	/* Check I2C communication */
	rt = opt_i2c_read(DATA0_LSB, &get_data, sizeof(get_data));

	if (rt < 0) {
		pr_err("%s failed : threre is no such device.\n", __func__);
		return rt;
	}

	gprintk("probe start!\n");

	data = kzalloc(sizeof(struct sensor_data), GFP_KERNEL);
	if (!data) {
		pr_err("%s: failed to alloc memory for module data\n",
		       __func__);
		return -ENOMEM;
	}

	data->enabled = 0;
	data->delay = SENSOR_DEFAULT_DELAY;

	data->input_dev = input_allocate_device();
	if (!data->input_dev) {
		pr_err("%s: could not allocate input device\n", __func__);
		rt = -ENOMEM;
		goto err_input_allocate_device_light;
	}

	input_set_capability(data->input_dev, EV_REL, REL_MISC);
	data->input_dev->name = SENSOR_NAME;

	rt = input_register_device(data->input_dev);
	if (rt) {
		pr_err("%s: could not register input device\n", __func__);
		input_free_device(data->input_dev);
		goto err_input_register_device_light;
	}
	input_set_drvdata(data->input_dev, data);

	rt = sysfs_create_group(&data->input_dev->dev.kobj,
				&lightsensor_attribute_group);
	if (rt) {
		pr_err("%s: could not create sysfs group\n", __func__);
		goto err_sysfs_create_group_light;
	}
	mutex_init(&data->mutex);
	mutex_init(&data->light_mutex);

	data->light_dev = sensors_classdev_register("light_sensor");
	if (IS_ERR(data->light_dev)) {
		pr_err("%s: could not create light_dev\n", __func__);
		goto err_light_device_create;
	}

	if (device_create_file(data->light_dev, &dev_attr_lux) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
		       dev_attr_lux.attr.name);
		goto err_light_device_create_file;
	}

	if (device_create_file(data->light_dev, &dev_attr_vendor) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
		       dev_attr_vendor.attr.name);
		goto err_light_device_create_file1;
	}

	if (device_create_file(data->light_dev, &dev_attr_name) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
		       dev_attr_name.attr.name);
		goto err_light_device_create_file2;
	}

	if (device_create_file(data->light_dev, &dev_attr_raw_data) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
		       dev_attr_raw_data.attr.name);
		goto err_light_device_create_file3;
	}

	dev_set_drvdata(data->light_dev, data);

	data->wq = create_singlethread_workqueue("gp2a_wq");
	if (!data->wq) {
		rt = -ENOMEM;
		pr_err("%s: could not create workqueue\n", __func__);
		goto err_create_workqueue;
	}

	/* this is the thread function we run on the work queue */
	INIT_DELAYED_WORK(&data->work, gp2a_work_func_light);

	/* set platdata */
	platform_set_drvdata(pdev, data);

	gprintk("probe success!\n");

	goto done;

/* error, unwind it all */
err_light_device_create_file3:
	device_remove_file(data->light_dev, &dev_attr_raw_data);
err_light_device_create_file2:
	device_remove_file(data->light_dev, &dev_attr_name);
err_light_device_create_file1:
	device_remove_file(data->light_dev, &dev_attr_vendor);
err_create_workqueue:
	device_remove_file(data->light_dev, &dev_attr_lux);
err_light_device_create_file:
	sensors_classdev_unregister(data->light_dev);
err_light_device_create:
	mutex_destroy(&data->mutex);
	sysfs_remove_group(&data->input_dev->dev.kobj,
			   &lightsensor_attribute_group);
err_sysfs_create_group_light:
	input_unregister_device(data->input_dev);
err_input_register_device_light:
err_input_allocate_device_light:
	kfree(data);

done:
	return rt;
}
Пример #8
0
int fts_sensor_init(struct fts_ts_data *data)
{
    struct fts_psensor_platform_data *psensor_pdata;
    struct input_dev *psensor_input_dev;
    int err;

    if (fts_psensor_support_enabled() )
    {
        device_init_wakeup(&data->client->dev, 1);
        psensor_pdata = devm_kzalloc(&data->client->dev,
                                     sizeof(struct fts_psensor_platform_data),
                                     GFP_KERNEL);
        if (!psensor_pdata)
        {
            FTS_ERROR("Failed to allocate memory");
            goto irq_free;
        }
        data->psensor_pdata = psensor_pdata;

        psensor_input_dev = input_allocate_device();
        if (!psensor_input_dev)
        {
            FTS_ERROR("Failed to allocate device");
            goto free_psensor_pdata;
        }

        __set_bit(EV_ABS, psensor_input_dev->evbit);
        input_set_abs_params(psensor_input_dev, ABS_DISTANCE, 0, 1, 0, 0);
        psensor_input_dev->name = "proximity";
        psensor_input_dev->id.bustype = BUS_I2C;
        psensor_input_dev->dev.parent = &data->client->dev;
        data->psensor_pdata->input_psensor_dev = psensor_input_dev;

        err = input_register_device(psensor_input_dev);
        if (err)
        {
            FTS_ERROR("Unable to register device, err=%d", err);
            goto free_psensor_input_dev;
        }

        psensor_pdata->ps_cdev = sensors_proximity_cdev;
        psensor_pdata->ps_cdev.sensors_enable = fts_psensor_enable_set;
        psensor_pdata->data = data;

        err = sensors_classdev_register(&data->client->dev, &psensor_pdata->ps_cdev);
        if (err)
        {
            goto unregister_psensor_input_device;
        }
    }

    return 0;
unregister_psensor_input_device:
    if (fts_psensor_support_enabled() )
        input_unregister_device(data->psensor_pdata->input_psensor_dev);
free_psensor_input_dev:
    if (fts_psensor_support_enabled() )
        input_free_device(data->psensor_pdata->input_psensor_dev);
free_psensor_pdata:
    if (fts_psensor_support_enabled() )
    {
        devm_kfree(&data->client->dev, psensor_pdata);
        data->psensor_pdata = NULL;
    }
irq_free:
    if (fts_psensor_support_enabled())
        device_init_wakeup(&data->client->dev, 0);
    free_irq(data->client->irq, data);

    return 1;
}
Пример #9
0
static int cm36686_i2c_probe(struct i2c_client *client,
				const struct i2c_device_id *id)
{
	int ret = -ENODEV;
	struct cm36686_data *cm36686 = NULL;

	pr_info("%s is called.\n", __func__);
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		pr_err("%s: i2c functionality check failed!\n", __func__);
		return ret;
	}

	cm36686 = kzalloc(sizeof(struct cm36686_data), GFP_KERNEL);
	if (!cm36686) {
		pr_err("%s: failed to alloc memory for cm36686 module data\n",
			__func__);
		return -ENOMEM;
	}

	cm36686->pdata = client->dev.platform_data;
	cm36686->i2c_client = client;
	i2c_set_clientdata(client, cm36686);
	mutex_init(&cm36686->power_lock);
	mutex_init(&cm36686->read_lock);

	if(cm36686->pdata->cm36686_light_power != NULL) {
		cm36686->cm36686_light_vddpower = cm36686->pdata->cm36686_light_power;
		if (cm36686->cm36686_light_vddpower)
			cm36686->cm36686_light_vddpower(true);
	}

	if(cm36686->pdata->cm36686_proxi_power != NULL) {
		cm36686->cm36686_proxi_vddpower = cm36686->pdata->cm36686_proxi_power;
		if (cm36686->cm36686_proxi_vddpower)
			cm36686->cm36686_proxi_vddpower(true);
	}

	/* wake lock init for proximity sensor */
	wake_lock_init(&cm36686->prx_wake_lock, WAKE_LOCK_SUSPEND,
			"prx_wake_lock");
	if (cm36686->pdata->cm36686_led_on) {
		cm36686->pdata->cm36686_led_on(true);
		msleep(20);
	}
	/* Check if the device is there or not. */
	ret = cm36686_i2c_write_word(cm36686, REG_CS_CONF1, 0x0001);
	if (ret < 0) {
		pr_err("%s: cm36686 is not connected.(%d)\n", __func__, ret);
		goto err_setup_reg;
	}

	/* setup initial registers */
	ret = cm36686_setup_reg(cm36686);
	if (ret < 0) {
		pr_err("%s: could not setup regs\n", __func__);
		goto err_setup_reg;
	}

	if (cm36686->pdata->cm36686_led_on)
		cm36686->pdata->cm36686_led_on(false);

	if (cm36686->cm36686_light_vddpower)
		cm36686->cm36686_light_vddpower(false);

	if (cm36686->cm36686_proxi_vddpower)
		cm36686->cm36686_proxi_vddpower(false);

	/* allocate proximity input_device */
	cm36686->proximity_input_dev = input_allocate_device();
	if (!cm36686->proximity_input_dev) {
		pr_err("%s: could not allocate proximity input device\n",
			__func__);
		goto err_input_allocate_device_proximity;
	}

	input_set_drvdata(cm36686->proximity_input_dev, cm36686);
	cm36686->proximity_input_dev->name = "proximity_sensor";
	input_set_capability(cm36686->proximity_input_dev, EV_ABS,
			ABS_DISTANCE);
	input_set_abs_params(cm36686->proximity_input_dev, ABS_DISTANCE, 0, 1,
			0, 0);

	ret = input_register_device(cm36686->proximity_input_dev);
	if (ret < 0) {
		input_free_device(cm36686->proximity_input_dev);
		pr_err("%s: could not register input device\n", __func__);
		goto err_input_register_device_proximity;
	}

	ret = sysfs_create_group(&cm36686->proximity_input_dev->dev.kobj,
				 &proximity_attribute_group);
	if (ret) {
		pr_err("%s: could not create sysfs group\n", __func__);
		goto err_sysfs_create_group_proximity;
	}
#if defined(CONFIG_SENSOR_USE_SYMLINK)
	ret =  sensors_initialize_symlink(cm36686->proximity_input_dev);
	if (ret < 0) {
		pr_err("%s - proximity_sensors_initialize_symlink error(%d).\n",
                        __func__, ret);
		goto err_setup_irq;
	}
#endif
	/* setup irq */
	ret = cm36686_setup_irq(cm36686);
	if (ret) {
		pr_err("%s: could not setup irq\n", __func__);
		goto err_setup_irq;
	}

	/* For factory test mode, we use timer to get average proximity data. */
	/* prox_timer settings. we poll for light values using a timer. */
	hrtimer_init(&cm36686->prox_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	cm36686->prox_poll_delay = ns_to_ktime(2000 * NSEC_PER_MSEC);/*2 sec*/
	cm36686->prox_timer.function = cm36686_prox_timer_func;

	/* the timer just fires off a work queue request.  we need a thread
	   to read the i2c (can be slow and blocking). */
	cm36686->prox_wq = create_singlethread_workqueue("cm36686_prox_wq");
	if (!cm36686->prox_wq) {
		ret = -ENOMEM;
		pr_err("%s: could not create prox workqueue\n", __func__);
		goto err_create_prox_workqueue;
	}
	/* this is the thread function we run on the work queue */
	INIT_WORK(&cm36686->work_prox, cm36686_work_func_prox);

	/* allocate lightsensor input_device */
	cm36686->light_input_dev = input_allocate_device();
	if (!cm36686->light_input_dev) {
		pr_err("%s: could not allocate light input device\n", __func__);
		goto err_input_allocate_device_light;
	}

	input_set_drvdata(cm36686->light_input_dev, cm36686);
	cm36686->light_input_dev->name = "light_sensor";
	input_set_capability(cm36686->light_input_dev, EV_REL, REL_MISC);
	input_set_capability(cm36686->light_input_dev, EV_REL, REL_DIAL);
	input_set_capability(cm36686->light_input_dev, EV_REL, REL_WHEEL);

	ret = input_register_device(cm36686->light_input_dev);
	if (ret < 0) {
		input_free_device(cm36686->light_input_dev);
		pr_err("%s: could not register input device\n", __func__);
		goto err_input_register_device_light;
	}

	ret = sysfs_create_group(&cm36686->light_input_dev->dev.kobj,
				 &light_attribute_group);
	if (ret) {
		pr_err("%s: could not create sysfs group\n", __func__);
		goto err_sysfs_create_group_light;
	}
#if defined(CONFIG_SENSOR_USE_SYMLINK)
	ret =  sensors_initialize_symlink(cm36686->light_input_dev);
	if (ret < 0) {
		pr_err("%s - light_sensors_initialize_symlink error(%d).\n",
                        __func__, ret);
		goto err_create_light_workqueue;
	}
#endif
	/* light_timer settings. we poll for light values using a timer. */
	hrtimer_init(&cm36686->light_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	cm36686->light_poll_delay = ns_to_ktime(200 * NSEC_PER_MSEC);
	cm36686->light_timer.function = cm36686_light_timer_func;

	/* the timer just fires off a work queue request.  we need a thread
	   to read the i2c (can be slow and blocking). */
	cm36686->light_wq = create_singlethread_workqueue("cm36686_light_wq");
	if (!cm36686->light_wq) {
		ret = -ENOMEM;
		pr_err("%s: could not create light workqueue\n", __func__);
		goto err_create_light_workqueue;
	}

	/* this is the thread function we run on the work queue */
	INIT_WORK(&cm36686->work_light, cm36686_work_func_light);

	/* set sysfs for proximity sensor */
	cm36686->proximity_dev = sensors_classdev_register("proximity_sensor");
	if (IS_ERR(cm36686->proximity_dev)) {
		pr_err("%s: could not create proximity_dev\n", __func__);
		goto err_proximity_device_create;
	}

	if (device_create_file(cm36686->proximity_dev, &dev_attr_state) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
			dev_attr_state.attr.name);
		goto err_proximity_device_create_file1;
	}

	if (device_create_file(cm36686->proximity_dev, &attr_prox_raw) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
			attr_prox_raw.attr.name);
		goto err_proximity_device_create_file2;
	}

#ifdef CM36686_CANCELATION
	if (device_create_file(cm36686->proximity_dev,
		&dev_attr_prox_cal) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
			dev_attr_prox_cal.attr.name);
		goto err_proximity_device_create_file3;
	}

	if (device_create_file(cm36686->proximity_dev,
		&dev_attr_prox_offset_pass) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
			dev_attr_prox_offset_pass.attr.name);
		goto err_proximity_device_create_file4;
	}
#endif
	if (device_create_file(cm36686->proximity_dev,
		&dev_attr_prox_avg) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
			dev_attr_prox_avg.attr.name);
		goto err_proximity_device_create_file5;
	}

	if (device_create_file(cm36686->proximity_dev,
		&dev_attr_thresh_high) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
			dev_attr_thresh_high.attr.name);
		goto err_proximity_device_create_file6;
	}

	if (device_create_file(cm36686->proximity_dev,
		&dev_attr_vendor) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
			dev_attr_vendor.attr.name);
		goto err_proximity_device_create_file7;
	}

	if (device_create_file(cm36686->proximity_dev,
		&dev_attr_name) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
			dev_attr_name.attr.name);
		goto err_proximity_device_create_file8;
	}

	if (device_create_file(cm36686->proximity_dev,
		&dev_attr_thresh_low) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
			dev_attr_thresh_low.attr.name);
		goto err_proximity_device_create_file9;
	}

	dev_set_drvdata(cm36686->proximity_dev, cm36686);

	/* set sysfs for light sensor */
	cm36686->light_dev = sensors_classdev_register("light_sensor");
	if (IS_ERR(cm36686->light_dev)) {
		pr_err("%s: could not create light_dev\n", __func__);
		goto err_light_device_create;
	}

	if (device_create_file(cm36686->light_dev, &dev_attr_lux) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
			dev_attr_lux.attr.name);
		goto err_light_device_create_file1;
	}

	if (device_create_file(cm36686->light_dev, &dev_attr_raw_data) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
			dev_attr_raw_data.attr.name);
		goto err_light_device_create_file2;
	}

	if (device_create_file(cm36686->light_dev, &dev_attr_vendor) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
			dev_attr_vendor.attr.name);
		goto err_light_device_create_file3;
	}

	if (device_create_file(cm36686->light_dev, &dev_attr_name) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
			dev_attr_name.attr.name);
		goto err_light_device_create_file4;
	}

	dev_set_drvdata(cm36686->light_dev, cm36686);

	pr_info("%s is success.\n", __func__);
	goto done;

/* error, unwind it all */
err_light_device_create_file4:
	device_remove_file(cm36686->light_dev, &dev_attr_vendor);
err_light_device_create_file3:
	device_remove_file(cm36686->light_dev, &dev_attr_raw_data);
err_light_device_create_file2:
	device_remove_file(cm36686->light_dev, &dev_attr_lux);
err_light_device_create_file1:
	sensors_classdev_unregister(cm36686->light_dev);
err_light_device_create:
	device_remove_file(cm36686->proximity_dev, &dev_attr_thresh_low);
err_proximity_device_create_file9:
	device_remove_file(cm36686->proximity_dev, &dev_attr_name);
err_proximity_device_create_file8:
	device_remove_file(cm36686->proximity_dev, &dev_attr_vendor);
err_proximity_device_create_file7:
	device_remove_file(cm36686->proximity_dev, &dev_attr_thresh_high);
err_proximity_device_create_file6:
	device_remove_file(cm36686->proximity_dev, &dev_attr_prox_avg);
err_proximity_device_create_file5:
#ifdef CM36686_CANCELATION
	device_remove_file(cm36686->proximity_dev, &dev_attr_prox_offset_pass);
err_proximity_device_create_file4:
	device_remove_file(cm36686->proximity_dev, &dev_attr_prox_cal);
err_proximity_device_create_file3:
#endif
	device_remove_file(cm36686->proximity_dev, &attr_prox_raw);
err_proximity_device_create_file2:
	device_remove_file(cm36686->proximity_dev, &dev_attr_state);
err_proximity_device_create_file1:
	sensors_classdev_unregister(cm36686->proximity_dev);
err_proximity_device_create:
	destroy_workqueue(cm36686->light_wq);
err_create_light_workqueue:
	sysfs_remove_group(&cm36686->light_input_dev->dev.kobj,
			   &light_attribute_group);
err_sysfs_create_group_light:
	input_unregister_device(cm36686->light_input_dev);
err_input_register_device_light:
err_input_allocate_device_light:
	destroy_workqueue(cm36686->prox_wq);
err_create_prox_workqueue:
	free_irq(cm36686->irq, cm36686);
	gpio_free(cm36686->pdata->irq);
err_setup_irq:
	sysfs_remove_group(&cm36686->proximity_input_dev->dev.kobj,
			   &proximity_attribute_group);
err_sysfs_create_group_proximity:
	input_unregister_device(cm36686->proximity_input_dev);
err_input_register_device_proximity:
err_input_allocate_device_proximity:
err_setup_reg:
	if (cm36686->pdata->cm36686_led_on)
		cm36686->pdata->cm36686_led_on(false);

	if (cm36686->cm36686_light_vddpower)
		cm36686->cm36686_light_vddpower(false);

	if (cm36686->cm36686_proxi_vddpower)
		cm36686->cm36686_proxi_vddpower(false);

	wake_lock_destroy(&cm36686->prx_wake_lock);
	mutex_destroy(&cm36686->read_lock);
	mutex_destroy(&cm36686->power_lock);
	kfree(cm36686);
done:
	return ret;
}
static int __devinit mma8x5x_probe(struct i2c_client *client,
				   const struct i2c_device_id *id)
{
	int result, chip_id;
	struct input_dev *idev;
	struct mma8x5x_data *pdata;
	struct i2c_adapter *adapter;
	adapter = to_i2c_adapter(client->dev.parent);
	/* power on the device */
	result = mma8x5x_config_regulator(client, 1);
	if (result)
		goto err_power_on;

	result = i2c_check_functionality(adapter,
					 I2C_FUNC_SMBUS_BYTE |
					 I2C_FUNC_SMBUS_BYTE_DATA);
	if (!result)
		goto err_check_id;

	chip_id = i2c_smbus_read_byte_data(client, MMA8X5X_WHO_AM_I);

	if (!mma8x5x_check_id(chip_id)) {
		dev_err(&client->dev,
			"read chip ID 0x%x is not equal to 0x%x,0x%x,0x%x,0x%x,0x%x!\n",
			chip_id, MMA8451_ID, MMA8452_ID, MMA8453_ID,
			MMA8652_ID, MMA8653_ID);
		result = -EINVAL;
		goto err_check_id;
	}
	/* set the private data */
	pdata = kzalloc(sizeof(struct mma8x5x_data), GFP_KERNEL);
	if (!pdata) {
		result = -ENOMEM;
		dev_err(&client->dev, "alloc data memory error!\n");
		goto err_check_id;
	}

	if (client->dev.of_node) {
		result = mma8x5x_parse_dt(&client->dev, pdata);
		if (result)
			goto err_parse_dt;
	} else {
		pdata->position = CONFIG_SENSORS_MMA_POSITION;
		pdata->int_pin = -1;
		pdata->int_flags = 0;
	}

	/* Initialize the MMA8X5X chip */
	pdata->client = client;
	pdata->chip_id = chip_id;
	pdata->mode = MODE_2G;
	pdata->poll_delay = POLL_INTERVAL;

	mutex_init(&pdata->data_lock);
	i2c_set_clientdata(client, pdata);
	/* Initialize the MMA8X5X chip */
	mma8x5x_device_init(client);
	if (pdata->use_int) {
		if (pdata->int_pin >= 0)
			client->irq = gpio_to_irq(pdata->int_pin);

		if (gpio_is_valid(pdata->int_pin)) {
			result = gpio_request(pdata->int_pin,
				"mma8x5x_irq_gpio");
			if (result) {
				dev_err(&client->dev, "irq gpio(%d) request failed",
					pdata->int_pin);
				goto err_request_gpio;
			}
			result = gpio_direction_input(pdata->int_pin);
			if (result) {
				dev_err(&client->dev,
					"set_direction for irq gpio failed\n");
				goto err_set_gpio_direction;
			}
		}
		device_init_wakeup(&client->dev, true);
		enable_irq_wake(client->irq);
		result = request_threaded_irq(client->irq, NULL,
			mma8x5x_interrupt,
			IRQ_TYPE_EDGE_RISING | IRQF_ONESHOT | IRQF_NO_SUSPEND,
			ACCEL_INPUT_DEV_NAME, (void *)client);
		if (result) {
			dev_err(&client->dev, "Could not allocate irq(%d) !\n",
				client->irq);
			goto err_register_irq;
		}
		mma8x5x_device_int_init(client);
	} else {
		INIT_DELAYED_WORK(&pdata->dwork, mma8x5x_dev_poll);
	}
	idev = input_allocate_device();
	if (!idev) {
		result = -ENOMEM;
		dev_err(&client->dev, "alloc input device failed!\n");
		goto err_alloc_poll_device;
	}
	input_set_drvdata(idev, pdata);
	idev->name = ACCEL_INPUT_DEV_NAME;
	idev->uniq = mma8x5x_id2name(pdata->chip_id);
	idev->id.bustype = BUS_I2C;
	idev->evbit[0] = BIT_MASK(EV_ABS);
	input_set_abs_params(idev, ABS_X, -0x7fff, 0x7fff, 0, 0);
	input_set_abs_params(idev, ABS_Y, -0x7fff, 0x7fff, 0, 0);
	input_set_abs_params(idev, ABS_Z, -0x7fff, 0x7fff, 0, 0);
	result = input_register_device(idev);
	if (result) {
		dev_err(&client->dev, "register input device failed!\n");
		goto err_register_device;
	}
	pdata->idev = idev;

	result = sysfs_create_group(&idev->dev.kobj, &mma8x5x_attr_group);
	if (result) {
		dev_err(&client->dev, "create device file failed!\n");
		result = -EINVAL;
		goto err_create_sysfs;
	}
	pdata->cdev = sensors_cdev;
	pdata->cdev.min_delay = POLL_INTERVAL_MIN * 1000;
	pdata->cdev.delay_msec = pdata->poll_delay;
	pdata->cdev.sensors_enable = mma8x5x_enable_set;
	pdata->cdev.sensors_poll_delay = mma8x5x_poll_delay_set;
	result = sensors_classdev_register(&client->dev, &pdata->cdev);
	if (result) {
		dev_err(&client->dev, "create class device file failed!\n");
		result = -EINVAL;
		goto err_create_class_sysfs;
	}
	dev_info(&client->dev,
		"%s:mma8x5x device driver probe successfully, position =%d\n",
		__func__, pdata->position);

	return 0;
err_create_class_sysfs:
	sysfs_remove_group(&idev->dev.kobj, &mma8x5x_attr_group);
err_create_sysfs:
	input_unregister_device(idev);
err_register_device:
	input_free_device(idev);
err_alloc_poll_device:
err_register_irq:
	if (pdata->use_int)
		device_init_wakeup(&client->dev, false);
err_set_gpio_direction:
	if (gpio_is_valid(pdata->int_pin) && pdata->use_int)
		gpio_free(pdata->int_pin);
err_request_gpio:
err_parse_dt:
	kfree(pdata);
err_check_id:
	mma8x5x_config_regulator(client, 0);
err_power_on:
	return result;
}
Пример #11
0
static int __devinit lsm303dlhc_mag_probe(struct i2c_client *client,
        const struct i2c_device_id *id)
{
    struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
    struct lsm303dlhc_mag_platform_data *pdata = client->dev.platform_data;
    struct lsm303dlhc_mag_data *mag;
    int result = 0;

    dev_info(&client->dev, "%s \n", __func__);

    if (!pdata) {
        result = -EINVAL;
        dev_err(&client->dev, "%s: platform data required.\n",
                __func__);
        goto err_no_platform_data;
    }
    mag = kzalloc(sizeof(*mag), GFP_KERNEL);
    if (NULL == mag) {
        result = -ENOMEM;
        goto err_alloc_data_failed;
    }
    mag->client = client;
    mag->poll_interval_ms = pdata->poll_interval_ms;
    mag->range = pdata->range;
    dev_info(&client->dev, "%s:pdata->range:%d\n", __func__, pdata->range);
    i2c_set_clientdata(client, mag);
    if (pdata->power_on)
        mag->power_on = pdata->power_on;
    else
        mag->power_on = lsm303dlhc_mag_power_stub;
    if (pdata->power_off)
        mag->power_off = pdata->power_off;
    else
        mag->power_off = lsm303dlhc_mag_power_stub;
    mag->power_on();
    lsm303dlhc_mag_config_regulator( mag , true);
    msleep(500);
    if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
        result = -EIO;
        goto err_check_functionality;
    }
    result = i2c_smbus_write_byte_data(client, MR_REG_M, IDLE_MODE);
    mag->power_off();
    lsm303dlhc_mag_config_regulator( mag , false);
    if (result) {
        dev_err(&client->dev, "%s: Device not responding.\n",
                __func__);
        goto err_not_responding;
    }
    INIT_DELAYED_WORK(&mag->work, lsm303dlhc_mag_poll_func);
    mutex_init(&mag->lock);

    mag->dev = sensors_classdev_register("magnetometer");

    result = create_sysfs_interfaces(mag->dev);
    if (result)
        goto err_sys_attr;
    dev_set_drvdata(mag->dev, mag);
    mag->input_dev = input_allocate_device();
    if (!mag->input_dev) {
        dev_err(&client->dev, "%s: input_allocate_device failed\n",
                __func__);
        result = -ENOMEM;
        goto err_allocate_device;
    }
    input_set_drvdata(mag->input_dev, mag);

    mag->input_dev->name = "magnetometer";
    set_bit(EV_ABS, mag->input_dev->evbit);
    set_bit(ABS_X, mag->input_dev->absbit);
    set_bit(ABS_Y, mag->input_dev->absbit);
    set_bit(ABS_Z, mag->input_dev->absbit);
    input_set_abs_params(mag->input_dev, ABS_X, -MAG_RANGE_MG,
                         MAG_RANGE_MG - 1, 0, 0);
    input_set_abs_params(mag->input_dev, ABS_Y, -MAG_RANGE_MG,
                         MAG_RANGE_MG - 1, 0, 0);
    input_set_abs_params(mag->input_dev, ABS_Z, -MAG_RANGE_MG,
                         MAG_RANGE_MG - 1, 0, 0);

    result = input_register_device(mag->input_dev);
    if (result) {
        dev_err(&client->dev, "%s: input_register_device failed!",
                __func__);
        goto err_register_device;
    }
    dev_set_drvdata(&mag->input_dev->dev, mag);

    if (device_create_file(&mag->input_dev->dev,
                           &dev_attr_enable) < 0) {
        pr_err("%s: Failed to create device file(%s)!\n", __func__,
               dev_attr_enable.attr.name);
        goto err_check_functionality;
    }

    mag->irq_m = pdata->irq_m;
    if (mag->irq_m > 0) { /* interrupt */

        mag->interruptible = true;
        result = request_threaded_irq(gpio_to_irq(mag->irq_m), NULL,
                                      lsm303dlhc_m_gpio_irq,
                                      IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "lsm303dlhc_m",
                                      mag);
        if (result) {
            dev_err(&client->dev, "request irq EGPIO_PIN_1 failed\n");
            goto err_check_functionality;
        }

        disable_irq(gpio_to_irq(mag->irq_m));
    }
    mag->interruptible = false;
    dev_info(&client->dev, "%s mag->interruptible=%d completed.\n", __func__, mag->interruptible);
    return 0;

err_register_device:
    input_free_device(mag->input_dev);
err_allocate_device:
    remove_sysfs_interfaces(mag->dev);
err_sys_attr:
err_not_responding:
    kfree(mag);
err_alloc_data_failed:
err_no_platform_data:
err_check_functionality:
    dev_err(&client->dev, "%s failed.\n", __func__);
    return result;
}