* [RFC][PATCH1/2] SFH7741: proximity sensor driver support
@ 2010-05-03  5:46 Datta, Shubhrajyoti
  2010-05-03  7:56 ` Hemanth V
  0 siblings, 1 reply; 4+ messages in thread
From: Datta, Shubhrajyoti @ 2010-05-03  5:46 UTC (permalink / raw)
  To: linux-input@vger.kernel.org, linux-omap@vger.kernel.org
  Cc: Ossi.Kauppinen@vti.fi, Datta, Shubhrajyoti
From: Datta, Shubhrajyoti 
Sent: Monday, May 03, 2010 11:07 AM
To: Datta, Shubhrajyoti
Subject: [RFC][PATCH1/2] SFH7741: proximity sensor driver support
Driver support for the proximity sensor SFH7741.
Signed-off-by: Shubhro <a0393217@ti.com>
---
 drivers/input/misc/Kconfig    |    9 ++
 drivers/input/misc/Makefile   |    1 +
 drivers/input/misc/sfh7741.c  |  308 +++++++++++++++++++++++++++++++++++++++++
 include/linux/input/sfh7741.h |   14 ++
 4 files changed, 332 insertions(+), 0 deletions(-)
 create mode 100644 drivers/input/misc/sfh7741.c
 create mode 100644 include/linux/input/sfh7741.h
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 16ec523..5919358 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -319,4 +319,13 @@ config INPUT_PCAP
 	  To compile this driver as a module, choose M here: the
 	  module will be called pcap_keys.
 
+config SENSORS_SFH7741
+	tristate "Proximity sensor"
+	default y
+	help
+	  Say Y here if you want to use proximity sensor sfh7741.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called sfh7741.
+
 endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index a8b8485..b2cac12 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -30,4 +30,5 @@ obj-$(CONFIG_INPUT_WINBOND_CIR)		+= winbond-cir.o
 obj-$(CONFIG_INPUT_WISTRON_BTNS)	+= wistron_btns.o
 obj-$(CONFIG_INPUT_WM831X_ON)		+= wm831x-on.o
 obj-$(CONFIG_INPUT_YEALINK)		+= yealink.o
+obj-$(CONFIG_SENSORS_SFH7741)		+= sfh7741.o
 
diff --git a/drivers/input/misc/sfh7741.c b/drivers/input/misc/sfh7741.c
new file mode 100644
index 0000000..b4febfe
--- /dev/null
+++ b/drivers/input/misc/sfh7741.c
@@ -0,0 +1,308 @@
+/*
+ * sfh7741.c
+ *
+ * SFH7741 Proximity Driver
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * Author: Shubhrajyoti Datta <a0393217@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/interrupt.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/gpio.h>
+#include <linux/input/sfh7741.h>
+
+struct sfh7741_drvdata {
+	struct input_dev *input;
+	int proximity_out;
+	int gpio_en;
+};
+
+static DEFINE_MUTEX(prox_enable_mutex);
+static int prox_enable = 1;
+
+static irqreturn_t sfh7741_isr(int irq, void *dev_id)
+{
+	struct sfh7741_drvdata *ddata = dev_id;
+
+	int proximity = gpio_get_value(ddata->proximity_out);
+	input_report_abs(ddata->input, ABS_DISTANCE, proximity);
+	input_sync(ddata->input);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit sfh7741_setup(struct device *dev,
+					struct sfh7741_drvdata *ddata
+					 )
+{
+	int  error;
+	char *desc = "sfh7741";
+
+	error = gpio_request(ddata->proximity_out, desc);
+	if (error < 0) {
+		dev_err(dev, "failed to request GPIO %d, error %d\n",
+			ddata->proximity_out, error);
+		return error;
+	}
+
+	error = gpio_direction_input(ddata->proximity_out);
+	if (error < 0) {
+		dev_err(dev, "failed to configure direction for GPIO %d,\
+				error %d\n", ddata->proximity_out, error);
+		goto fail1;
+	}
+
+	error = request_threaded_irq(gpio_to_irq(ddata->proximity_out) , NULL ,
+				sfh7741_isr,
+				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
+				| IRQF_ONESHOT,
+				desc, ddata);
+	if (error) {
+		dev_err(dev, "Unable to claim irq %d; error %d\n",
+			gpio_to_irq(ddata->proximity_out), error);
+		goto fail1;
+	}
+
+	error = gpio_request(ddata->gpio_en, desc);
+	if (error < 0) {
+		dev_err(dev, "failed to request GPIO %d, error %d\n",
+			ddata->gpio_en, error);
+		goto fail2;
+	}
+
+	error = gpio_direction_output(ddata->gpio_en , 1);
+	if (error < 0) {
+		dev_err(dev, "%s: GPIO configuration failed: GPIO %d,\
+			error %d\n",__func__, ddata->gpio_en, error);
+		goto fail3;
+	}
+	return 0;
+
+fail3:
+	gpio_free(ddata->gpio_en);
+fail2:
+	free_irq(gpio_to_irq(ddata->proximity_out), &ddata);
+fail1:
+	gpio_free(ddata->proximity_out);
+	return error;
+}
+
+static ssize_t set_prox_state(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	int state , error;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct sfh7741_drvdata *ddata = platform_get_drvdata(pdev);
+
+	if (sscanf(buf, "%u", &state) != 1)
+		return -EINVAL;
+
+	if ((state != 1) && (state != 0))
+		return -EINVAL;
+
+	error = gpio_direction_output(ddata->gpio_en , state);
+	if (error < 0) {
+		dev_err(dev, "%s: GPIO configuration failed: GPIO %d,\
+			error %d\n",__func__, ddata->gpio_en, error);
+	}
+	mutex_lock(&prox_enable_mutex);
+	if (state != prox_enable) {
+		if (state)
+			enable_irq(gpio_to_irq(ddata->proximity_out));
+		else
+			disable_irq(gpio_to_irq(ddata->proximity_out));
+		prox_enable = state;
+	}
+	mutex_unlock(&prox_enable_mutex);
+	return strnlen(buf, count);
+}
+
+static ssize_t show_prox_state(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	return sprintf(buf, "%u\n", prox_enable);
+}
+static DEVICE_ATTR(state, S_IWUSR | S_IRUGO, show_prox_state, set_prox_state);
+
+static ssize_t show_proximity(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	int proximity;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct sfh7741_drvdata *ddata = platform_get_drvdata(pdev);
+
+	proximity = gpio_get_value(ddata->proximity_out);
+	return sprintf(buf, "%u\n", proximity);
+}
+static DEVICE_ATTR(proximity, S_IRUGO, show_proximity, NULL);
+
+static struct attribute *sfh7741_attributes[] = {
+	&dev_attr_state.attr,
+	&dev_attr_proximity.attr,
+	NULL
+};
+
+static const struct attribute_group sfh7741_attr_group = {
+	.attrs = sfh7741_attributes,
+};
+
+static int __devinit sfh7741_probe(struct platform_device *pdev)
+{
+	struct sfh7741_platform_data *pdata = pdev->dev.platform_data;
+	struct sfh7741_drvdata *ddata;
+	struct device *dev = &pdev->dev;
+	struct input_dev *input;
+	int  error;
+
+	pr_info("SFH7741: Proximity sensor\n");
+
+	ddata = kzalloc(sizeof(struct sfh7741_drvdata),
+			GFP_KERNEL);
+	input = input_allocate_device();
+	if (!ddata || !input) {
+		dev_err(dev, "failed to allocate input device\n");
+		return -ENOMEM;
+	}
+
+	input->name = pdev->name;
+	input->phys = "sfh7741/input0";
+	input->dev.parent = &pdev->dev;
+
+	input->id.bustype = BUS_HOST;
+	ddata->proximity_out = pdata->gpio_intr;
+	ddata->gpio_en = pdata->gpio_en;
+
+	ddata->input = input;
+	__set_bit(EV_ABS, input->evbit);
+
+	input_set_abs_params(input, ABS_DISTANCE, 0, 1, 0, 0);
+
+	error = input_register_device(input);
+	if (error) {
+		dev_err(dev, "Unable to register input device,error: %d\n"
+				, error);
+		goto fail1;
+	}
+
+	platform_set_drvdata(pdev, ddata);
+	error = sfh7741_setup(dev, ddata);
+	if (error)
+		goto fail2;
+
+	error = sysfs_create_group(&dev->kobj, &sfh7741_attr_group);
+	if (error)
+		dev_err(dev, "failed to create sysfs entries \n");
+
+	return 0;
+
+fail2:
+	input_unregister_device(input);
+	platform_set_drvdata(pdev, NULL);
+fail1:
+	input_free_device(input);
+	kfree(ddata);
+	return error;
+
+}
+
+static int __devexit sfh7741_remove(struct platform_device *pdev)
+{
+	struct sfh7741_drvdata *ddata = platform_get_drvdata(pdev);
+	int irq ;
+	struct device *dev = &pdev->dev;
+
+	sysfs_remove_group(&dev->kobj, &sfh7741_attr_group);
+	gpio_free(ddata->gpio_en);
+
+	irq = gpio_to_irq(ddata->proximity_out);
+	free_irq(irq, (void *)ddata);
+	gpio_free(ddata->proximity_out);
+
+	input_unregister_device(ddata->input);
+	kfree(ddata);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int sfh7741_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct sfh7741_drvdata *ddata = platform_get_drvdata(pdev);
+
+	error = gpio_direction_output(ddata->gpio_en , 0);
+	if (error < 0) {
+		dev_err(dev, "%s: GPIO configuration failed: GPIO %d,\
+			error %d\n",__func__, ddata->gpio_en, error);
+	}
+	return 0;
+}
+
+static int sfh7741_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct sfh7741_drvdata *ddata = platform_get_drvdata(pdev);
+
+	error = gpio_direction_output(ddata->gpio_en , 1);
+	if (error < 0) {
+		dev_err(dev, "%s: GPIO configuration failed: GPIO %d,\
+			error %d\n",__func__, ddata->gpio_en, error);
+	}
+	return 0;
+}
+
+static const struct dev_pm_ops sfh7741_pm_ops = {
+	.suspend	= sfh7741_suspend,
+	.resume		= sfh7741_resume,
+};
+#endif
+
+static struct platform_driver sfh7741_device_driver = {
+	.probe		= sfh7741_probe,
+	.remove		= __devexit_p(sfh7741_remove),
+	.driver		= {
+		.name	= "sfh7741",
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &sfh7741_pm_ops,
+#endif
+	}
+};
+
+static int __init sfh7741_init(void)
+{
+	return platform_driver_register(&sfh7741_device_driver);
+}
+
+static void __exit sfh7741_exit(void)
+{
+	platform_driver_unregister(&sfh7741_device_driver);
+}
+
+module_init(sfh7741_init);
+module_exit(sfh7741_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION("Proximity driver ");
+MODULE_ALIAS("platform:sfh7741");
+
diff --git a/include/linux/input/sfh7741.h b/include/linux/input/sfh7741.h
new file mode 100644
index 0000000..801c971
--- /dev/null
+++ b/include/linux/input/sfh7741.h
@@ -0,0 +1,14 @@
+/*
+ * Configuration and driver data for Proximity driver.
+ */
+
+#ifndef __SFH7741_H
+#define __SFH7741_H
+
+struct sfh7741_platform_data {
+	int gpio_intr;
+	int gpio_en;
+};
+
+#endif
+
-- 
1.5.4.7
^ permalink raw reply related	[flat|nested] 4+ messages in thread
* Re: [RFC][PATCH1/2] SFH7741: proximity sensor driver support
  2010-05-03  5:46 [RFC][PATCH1/2] SFH7741: proximity sensor driver support Datta, Shubhrajyoti
@ 2010-05-03  7:56 ` Hemanth V
  2010-05-03  9:07   ` Datta, Shubhrajyoti
  0 siblings, 1 reply; 4+ messages in thread
From: Hemanth V @ 2010-05-03  7:56 UTC (permalink / raw)
  To: Datta, Shubhrajyoti, linux-input, linux-omap
----- Original Message ----- 
From: "Datta, Shubhrajyoti" <shubhrajyoti@ti.com>
>
> From: Datta, Shubhrajyoti
> Sent: Monday, May 03, 2010 11:07 AM
> To: Datta, Shubhrajyoti
> Subject: [RFC][PATCH1/2] SFH7741: proximity sensor driver support
>
> Driver support for the proximity sensor SFH7741.
>
> Signed-off-by: Shubhro <a0393217@ti.com>
> ---
> drivers/input/misc/Kconfig    |    9 ++
> drivers/input/misc/Makefile   |    1 +
> drivers/input/misc/sfh7741.c  |  308 
> +++++++++++++++++++++++++++++++++++++++++
> include/linux/input/sfh7741.h |   14 ++
> 4 files changed, 332 insertions(+), 0 deletions(-)
> create mode 100644 drivers/input/misc/sfh7741.c
> create mode 100644 include/linux/input/sfh7741.h
>
> diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
> index 16ec523..5919358 100644
> --- a/drivers/input/misc/Kconfig
> +++ b/drivers/input/misc/Kconfig
> @@ -319,4 +319,13 @@ config INPUT_PCAP
>    To compile this driver as a module, choose M here: the
>    module will be called pcap_keys.
>
> +config SENSORS_SFH7741
> + tristate "Proximity sensor"
> + default y
> + help
> +   Say Y here if you want to use proximity sensor sfh7741.
> +
> +   To compile this driver as a module, choose M here: the
> +   module will be called sfh7741.
> +
> endif
> diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
> index a8b8485..b2cac12 100644
> --- a/drivers/input/misc/Makefile
> +++ b/drivers/input/misc/Makefile
> @@ -30,4 +30,5 @@ obj-$(CONFIG_INPUT_WINBOND_CIR) += winbond-cir.o
> obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o
> obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
> obj-$(CONFIG_INPUT_YEALINK) += yealink.o
> +obj-$(CONFIG_SENSORS_SFH7741) += sfh7741.o
>
> diff --git a/drivers/input/misc/sfh7741.c b/drivers/input/misc/sfh7741.c
> new file mode 100644
> index 0000000..b4febfe
> --- /dev/null
> +++ b/drivers/input/misc/sfh7741.c
> @@ -0,0 +1,308 @@
> +/*
> + * sfh7741.c
> + *
> + * SFH7741 Proximity Driver
> + *
> + * Copyright (C) 2010 Texas Instruments
> + *
> + * Author: Shubhrajyoti Datta <a0393217@ti.com>
> + *
> + * This program is free software; you can redistribute it and/or modify 
> it
> + * under the terms of the GNU General Public License version 2 as 
> published by
> + * the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 
> USA
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/pm.h>
> +#include <linux/platform_device.h>
> +#include <linux/input.h>
> +#include <linux/gpio.h>
> +#include <linux/input/sfh7741.h>
> +
> +struct sfh7741_drvdata {
> + struct input_dev *input;
> + int proximity_out;
> + int gpio_en;
> +};
> +
> +static DEFINE_MUTEX(prox_enable_mutex);
This mutex can be included as part of driver data structure
> +static int prox_enable = 1;
Same comment as above
> +
> +static irqreturn_t sfh7741_isr(int irq, void *dev_id)
> +{
> + struct sfh7741_drvdata *ddata = dev_id;
> +
> + int proximity = gpio_get_value(ddata->proximity_out);
> + input_report_abs(ddata->input, ABS_DISTANCE, proximity);
> + input_sync(ddata->input);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int __devinit sfh7741_setup(struct device *dev,
> + struct sfh7741_drvdata *ddata
> + )
> +{
> + int  error;
> + char *desc = "sfh7741";
> +
> + error = gpio_request(ddata->proximity_out, desc);
> + if (error < 0) {
> + dev_err(dev, "failed to request GPIO %d, error %d\n",
> + ddata->proximity_out, error);
> + return error;
> + }
> +
> + error = gpio_direction_input(ddata->proximity_out);
> + if (error < 0) {
> + dev_err(dev, "failed to configure direction for GPIO %d,\
> + error %d\n", ddata->proximity_out, error);
> + goto fail1;
> + }
> +
General comment about GPIO,
It might be better to have GPIO configuration as part of board file,
rather than being part of the driver. This is should make the driver
more generic.
> + error = request_threaded_irq(gpio_to_irq(ddata->proximity_out) , NULL ,
> + sfh7741_isr,
> + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
> + | IRQF_ONESHOT,
> + desc, ddata);
> + if (error) {
> + dev_err(dev, "Unable to claim irq %d; error %d\n",
> + gpio_to_irq(ddata->proximity_out), error);
> + goto fail1;
> + }
> +
> + error = gpio_request(ddata->gpio_en, desc);
> + if (error < 0) {
> + dev_err(dev, "failed to request GPIO %d, error %d\n",
> + ddata->gpio_en, error);
> + goto fail2;
> + }
> +
> + error = gpio_direction_output(ddata->gpio_en , 1);
> + if (error < 0) {
> + dev_err(dev, "%s: GPIO configuration failed: GPIO %d,\
> + error %d\n",__func__, ddata->gpio_en, error);
> + goto fail3;
> + }
> + return 0;
> +
> +fail3:
> + gpio_free(ddata->gpio_en);
> +fail2:
> + free_irq(gpio_to_irq(ddata->proximity_out), &ddata);
> +fail1:
> + gpio_free(ddata->proximity_out);
> + return error;
> +}
> +
> +static ssize_t set_prox_state(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + int state , error;
> + struct platform_device *pdev = to_platform_device(dev);
> + struct sfh7741_drvdata *ddata = platform_get_drvdata(pdev);
> +
> + if (sscanf(buf, "%u", &state) != 1)
> + return -EINVAL;
> +
> + if ((state != 1) && (state != 0))
> + return -EINVAL;
> +
> + error = gpio_direction_output(ddata->gpio_en , state);
> + if (error < 0) {
> + dev_err(dev, "%s: GPIO configuration failed: GPIO %d,\
> + error %d\n",__func__, ddata->gpio_en, error);
> + }
> + mutex_lock(&prox_enable_mutex);
> + if (state != prox_enable) {
> + if (state)
> + enable_irq(gpio_to_irq(ddata->proximity_out));
> + else
> + disable_irq(gpio_to_irq(ddata->proximity_out));
> + prox_enable = state;
> + }
> + mutex_unlock(&prox_enable_mutex);
> + return strnlen(buf, count);
> +}
> +
> +static ssize_t show_prox_state(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + return sprintf(buf, "%u\n", prox_enable);
> +}
> +static DEVICE_ATTR(state, S_IWUSR | S_IRUGO, show_prox_state, 
> set_prox_state);
> +
> +static ssize_t show_proximity(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + int proximity;
> + struct platform_device *pdev = to_platform_device(dev);
> + struct sfh7741_drvdata *ddata = platform_get_drvdata(pdev);
> +
> + proximity = gpio_get_value(ddata->proximity_out);
> + return sprintf(buf, "%u\n", proximity);
> +}
> +static DEVICE_ATTR(proximity, S_IRUGO, show_proximity, NULL);
> +
> +static struct attribute *sfh7741_attributes[] = {
> + &dev_attr_state.attr,
> + &dev_attr_proximity.attr,
> + NULL
> +};
> +
> +static const struct attribute_group sfh7741_attr_group = {
> + .attrs = sfh7741_attributes,
> +};
> +
> +static int __devinit sfh7741_probe(struct platform_device *pdev)
> +{
> + struct sfh7741_platform_data *pdata = pdev->dev.platform_data;
> + struct sfh7741_drvdata *ddata;
> + struct device *dev = &pdev->dev;
> + struct input_dev *input;
> + int  error;
> +
> + pr_info("SFH7741: Proximity sensor\n");
> +
> + ddata = kzalloc(sizeof(struct sfh7741_drvdata),
> + GFP_KERNEL);
> + input = input_allocate_device();
> + if (!ddata || !input) {
> + dev_err(dev, "failed to allocate input device\n");
> + return -ENOMEM;
> + }
> +
> + input->name = pdev->name;
> + input->phys = "sfh7741/input0";
> + input->dev.parent = &pdev->dev;
> +
> + input->id.bustype = BUS_HOST;
> + ddata->proximity_out = pdata->gpio_intr;
> + ddata->gpio_en = pdata->gpio_en;
> +
> + ddata->input = input;
> + __set_bit(EV_ABS, input->evbit);
> +
> + input_set_abs_params(input, ABS_DISTANCE, 0, 1, 0, 0);
> +
> + error = input_register_device(input);
> + if (error) {
> + dev_err(dev, "Unable to register input device,error: %d\n"
> + , error);
> + goto fail1;
> + }
> +
> + platform_set_drvdata(pdev, ddata);
> + error = sfh7741_setup(dev, ddata);
> + if (error)
> + goto fail2;
> +
> + error = sysfs_create_group(&dev->kobj, &sfh7741_attr_group);
> + if (error)
> + dev_err(dev, "failed to create sysfs entries \n");
> +
> + return 0;
> +
> +fail2:
> + input_unregister_device(input);
> + platform_set_drvdata(pdev, NULL);
> +fail1:
> + input_free_device(input);
> + kfree(ddata);
> + return error;
> +
> +}
> +
> +static int __devexit sfh7741_remove(struct platform_device *pdev)
> +{
> + struct sfh7741_drvdata *ddata = platform_get_drvdata(pdev);
> + int irq ;
> + struct device *dev = &pdev->dev;
> +
> + sysfs_remove_group(&dev->kobj, &sfh7741_attr_group);
> + gpio_free(ddata->gpio_en);
> +
> + irq = gpio_to_irq(ddata->proximity_out);
> + free_irq(irq, (void *)ddata);
> + gpio_free(ddata->proximity_out);
> +
> + input_unregister_device(ddata->input);
> + kfree(ddata);
> + return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int sfh7741_suspend(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct sfh7741_drvdata *ddata = platform_get_drvdata(pdev);
> +
> + error = gpio_direction_output(ddata->gpio_en , 0);
> + if (error < 0) {
> + dev_err(dev, "%s: GPIO configuration failed: GPIO %d,\
> + error %d\n",__func__, ddata->gpio_en, error);
> + }
> + return 0;
> +}
> +
> +static int sfh7741_resume(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct sfh7741_drvdata *ddata = platform_get_drvdata(pdev);
> +
> + error = gpio_direction_output(ddata->gpio_en , 1);
> + if (error < 0) {
> + dev_err(dev, "%s: GPIO configuration failed: GPIO %d,\
> + error %d\n",__func__, ddata->gpio_en, error);
> + }
> + return 0;
> +}
> +
> +static const struct dev_pm_ops sfh7741_pm_ops = {
> + .suspend = sfh7741_suspend,
> + .resume = sfh7741_resume,
> +};
> +#endif
> +
> +static struct platform_driver sfh7741_device_driver = {
> + .probe = sfh7741_probe,
> + .remove = __devexit_p(sfh7741_remove),
> + .driver = {
> + .name = "sfh7741",
> + .owner = THIS_MODULE,
> +#ifdef CONFIG_PM
> + .pm = &sfh7741_pm_ops,
> +#endif
> + }
> +};
> +
> +static int __init sfh7741_init(void)
> +{
> + return platform_driver_register(&sfh7741_device_driver);
> +}
> +
> +static void __exit sfh7741_exit(void)
> +{
> + platform_driver_unregister(&sfh7741_device_driver);
> +}
> +
> +module_init(sfh7741_init);
> +module_exit(sfh7741_exit);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Texas Instruments");
> +MODULE_DESCRIPTION("Proximity driver ");
> +MODULE_ALIAS("platform:sfh7741");
> +
> diff --git a/include/linux/input/sfh7741.h b/include/linux/input/sfh7741.h
> new file mode 100644
> index 0000000..801c971
> --- /dev/null
> +++ b/include/linux/input/sfh7741.h
> @@ -0,0 +1,14 @@
> +/*
> + * Configuration and driver data for Proximity driver.
> + */
> +
> +#ifndef __SFH7741_H
> +#define __SFH7741_H
> +
> +struct sfh7741_platform_data {
> + int gpio_intr;
> + int gpio_en;
> +};
> +
> +#endif
> +
> -- 
> 1.5.4.7
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
^ permalink raw reply	[flat|nested] 4+ messages in thread
* RE: [RFC][PATCH1/2] SFH7741: proximity sensor driver support
  2010-05-03  7:56 ` Hemanth V
@ 2010-05-03  9:07   ` Datta, Shubhrajyoti
  2010-05-04  6:16     ` Hemanth V
  0 siblings, 1 reply; 4+ messages in thread
From: Datta, Shubhrajyoti @ 2010-05-03  9:07 UTC (permalink / raw)
  To: V, Hemanth, linux-input@vger.kernel.org,
	linux-omap@vger.kernel.org
> -----Original Message-----
> From: V, Hemanth
> Sent: Monday, May 03, 2010 1:27 PM
> To: Datta, Shubhrajyoti; linux-input@vger.kernel.org; linux-
> omap@vger.kernel.org
> Subject: Re: [RFC][PATCH1/2] SFH7741: proximity sensor driver support
> 
> ----- Original Message -----
> From: "Datta, Shubhrajyoti" <shubhrajyoti@ti.com>
> >
> > From: Datta, Shubhrajyoti
> > Sent: Monday, May 03, 2010 11:07 AM
> > To: Datta, Shubhrajyoti
> > Subject: [RFC][PATCH1/2] SFH7741: proximity sensor driver support
> >
> > Driver support for the proximity sensor SFH7741.
> >
> > Signed-off-by: Shubhro <a0393217@ti.com>
> > ---
> > drivers/input/misc/Kconfig    |    9 ++
> > drivers/input/misc/Makefile   |    1 +
> > drivers/input/misc/sfh7741.c  |  308
> > +++++++++++++++++++++++++++++++++++++++++
> > include/linux/input/sfh7741.h |   14 ++
> > 4 files changed, 332 insertions(+), 0 deletions(-)
> > create mode 100644 drivers/input/misc/sfh7741.c
> > create mode 100644 include/linux/input/sfh7741.h
> >
> > diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
> > index 16ec523..5919358 100644
> > --- a/drivers/input/misc/Kconfig
> > +++ b/drivers/input/misc/Kconfig
> > @@ -319,4 +319,13 @@ config INPUT_PCAP
> >    To compile this driver as a module, choose M here: the
> >    module will be called pcap_keys.
> >
> > +config SENSORS_SFH7741
> > + tristate "Proximity sensor"
> > + default y
> > + help
> > +   Say Y here if you want to use proximity sensor sfh7741.
> > +
> > +   To compile this driver as a module, choose M here: the
> > +   module will be called sfh7741.
> > +
> > endif
> > diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
> > index a8b8485..b2cac12 100644
> > --- a/drivers/input/misc/Makefile
> > +++ b/drivers/input/misc/Makefile
> > @@ -30,4 +30,5 @@ obj-$(CONFIG_INPUT_WINBOND_CIR) += winbond-cir.o
> > obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o
> > obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
> > obj-$(CONFIG_INPUT_YEALINK) += yealink.o
> > +obj-$(CONFIG_SENSORS_SFH7741) += sfh7741.o
> >
> > diff --git a/drivers/input/misc/sfh7741.c b/drivers/input/misc/sfh7741.c
> > new file mode 100644
> > index 0000000..b4febfe
> > --- /dev/null
> > +++ b/drivers/input/misc/sfh7741.c
> > @@ -0,0 +1,308 @@
> > +/*
> > + * sfh7741.c
> > + *
> > + * SFH7741 Proximity Driver
> > + *
> > + * Copyright (C) 2010 Texas Instruments
> > + *
> > + * Author: Shubhrajyoti Datta <a0393217@ti.com>
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > it
> > + * under the terms of the GNU General Public License version 2 as
> > published by
> > + * the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU General Public License
> > + * along with this program; if not, write to the Free Software
> > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
> > USA
> > + */
> > +
> > +#include <linux/interrupt.h>
> > +#include <linux/pm.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/input.h>
> > +#include <linux/gpio.h>
> > +#include <linux/input/sfh7741.h>
> > +
> > +struct sfh7741_drvdata {
> > + struct input_dev *input;
> > + int proximity_out;
> > + int gpio_en;
> > +};
> > +
> > +static DEFINE_MUTEX(prox_enable_mutex);
> 
> This mutex can be included as part of driver data structure
> 
> > +static int prox_enable = 1;
> 
> Same comment as above
Agreed.
> 
> > +
> > +static irqreturn_t sfh7741_isr(int irq, void *dev_id)
> > +{
> > + struct sfh7741_drvdata *ddata = dev_id;
> > +
> > + int proximity = gpio_get_value(ddata->proximity_out);
> > + input_report_abs(ddata->input, ABS_DISTANCE, proximity);
> > + input_sync(ddata->input);
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +static int __devinit sfh7741_setup(struct device *dev,
> > + struct sfh7741_drvdata *ddata
> > + )
> > +{
> > + int  error;
> > + char *desc = "sfh7741";
> > +
> > + error = gpio_request(ddata->proximity_out, desc);
> > + if (error < 0) {
> > + dev_err(dev, "failed to request GPIO %d, error %d\n",
> > + ddata->proximity_out, error);
> > + return error;
> > + }
> > +
> > + error = gpio_direction_input(ddata->proximity_out);
> > + if (error < 0) {
> > + dev_err(dev, "failed to configure direction for GPIO %d,\
> > + error %d\n", ddata->proximity_out, error);
> > + goto fail1;
> > + }
> > +
> 
> General comment about GPIO,
> It might be better to have GPIO configuration as part of board file,
> rather than being part of the driver. This is should make the driver
> more generic.
I read GPIO in the ISR how can I take care of that? 
> 
> > + error = request_threaded_irq(gpio_to_irq(ddata->proximity_out) , NULL
> ,
> > + sfh7741_isr,
> > + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
> > + | IRQF_ONESHOT,
> > + desc, ddata);
> > + if (error) {
> > + dev_err(dev, "Unable to claim irq %d; error %d\n",
> > + gpio_to_irq(ddata->proximity_out), error);
> > + goto fail1;
> > + }
> > +
> > + error = gpio_request(ddata->gpio_en, desc);
> > + if (error < 0) {
> > + dev_err(dev, "failed to request GPIO %d, error %d\n",
> > + ddata->gpio_en, error);
> > + goto fail2;
> > + }
> > +
> > + error = gpio_direction_output(ddata->gpio_en , 1);
> > + if (error < 0) {
> > + dev_err(dev, "%s: GPIO configuration failed: GPIO %d,\
> > + error %d\n",__func__, ddata->gpio_en, error);
> > + goto fail3;
> > + }
> > + return 0;
> > +
> > +fail3:
> > + gpio_free(ddata->gpio_en);
> > +fail2:
> > + free_irq(gpio_to_irq(ddata->proximity_out), &ddata);
> > +fail1:
> > + gpio_free(ddata->proximity_out);
> > + return error;
> > +}
> > +
> > +static ssize_t set_prox_state(struct device *dev,
> > + struct device_attribute *attr,
> > + const char *buf, size_t count)
> > +{
> > + int state , error;
> > + struct platform_device *pdev = to_platform_device(dev);
> > + struct sfh7741_drvdata *ddata = platform_get_drvdata(pdev);
> > +
> > + if (sscanf(buf, "%u", &state) != 1)
> > + return -EINVAL;
> > +
> > + if ((state != 1) && (state != 0))
> > + return -EINVAL;
> > +
> > + error = gpio_direction_output(ddata->gpio_en , state);
> > + if (error < 0) {
> > + dev_err(dev, "%s: GPIO configuration failed: GPIO %d,\
> > + error %d\n",__func__, ddata->gpio_en, error);
> > + }
> > + mutex_lock(&prox_enable_mutex);
> > + if (state != prox_enable) {
> > + if (state)
> > + enable_irq(gpio_to_irq(ddata->proximity_out));
> > + else
> > + disable_irq(gpio_to_irq(ddata->proximity_out));
> > + prox_enable = state;
> > + }
> > + mutex_unlock(&prox_enable_mutex);
> > + return strnlen(buf, count);
> > +}
> > +
> > +static ssize_t show_prox_state(struct device *dev,
> > + struct device_attribute *attr,
> > + char *buf)
> > +{
> > + return sprintf(buf, "%u\n", prox_enable);
> > +}
> > +static DEVICE_ATTR(state, S_IWUSR | S_IRUGO, show_prox_state,
> > set_prox_state);
> > +
> > +static ssize_t show_proximity(struct device *dev,
> > + struct device_attribute *attr,
> > + char *buf)
> > +{
> > + int proximity;
> > + struct platform_device *pdev = to_platform_device(dev);
> > + struct sfh7741_drvdata *ddata = platform_get_drvdata(pdev);
> > +
> > + proximity = gpio_get_value(ddata->proximity_out);
> > + return sprintf(buf, "%u\n", proximity);
> > +}
> > +static DEVICE_ATTR(proximity, S_IRUGO, show_proximity, NULL);
> > +
> > +static struct attribute *sfh7741_attributes[] = {
> > + &dev_attr_state.attr,
> > + &dev_attr_proximity.attr,
> > + NULL
> > +};
> > +
> > +static const struct attribute_group sfh7741_attr_group = {
> > + .attrs = sfh7741_attributes,
> > +};
> > +
> > +static int __devinit sfh7741_probe(struct platform_device *pdev)
> > +{
> > + struct sfh7741_platform_data *pdata = pdev->dev.platform_data;
> > + struct sfh7741_drvdata *ddata;
> > + struct device *dev = &pdev->dev;
> > + struct input_dev *input;
> > + int  error;
> > +
> > + pr_info("SFH7741: Proximity sensor\n");
> > +
> > + ddata = kzalloc(sizeof(struct sfh7741_drvdata),
> > + GFP_KERNEL);
> > + input = input_allocate_device();
> > + if (!ddata || !input) {
> > + dev_err(dev, "failed to allocate input device\n");
> > + return -ENOMEM;
> > + }
> > +
> > + input->name = pdev->name;
> > + input->phys = "sfh7741/input0";
> > + input->dev.parent = &pdev->dev;
> > +
> > + input->id.bustype = BUS_HOST;
> > + ddata->proximity_out = pdata->gpio_intr;
> > + ddata->gpio_en = pdata->gpio_en;
> > +
> > + ddata->input = input;
> > + __set_bit(EV_ABS, input->evbit);
> > +
> > + input_set_abs_params(input, ABS_DISTANCE, 0, 1, 0, 0);
> > +
> > + error = input_register_device(input);
> > + if (error) {
> > + dev_err(dev, "Unable to register input device,error: %d\n"
> > + , error);
> > + goto fail1;
> > + }
> > +
> > + platform_set_drvdata(pdev, ddata);
> > + error = sfh7741_setup(dev, ddata);
> > + if (error)
> > + goto fail2;
> > +
> > + error = sysfs_create_group(&dev->kobj, &sfh7741_attr_group);
> > + if (error)
> > + dev_err(dev, "failed to create sysfs entries \n");
> > +
> > + return 0;
> > +
> > +fail2:
> > + input_unregister_device(input);
> > + platform_set_drvdata(pdev, NULL);
> > +fail1:
> > + input_free_device(input);
> > + kfree(ddata);
> > + return error;
> > +
> > +}
> > +
> > +static int __devexit sfh7741_remove(struct platform_device *pdev)
> > +{
> > + struct sfh7741_drvdata *ddata = platform_get_drvdata(pdev);
> > + int irq ;
> > + struct device *dev = &pdev->dev;
> > +
> > + sysfs_remove_group(&dev->kobj, &sfh7741_attr_group);
> > + gpio_free(ddata->gpio_en);
> > +
> > + irq = gpio_to_irq(ddata->proximity_out);
> > + free_irq(irq, (void *)ddata);
> > + gpio_free(ddata->proximity_out);
> > +
> > + input_unregister_device(ddata->input);
> > + kfree(ddata);
> > + return 0;
> > +}
> > +
> > +#ifdef CONFIG_PM
> > +static int sfh7741_suspend(struct device *dev)
> > +{
> > + struct platform_device *pdev = to_platform_device(dev);
> > + struct sfh7741_drvdata *ddata = platform_get_drvdata(pdev);
> > +
> > + error = gpio_direction_output(ddata->gpio_en , 0);
> > + if (error < 0) {
> > + dev_err(dev, "%s: GPIO configuration failed: GPIO %d,\
> > + error %d\n",__func__, ddata->gpio_en, error);
> > + }
> > + return 0;
> > +}
> > +
> > +static int sfh7741_resume(struct device *dev)
> > +{
> > + struct platform_device *pdev = to_platform_device(dev);
> > + struct sfh7741_drvdata *ddata = platform_get_drvdata(pdev);
> > +
> > + error = gpio_direction_output(ddata->gpio_en , 1);
> > + if (error < 0) {
> > + dev_err(dev, "%s: GPIO configuration failed: GPIO %d,\
> > + error %d\n",__func__, ddata->gpio_en, error);
> > + }
> > + return 0;
> > +}
> > +
> > +static const struct dev_pm_ops sfh7741_pm_ops = {
> > + .suspend = sfh7741_suspend,
> > + .resume = sfh7741_resume,
> > +};
> > +#endif
> > +
> > +static struct platform_driver sfh7741_device_driver = {
> > + .probe = sfh7741_probe,
> > + .remove = __devexit_p(sfh7741_remove),
> > + .driver = {
> > + .name = "sfh7741",
> > + .owner = THIS_MODULE,
> > +#ifdef CONFIG_PM
> > + .pm = &sfh7741_pm_ops,
> > +#endif
> > + }
> > +};
> > +
> > +static int __init sfh7741_init(void)
> > +{
> > + return platform_driver_register(&sfh7741_device_driver);
> > +}
> > +
> > +static void __exit sfh7741_exit(void)
> > +{
> > + platform_driver_unregister(&sfh7741_device_driver);
> > +}
> > +
> > +module_init(sfh7741_init);
> > +module_exit(sfh7741_exit);
> > +
> > +MODULE_LICENSE("GPL");
> > +MODULE_AUTHOR("Texas Instruments");
> > +MODULE_DESCRIPTION("Proximity driver ");
> > +MODULE_ALIAS("platform:sfh7741");
> > +
> > diff --git a/include/linux/input/sfh7741.h
> b/include/linux/input/sfh7741.h
> > new file mode 100644
> > index 0000000..801c971
> > --- /dev/null
> > +++ b/include/linux/input/sfh7741.h
> > @@ -0,0 +1,14 @@
> > +/*
> > + * Configuration and driver data for Proximity driver.
> > + */
> > +
> > +#ifndef __SFH7741_H
> > +#define __SFH7741_H
> > +
> > +struct sfh7741_platform_data {
> > + int gpio_intr;
> > + int gpio_en;
> > +};
> > +
> > +#endif
> > +
> > --
> > 1.5.4.7
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >
^ permalink raw reply	[flat|nested] 4+ messages in thread
* RE: [RFC][PATCH1/2] SFH7741: proximity sensor driver support
  2010-05-03  9:07   ` Datta, Shubhrajyoti
@ 2010-05-04  6:16     ` Hemanth V
  0 siblings, 0 replies; 4+ messages in thread
From: Hemanth V @ 2010-05-04  6:16 UTC (permalink / raw)
  To: Datta, Shubhrajyoti
  Cc: linux-input@vger.kernel.org, linux-omap@vger.kernel.org
>> ----- Original Message -----
>> From: "Datta, Shubhrajyoti" <shubhrajyoti@ti.com>
>> >
>> > From: Datta, Shubhrajyoti
>> > Sent: Monday, May 03, 2010 11:07 AM
>> > To: Datta, Shubhrajyoti
>> > Subject: [RFC][PATCH1/2] SFH7741: proximity sensor driver support
>> >
>>
>> > +
>> > +static irqreturn_t sfh7741_isr(int irq, void *dev_id)
>> > +{
>> > + struct sfh7741_drvdata *ddata = dev_id;
>> > +
>> > + int proximity = gpio_get_value(ddata->proximity_out);
>> > + input_report_abs(ddata->input, ABS_DISTANCE, proximity);
>> > + input_sync(ddata->input);
>> > +
>> > + return IRQ_HANDLED;
>> > +}
>> > +
>> > +static int __devinit sfh7741_setup(struct device *dev,
>> > + struct sfh7741_drvdata *ddata
>> > + )
>> > +{
>> > + int  error;
>> > + char *desc = "sfh7741";
>> > +
>> > + error = gpio_request(ddata->proximity_out, desc);
>> > + if (error < 0) {
>> > + dev_err(dev, "failed to request GPIO %d, error %d\n",
>> > + ddata->proximity_out, error);
>> > + return error;
>> > + }
>> > +
>> > + error = gpio_direction_input(ddata->proximity_out);
>> > + if (error < 0) {
>> > + dev_err(dev, "failed to configure direction for GPIO %d,\
>> > + error %d\n", ddata->proximity_out, error);
>> > + goto fail1;
>> > + }
>> > +
>>
>> General comment about GPIO,
>> It might be better to have GPIO configuration as part of board file,
>> rather than being part of the driver. This is should make the driver
>> more generic.
> I read GPIO in the ISR how can I take care of that?
A generic read function pointer could be defined as part
of platform data, which could be used to retieve gpio value
^ permalink raw reply	[flat|nested] 4+ messages in thread
end of thread, other threads:[~2010-05-04  6:16 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-03  5:46 [RFC][PATCH1/2] SFH7741: proximity sensor driver support Datta, Shubhrajyoti
2010-05-03  7:56 ` Hemanth V
2010-05-03  9:07   ` Datta, Shubhrajyoti
2010-05-04  6:16     ` Hemanth V
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).