diff options
| author | Viditha Hanumanthareddy <ngjq36@motorola.com> | 2014-02-05 16:57:57 -0600 | 
|---|---|---|
| committer | James Wylder <jwylder@motorola.com> | 2014-03-05 17:47:17 -0600 | 
| commit | 9410893aafb53b4b54a7a534640fe508eb8190c9 (patch) | |
| tree | 3bc67bf44baf7ecb7f947798c61b932fcb176c13 | |
| parent | 89423e5bf4e60ad8d6d0cf7eeee497e8043ce4fb (diff) | |
| download | olio-linux-3.10-9410893aafb53b4b54a7a534640fe508eb8190c9.tar.xz olio-linux-3.10-9410893aafb53b4b54a7a534640fe508eb8190c9.zip  | |
IKXCLOCK-196: als driver
Change-Id: If19ce8a3c705c58f4439f67a8981fd0fb623ac55
Reviewed-on: http://gerrit.pcs.mot.com/608584
SLTApproved: Slta Waiver <sltawvr@motorola.com>
Tested-by: Jira Key <jirakey@motorola.com>
Reviewed-by: Sajid Dalvi <fsd017@motorola.com>
Submit-Approved: Jira Key <jirakey@motorola.com>
| -rw-r--r-- | arch/arm/boot/dts/omap3-minnow.dtsi | 3 | ||||
| -rw-r--r-- | drivers/mfd/m4sensorhub-reg.h | 5 | ||||
| -rw-r--r-- | drivers/misc/Makefile | 1 | ||||
| -rw-r--r-- | drivers/misc/m4sensorhub_als.c | 289 | ||||
| -rw-r--r-- | include/linux/m4sensorhub/m4sensorhub_bank_enum.h | 1 | ||||
| -rw-r--r-- | include/linux/m4sensorhub/m4sensorhub_irqs.h | 3 | ||||
| -rw-r--r-- | include/linux/m4sensorhub/m4sensorhub_reg_enum.h | 4 | 
7 files changed, 306 insertions, 0 deletions
diff --git a/arch/arm/boot/dts/omap3-minnow.dtsi b/arch/arm/boot/dts/omap3-minnow.dtsi index a387d98b01d..de697e213b7 100644 --- a/arch/arm/boot/dts/omap3-minnow.dtsi +++ b/arch/arm/boot/dts/omap3-minnow.dtsi @@ -65,6 +65,9 @@  		stillmode {  			compatible = "mot,m4stillmode";  		}; +		lightsensor { +			compatible = "mot,m4als"; +		};  	};  	sound { diff --git a/drivers/mfd/m4sensorhub-reg.h b/drivers/mfd/m4sensorhub-reg.h index 66e2b8d8222..143bbaea2db 100644 --- a/drivers/mfd/m4sensorhub-reg.h +++ b/drivers/mfd/m4sensorhub-reg.h @@ -168,6 +168,10 @@ static const struct {  	[M4SH_REG_HEARTRATE_HEARTRATE]       = {M4SH_TYPE_HEARTRATE, 0x0, 2},  	[M4SH_REG_HEARTRATESENSOR_RAWHRVALUE] = {M4SH_TYPE_HEARTRATESENSOR, 0x0, 24},  	[M4SH_REG_HEARTRATESENSOR_SAMPLERATE] = {M4SH_TYPE_HEARTRATESENSOR, 0x18, 2}, +	[M4SH_REG_LIGHTSENSOR_VERSION]       = {M4SH_TYPE_LIGHTSENSOR, 0x0, 1}, +	[M4SH_REG_LIGHTSENSOR_DUMMY]         = {M4SH_TYPE_LIGHTSENSOR, 0x1, 1}, +	[M4SH_REG_LIGHTSENSOR_SAMPLERATE]    = {M4SH_TYPE_LIGHTSENSOR, 0x2, 2}, +	[M4SH_REG_LIGHTSENSOR_SIGNAL]        = {M4SH_TYPE_LIGHTSENSOR, 0x4, 2},  };  static const unsigned int bank_size_tbl[M4SH_TYPE__NUM] = { @@ -194,5 +198,6 @@ static const unsigned int bank_size_tbl[M4SH_TYPE__NUM] = {  	[M4SH_TYPE_EMG]                      = 330,  	[M4SH_TYPE_HEARTRATE]                = 2,  	[M4SH_TYPE_HEARTRATESENSOR]          = 26, +	[M4SH_TYPE_LIGHTSENSOR]              = 6,  };  #endif /*__M4SENSORHUB_MEM_INTERNAL_H__ */ diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index fb30252d4e5..6794be9a4a0 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -62,6 +62,7 @@ obj-$(CONFIG_MFD_M4SENSORHUB)   += m4sensorhub_stillmode.o  obj-$(CONFIG_MFD_M4SENSORHUB)   += m4sensorhub_download.o  obj-$(CONFIG_MFD_M4SENSORHUB)   += m4sensorhub_display.o  obj-$(CONFIG_MFD_M4SENSORHUB)   += m4sensorhub_passive.o +obj-$(CONFIG_MFD_M4SENSORHUB)   += m4sensorhub_als.o  obj-$(CONFIG_VIB_GPIO)          += vib-gpio.o  obj-$(CONFIG_C55_CTRL) += c55_ctrl.o  obj-$(CONFIG_MMI_FACTORY) += mmi-factory.o diff --git a/drivers/misc/m4sensorhub_als.c b/drivers/misc/m4sensorhub_als.c new file mode 100644 index 00000000000..ea8e20da467 --- /dev/null +++ b/drivers/misc/m4sensorhub_als.c @@ -0,0 +1,289 @@ +/* + *  Copyright (C) 2012 Motorola, Inc. + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  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 + * + *  Adds ability to program periodic interrupts from user space that + *  can wake the phone out of low power modes. + * + */ + +#include <linux/module.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/miscdevice.h> +#include <linux/platform_device.h> +#include <linux/proc_fs.h> +#include <linux/input.h> +#include <linux/m4sensorhub.h> +#include <linux/uaccess.h> +#include <linux/slab.h> + +#define ALS_CLIENT_DRIVER_NAME	"m4sensorhub_als" + +struct als_client { +	struct m4sensorhub_data *m4sensorhub; +	u16 als_signal; +}; + +static struct als_client *misc_als_data; + +static int als_client_open(struct inode *inode, struct file *file) +{ +	int err = 0; + +	err = nonseekable_open(inode, file); +	if (err < 0) { +		KDEBUG(M4SH_ERROR, "%s failed\n", __func__); +		return err; +	} +	file->private_data = misc_als_data; + +	return 0; +} + +static int als_client_close(struct inode *inode, struct file *file) +{ +	KDEBUG(M4SH_DEBUG, "als_client in %s\n", __func__); +	return 0; +} + + +static void m4_read_als_data(struct als_client *als_client_data) +{ +	m4sensorhub_reg_read( +			als_client_data->m4sensorhub, +			M4SH_REG_LIGHTSENSOR_SIGNAL, +			(char *)&als_client_data->als_signal +			); +} + +static void m4_handle_als_irq(enum m4sensorhub_irqs int_event, +					void *als_data) +{ +	struct als_client *als_client_data = als_data; +	m4_read_als_data(als_client_data); +} + +static const struct file_operations als_client_fops = { +	.owner = THIS_MODULE, +	.open  = als_client_open, +	.release = als_client_close, +}; + +static struct miscdevice als_client_miscdrv = { +	.minor = MISC_DYNAMIC_MINOR, +	.name  = ALS_CLIENT_DRIVER_NAME, +	.fops = &als_client_fops, +}; + +static ssize_t als_set_samplerate(struct device *dev, +				struct device_attribute *attr, +				const char *buf, size_t count) +{ +	int samplerate, ret; +	struct platform_device *pdev = to_platform_device(dev); +	struct als_client *als_client_data = platform_get_drvdata(pdev); + +	sscanf(buf, "%d", &samplerate); +	/* set sample rate */ +	ret = m4sensorhub_reg_write( +				als_client_data->m4sensorhub, +				M4SH_REG_LIGHTSENSOR_SAMPLERATE, +				(char *)&samplerate, m4sh_no_mask +				); +	if (ret < 0) +		KDEBUG( +			M4SH_ERROR, "Failed to set als samplerate to %d\n", +			samplerate +			); +	/* enable interrupt */ +	ret = m4sensorhub_irq_enable( +				als_client_data->m4sensorhub, +				M4SH_IRQ_LIGHTSENSOR_DATA_READY +				); +	if (ret < 0) +		KDEBUG(M4SH_ERROR, "Error enabling als int(%d)\n", ret); + +	return count; +} + +static ssize_t als_get_signal(struct device *dev, +			struct device_attribute *attr, char *buf) +{ +	struct platform_device *pdev = to_platform_device(dev); +	struct als_client *als_client_data = platform_get_drvdata(pdev); + +	return sprintf(buf, "%ud\n", als_client_data->als_signal); +} + +static DEVICE_ATTR(samplerate, 0222, NULL, als_set_samplerate); +static DEVICE_ATTR(signal, 0444, als_get_signal, NULL); + +static struct attribute *als_attributes[] = { +	&dev_attr_samplerate.attr, +	&dev_attr_signal.attr, +	NULL +}; + +static const struct attribute_group als_attribute_group = { +	.attrs = als_attributes, +}; + +static int als_driver_init(struct m4sensorhub_data *m4sensorhub) +{ +	int ret; +	ret = m4sensorhub_irq_register(m4sensorhub, +					M4SH_IRQ_LIGHTSENSOR_DATA_READY, +					m4_handle_als_irq, +					misc_als_data); +	if (ret < 0) { +		KDEBUG( +			M4SH_ERROR, +			"Error registering int %d (%d)\n", +			M4SH_IRQ_PASSIVE_BUFFER_FULL, ret +			); +	} + +	return ret; +} + +static int als_client_probe(struct platform_device *pdev) +{ +	int ret = -1; +	struct als_client *als_client_data; +	struct m4sensorhub_data *m4sensorhub = m4sensorhub_client_get_drvdata(); + +	if (!m4sensorhub) +		return -EFAULT; + +	als_client_data = kzalloc(sizeof(*als_client_data), +						GFP_KERNEL); +	if (!als_client_data) +		return -ENOMEM; + +	als_client_data->m4sensorhub = m4sensorhub; +	platform_set_drvdata(pdev, als_client_data); + +	ret = misc_register(&als_client_miscdrv); +	if (ret < 0) { +		KDEBUG(M4SH_ERROR, "Error registering %s driver\n", __func__); +		goto free_mem; +	} +	misc_als_data = als_client_data; +	ret = m4sensorhub_register_initcall(als_driver_init); +	if (ret < 0) { +		KDEBUG(M4SH_ERROR, "Unable to register init function" +			"for als client = %d\n", ret); +		goto unregister_misc_device; +	} +	ret = sysfs_create_group(&pdev->dev.kobj, &als_attribute_group); +	if (ret) +		goto unregister_initcall; + + +	KDEBUG(M4SH_INFO, "Initialized %s driver\n", __func__); +	return 0; +unregister_initcall: +	m4sensorhub_unregister_initcall(als_driver_init); +unregister_misc_device: +	misc_als_data = NULL; +	misc_deregister(&als_client_miscdrv); +free_mem: +	platform_set_drvdata(pdev, NULL); +	als_client_data->m4sensorhub = NULL; +	kfree(als_client_data); +	als_client_data = NULL; +	return ret; +} + +static int __exit als_client_remove(struct platform_device *pdev) +{ +	struct als_client *als_client_data = +						platform_get_drvdata(pdev); + +	m4sensorhub_irq_disable(als_client_data->m4sensorhub, +				M4SH_IRQ_LIGHTSENSOR_DATA_READY); +	m4sensorhub_irq_unregister( +				als_client_data->m4sensorhub, +				M4SH_IRQ_LIGHTSENSOR_DATA_READY +				); +	m4sensorhub_unregister_initcall(als_driver_init); + +	misc_als_data = NULL; +	misc_deregister(&als_client_miscdrv); +	platform_set_drvdata(pdev, NULL); +	als_client_data->m4sensorhub = NULL; +	kfree(als_client_data); +	als_client_data = NULL; +	return 0; +} + +static void als_client_shutdown(struct platform_device *pdev) +{ +	return; +} +#ifdef CONFIG_PM +static int als_client_suspend(struct platform_device *pdev, +				pm_message_t message) +{ +	return 0; +} + +static int als_client_resume(struct platform_device *pdev) +{ +	return 0; +} +#else +#define als_client_suspend NULL +#define als_client_resume  NULL +#endif + +static struct of_device_id m4als_match_tbl[] = { +	{ .compatible = "mot,m4als" }, +	{}, +}; + +static struct platform_driver als_client_driver = { +	.probe		= als_client_probe, +	.remove		= __exit_p(als_client_remove), +	.shutdown	= als_client_shutdown, +	.suspend	= als_client_suspend, +	.resume		= als_client_resume, +	.driver		= { +		.name	= ALS_CLIENT_DRIVER_NAME, +		.owner	= THIS_MODULE, +		.of_match_table = of_match_ptr(m4als_match_tbl), +	}, +}; + +static int __init als_client_init(void) +{ +	return platform_driver_register(&als_client_driver); +} + +static void __exit als_client_exit(void) +{ +	platform_driver_unregister(&als_client_driver); +} + +module_init(als_client_init); +module_exit(als_client_exit); + +MODULE_ALIAS("platform:als_client"); +MODULE_DESCRIPTION("M4 Sensor Hub Passive mode client driver"); +MODULE_AUTHOR("Motorola"); +MODULE_LICENSE("GPL"); + diff --git a/include/linux/m4sensorhub/m4sensorhub_bank_enum.h b/include/linux/m4sensorhub/m4sensorhub_bank_enum.h index 13f69e9d041..12fd8c06995 100644 --- a/include/linux/m4sensorhub/m4sensorhub_bank_enum.h +++ b/include/linux/m4sensorhub/m4sensorhub_bank_enum.h @@ -48,6 +48,7 @@ enum m4sensorhub_type {  	M4SH_TYPE_EMG,  	M4SH_TYPE_HEARTRATE,  	M4SH_TYPE_HEARTRATESENSOR, +	M4SH_TYPE_LIGHTSENSOR,  	M4SH_TYPE__NUM  }; diff --git a/include/linux/m4sensorhub/m4sensorhub_irqs.h b/include/linux/m4sensorhub/m4sensorhub_irqs.h index c41c5c5ed89..4f2fb51ed98 100644 --- a/include/linux/m4sensorhub/m4sensorhub_irqs.h +++ b/include/linux/m4sensorhub/m4sensorhub_irqs.h @@ -71,6 +71,9 @@ enum m4sensorhub_irqs {  	/* INT1 0x40 : passive buffer full */  	M4SH_IRQ_PASSIVE_BUFFER_FULL, +	/* INT1 0x80 : lightsensor data full */ +	M4SH_IRQ_LIGHTSENSOR_DATA_READY, +  	/* Number of allocated interrupts */  	M4SH_IRQ__NUM  }; diff --git a/include/linux/m4sensorhub/m4sensorhub_reg_enum.h b/include/linux/m4sensorhub/m4sensorhub_reg_enum.h index 132087240f1..ea28013e625 100644 --- a/include/linux/m4sensorhub/m4sensorhub_reg_enum.h +++ b/include/linux/m4sensorhub/m4sensorhub_reg_enum.h @@ -162,6 +162,10 @@ enum m4sensorhub_reg {  	M4SH_REG_HEARTRATE_HEARTRATE,  	M4SH_REG_HEARTRATESENSOR_RAWHRVALUE,  	M4SH_REG_HEARTRATESENSOR_SAMPLERATE, +	M4SH_REG_LIGHTSENSOR_VERSION, +	M4SH_REG_LIGHTSENSOR_DUMMY, +	M4SH_REG_LIGHTSENSOR_SAMPLERATE, +	M4SH_REG_LIGHTSENSOR_SIGNAL,  	M4SH_REG__INVALID,                /* Marker for invalid register */  	M4SH_REG__NUM = M4SH_REG__INVALID /* Number of registers */  };  |