summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/boot/dts/omap3-minnow.dtsi2
-rw-r--r--arch/arm/configs/minnow_defconfig197
-rw-r--r--drivers/misc/Makefile2
-rw-r--r--drivers/misc/m4sensorhub_bmp180.c423
-rw-r--r--drivers/misc/m4sensorhub_pressure.c420
-rw-r--r--include/linux/iio/m4sensorhub_pressure.h12
6 files changed, 630 insertions, 426 deletions
diff --git a/arch/arm/boot/dts/omap3-minnow.dtsi b/arch/arm/boot/dts/omap3-minnow.dtsi
index a747680c1a5..879cb58f26e 100644
--- a/arch/arm/boot/dts/omap3-minnow.dtsi
+++ b/arch/arm/boot/dts/omap3-minnow.dtsi
@@ -117,7 +117,7 @@
compatible = "simple-bus";
pressure {
- compatible = "mot,m4pressure";
+ compatible = "mot,m4sensorhub_pressure";
};
mpu9150 {
compatible = "mot,m4mpu9150";
diff --git a/arch/arm/configs/minnow_defconfig b/arch/arm/configs/minnow_defconfig
index 396909a7dc6..761ec0d8f04 100644
--- a/arch/arm/configs/minnow_defconfig
+++ b/arch/arm/configs/minnow_defconfig
@@ -1435,6 +1435,7 @@ CONFIG_HDQ_MASTER_OMAP=y
CONFIG_POWER_SUPPLY=y
# CONFIG_POWER_SUPPLY_DEBUG is not set
# CONFIG_PDA_POWER is not set
+# CONFIG_GENERIC_ADC_BATTERY is not set
# CONFIG_TEST_POWER is not set
# CONFIG_BATTERY_DS2780 is not set
# CONFIG_BATTERY_DS2781 is not set
@@ -2134,6 +2135,105 @@ CONFIG_STAGING=y
# CONFIG_TRANZPORT is not set
# CONFIG_LINE6_USB is not set
# CONFIG_VT6656 is not set
+
+#
+# IIO staging drivers
+#
+
+#
+# Accelerometers
+#
+# CONFIG_ADIS16201 is not set
+# CONFIG_ADIS16203 is not set
+# CONFIG_ADIS16204 is not set
+# CONFIG_ADIS16209 is not set
+# CONFIG_ADIS16220 is not set
+# CONFIG_ADIS16240 is not set
+# CONFIG_LIS3L02DQ is not set
+# CONFIG_SCA3000 is not set
+
+#
+# Analog to digital converters
+#
+# CONFIG_AD7291 is not set
+# CONFIG_AD7606 is not set
+# CONFIG_AD799X is not set
+# CONFIG_AD7780 is not set
+# CONFIG_AD7816 is not set
+# CONFIG_AD7192 is not set
+# CONFIG_AD7280 is not set
+
+#
+# Analog digital bi-direction converters
+#
+# CONFIG_ADT7316 is not set
+
+#
+# Capacitance to digital converters
+#
+# CONFIG_AD7150 is not set
+# CONFIG_AD7152 is not set
+# CONFIG_AD7746 is not set
+
+#
+# Direct Digital Synthesis
+#
+# CONFIG_AD5930 is not set
+# CONFIG_AD9832 is not set
+# CONFIG_AD9834 is not set
+# CONFIG_AD9850 is not set
+# CONFIG_AD9852 is not set
+# CONFIG_AD9910 is not set
+# CONFIG_AD9951 is not set
+
+#
+# Digital gyroscope sensors
+#
+# CONFIG_ADIS16060 is not set
+# CONFIG_ADIS16130 is not set
+# CONFIG_ADIS16260 is not set
+
+#
+# Network Analyzer, Impedance Converters
+#
+# CONFIG_AD5933 is not set
+
+#
+# Light sensors
+#
+# CONFIG_SENSORS_ISL29018 is not set
+# CONFIG_SENSORS_ISL29028 is not set
+# CONFIG_TSL2583 is not set
+# CONFIG_TSL2x7x is not set
+
+#
+# Magnetometer sensors
+#
+# CONFIG_SENSORS_HMC5843 is not set
+
+#
+# Active energy metering IC
+#
+# CONFIG_ADE7753 is not set
+# CONFIG_ADE7754 is not set
+# CONFIG_ADE7758 is not set
+# CONFIG_ADE7759 is not set
+# CONFIG_ADE7854 is not set
+
+#
+# Resolver to digital converters
+#
+# CONFIG_AD2S90 is not set
+# CONFIG_AD2S1200 is not set
+# CONFIG_AD2S1210 is not set
+
+#
+# Triggers - standalone
+#
+# CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set
+# CONFIG_IIO_GPIO_TRIGGER is not set
+# CONFIG_IIO_SYSFS_TRIGGER is not set
+# CONFIG_IIO_SIMPLE_DUMMY is not set
# CONFIG_ZSMALLOC is not set
# CONFIG_BCM_WIMAX is not set
# CONFIG_FT1000 is not set
@@ -2194,7 +2294,102 @@ CONFIG_OF_IOMMU=y
# CONFIG_PM_DEVFREQ is not set
# CONFIG_EXTCON is not set
# CONFIG_MEMORY is not set
-# CONFIG_IIO is not set
+CONFIG_IIO=y
+CONFIG_IIO_BUFFER=y
+# CONFIG_IIO_BUFFER_CB is not set
+CONFIG_IIO_KFIFO_BUF=y
+CONFIG_IIO_TRIGGER=y
+CONFIG_IIO_CONSUMERS_PER_TRIGGER=2
+
+#
+# Accelerometers
+#
+# CONFIG_KXSD9 is not set
+# CONFIG_IIO_ST_ACCEL_3AXIS is not set
+
+#
+# Analog to digital converters
+#
+# CONFIG_AD7266 is not set
+# CONFIG_AD7298 is not set
+# CONFIG_AD7923 is not set
+# CONFIG_AD7791 is not set
+# CONFIG_AD7793 is not set
+# CONFIG_AD7476 is not set
+# CONFIG_AD7887 is not set
+# CONFIG_EXYNOS_ADC is not set
+# CONFIG_MAX1363 is not set
+# CONFIG_TI_ADC081C is not set
+
+#
+# Amplifiers
+#
+# CONFIG_AD8366 is not set
+
+#
+# Hid Sensor IIO Common
+#
+
+#
+# Digital to analog converters
+#
+# CONFIG_AD5064 is not set
+# CONFIG_AD5360 is not set
+# CONFIG_AD5380 is not set
+# CONFIG_AD5421 is not set
+# CONFIG_AD5624R_SPI is not set
+# CONFIG_AD5446 is not set
+# CONFIG_AD5449 is not set
+# CONFIG_AD5504 is not set
+# CONFIG_AD5755 is not set
+# CONFIG_AD5764 is not set
+# CONFIG_AD5791 is not set
+# CONFIG_AD5686 is not set
+# CONFIG_MAX517 is not set
+# CONFIG_MCP4725 is not set
+
+#
+# Frequency Synthesizers DDS/PLL
+#
+
+#
+# Clock Generator/Distribution
+#
+# CONFIG_AD9523 is not set
+
+#
+# Phase-Locked Loop (PLL) frequency synthesizers
+#
+# CONFIG_ADF4350 is not set
+
+#
+# Digital gyroscope sensors
+#
+# CONFIG_ADIS16080 is not set
+# CONFIG_ADIS16136 is not set
+# CONFIG_ADXRS450 is not set
+# CONFIG_IIO_ST_GYRO_3AXIS is not set
+# CONFIG_ITG3200 is not set
+
+#
+# Inertial measurement units
+#
+# CONFIG_ADIS16400 is not set
+# CONFIG_ADIS16480 is not set
+# CONFIG_INV_MPU6050_IIO is not set
+
+#
+# Light sensors
+#
+# CONFIG_ADJD_S311 is not set
+# CONFIG_SENSORS_TSL2563 is not set
+# CONFIG_VCNL4000 is not set
+
+#
+# Magnetometer sensors
+#
+# CONFIG_AK8975 is not set
+# CONFIG_IIO_ST_MAGN_3AXIS is not set
# CONFIG_PWM is not set
CONFIG_IRQCHIP=y
# CONFIG_IPACK_BUS is not set
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index a354115b155..95233b463a5 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -54,7 +54,6 @@ obj-$(CONFIG_INTEL_MEI) += mei/
obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/
obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o
obj-$(CONFIG_SRAM) += sram.o
-obj-$(CONFIG_MFD_M4SENSORHUB) += m4sensorhub_bmp180.o
obj-$(CONFIG_MFD_M4SENSORHUB) += m4sensorhub_mpu9150.o
obj-$(CONFIG_MFD_M4SENSORHUB) += m4sensorhub_pedometer.o
obj-$(CONFIG_MFD_M4SENSORHUB) += m4sensorhub_gesture.o
@@ -64,6 +63,7 @@ obj-$(CONFIG_MFD_M4SENSORHUB) += m4sensorhub_display.o
obj-$(CONFIG_MFD_M4SENSORHUB) += m4sensorhub_passive.o
obj-$(CONFIG_MFD_M4SENSORHUB) += m4sensorhub_als.o
obj-$(CONFIG_MFD_M4SENSORHUB) += m4sensorhub_heartrate.o
+obj-$(CONFIG_MFD_M4SENSORHUB) += m4sensorhub_pressure.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_bmp180.c b/drivers/misc/m4sensorhub_bmp180.c
deleted file mode 100644
index 02fa1e7c102..00000000000
--- a/drivers/misc/m4sensorhub_bmp180.c
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * 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/uaccess.h>
-#include <linux/m4sensorhub.h>
-#include <linux/m4sensorhub_client_ioctl.h>
-#include <linux/m4sensorhub/MemMapPressureSensor.h>
-#include <linux/slab.h>
-
-#define PRESSURE_CLIENT_DRIVER_NAME "m4sensorhub_bmp180"
-#define PRESSURE_MIN 30000
-#define PRESSURE_MAX 110000
-
-struct pressure_client {
- struct m4sensorhub_data *m4sensorhub;
- struct input_dev *input_dev;
- int pressure;
- int altitude;
- signed short samplerate;
-};
-
-struct pressure_client *misc_pressure_data;
-
-static int pressure_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_pressure_data;
-
- return 0;
-}
-
-static int pressure_client_close(struct inode *inode, struct file *file)
-{
- KDEBUG(M4SH_DEBUG, " pressure_client in %s\n", __func__);
- return 0;
-}
-
-static void m4_report_pressure_inputevent(struct pressure_client
- *pressure_client_data)
-{
- input_report_abs(pressure_client_data->input_dev, ABS_PRESSURE,
- pressure_client_data->pressure);
- input_report_abs(pressure_client_data->input_dev, ABS_ALTITUDE,
- pressure_client_data->altitude);
- input_sync(pressure_client_data->input_dev);
-}
-
-static void m4_read_pressure_data(struct pressure_client *pressure_data)
-{
- sPressureData pressure;
-
- m4sensorhub_reg_read(pressure_data->m4sensorhub,
- M4SH_REG_PRESSURE_PRESSURE,
- (char *)&pressure.pressure);
- pressure_data->pressure = pressure.pressure;
- m4sensorhub_reg_read(pressure_data->m4sensorhub,
- M4SH_REG_PRESSURE_ABSOLUTEALTITUDE,
- (char *)&pressure.absoluteAltitude);
- pressure_data->altitude = pressure.absoluteAltitude;
-}
-
-static void m4_handle_pressure_irq(enum m4sensorhub_irqs int_event,
- void *pressure_data)
-{
- struct pressure_client *pressure_client_data = pressure_data;
-
- m4_read_pressure_data(pressure_client_data);
- m4_report_pressure_inputevent(pressure_client_data);
-}
-
-static int m4_set_pressure_samplerate(
- struct pressure_client *pressure_client_data,
- signed int samplerate)
-{
- int ret = 0;
-
- if (samplerate != pressure_client_data->samplerate) {
- ret = m4sensorhub_reg_write(pressure_client_data->m4sensorhub,
- M4SH_REG_PRESSURE_SAMPLERATE,
- (char *)&samplerate, m4sh_no_mask);
- if (ret != m4sensorhub_reg_getsize(
- pressure_client_data->m4sensorhub,
- M4SH_REG_PRESSURE_SAMPLERATE)) {
- KDEBUG(M4SH_ERROR, "Unable to set delay for \
- pressure sensor\n");
- return ret;
- }
-
- KDEBUG(M4SH_DEBUG, "%s() updating samplerate from %d to %d\n",
- __func__, pressure_client_data->samplerate,
- samplerate);
- pressure_client_data->samplerate = samplerate;
-
- if (samplerate >= 0)
- ret = m4sensorhub_irq_enable(
- pressure_client_data->m4sensorhub,
- M4SH_IRQ_PRESSURE_DATA_READY);
- else
- ret = m4sensorhub_irq_disable(
- pressure_client_data->m4sensorhub,
- M4SH_IRQ_PRESSURE_DATA_READY);
- if (ret != 0)
- KDEBUG(M4SH_ERROR, "Unable to enable/disable \
- pressure irq\n");
- }
-
- return ret;
-}
-
-/*
- * Handle commands from user-space.
- */
-static long pressure_client_ioctl(struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- int ret = 0;
- int delay;
- unsigned char mask[] = {0xff, 0xff, 0xff, 0xff};
- static int status;
- int altitude = 0;
- void __user *argp = (void __user *)arg;
- struct pressure_client *pressure_client_data = filp->private_data;
-
- switch (cmd) {
- case M4_SENSOR_IOCTL_GET_PRESSURE:
- m4_read_pressure_data(pressure_client_data);
- m4_report_pressure_inputevent(pressure_client_data);
- break;
-
- case M4_SENSOR_IOCTL_SET_DELAY:
- if (copy_from_user(&delay, argp, sizeof(delay)))
- return -EFAULT;
- if (delay >= 0)
- ret = m4_set_pressure_samplerate(pressure_client_data,
- delay);
- if (ret < 0) {
- KDEBUG(M4SH_ERROR, "Error enabling int %d (%d)\n",
- M4SH_IRQ_PRESSURE_DATA_READY, ret);
- return -EFAULT;
- }
- break;
-
- case M4_SENSOR_IOCTL_APP_GET_FLAG:
- if (copy_to_user(argp, &status, sizeof(status)))
- return -EFAULT;
- break;
-
- case M4_SENSOR_IOCTL_APP_SET_FLAG:
- if (copy_from_user(&status, argp, sizeof(status)))
- return -EFAULT;
- break;
- case M4_SENSOR_IOCTL_SET_ALTITUDE:
- if (copy_from_user(&altitude, argp, sizeof(altitude)))
- return -EFAULT;
- if (altitude > 0)
- m4sensorhub_reg_write(pressure_client_data->m4sensorhub,
- M4SH_REG_PRESSURE_REFERENCEALTITUDE,
- (char *)&altitude, mask);
-
- break;
- default:
- KDEBUG(M4SH_ERROR, "Invalid IOCTL Command in %s \n", __func__);
- ret = -EINVAL;
- }
- return ret;
-}
-
-static ssize_t pressure_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct pressure_client *pressure_client_data
- = platform_get_drvdata(pdev);
-
- m4_read_pressure_data(pressure_client_data);
- KDEBUG(M4SH_DEBUG, "%s : Pressure : = %d",
- __func__, pressure_client_data->pressure);
- return sprintf(buf, "%d\n", pressure_client_data->pressure);
-}
-
-static ssize_t altitude_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct pressure_client *pressure_client_data
- = platform_get_drvdata(pdev);
-
- m4_read_pressure_data(pressure_client_data);
- KDEBUG(M4SH_DEBUG, "%s : Altitude : %d",
- __func__, pressure_client_data->altitude);
- return sprintf(buf, "%d\n", pressure_client_data->altitude);
-}
-
-static DEVICE_ATTR(pressure, 0444, pressure_show, NULL);
-static DEVICE_ATTR(altitude, 0444, altitude_show, NULL);
-
-static const struct file_operations pressure_client_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = pressure_client_ioctl,
- .open = pressure_client_open,
- .release = pressure_client_close,
-};
-
-static struct miscdevice pressure_client_miscdrv = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = PRESSURE_CLIENT_DRIVER_NAME,
- .fops = &pressure_client_fops,
-};
-
-
-static int pressure_driver_init(struct init_calldata *p_arg)
-{
- int ret;
- struct m4sensorhub_data *m4sensorhub = p_arg->p_m4sensorhub_data;
- ret = m4sensorhub_irq_register(m4sensorhub,
- M4SH_IRQ_PRESSURE_DATA_READY,
- m4_handle_pressure_irq,
- misc_pressure_data);
- if (ret < 0)
- KDEBUG(M4SH_ERROR, "Error registering int %d (%d)\n",
- M4SH_IRQ_PRESSURE_DATA_READY, ret);
- return ret;
-}
-
-static int pressure_client_probe(struct platform_device *pdev)
-{
- int ret = -1;
- struct pressure_client *pressure_client_data;
- struct m4sensorhub_data *m4sensorhub = m4sensorhub_client_get_drvdata();
-
- if (!m4sensorhub)
- return -EFAULT;
-
- pressure_client_data = kzalloc(sizeof(*pressure_client_data),
- GFP_KERNEL);
- if (!pressure_client_data)
- return -ENOMEM;
-
- pressure_client_data->m4sensorhub = m4sensorhub;
- platform_set_drvdata(pdev, pressure_client_data);
-
- pressure_client_data->input_dev = input_allocate_device();
- if (!pressure_client_data->input_dev) {
- ret = -ENOMEM;
- KDEBUG(M4SH_ERROR, "%s: input device allocate failed: %d\n",
- __func__, ret);
- goto free_mem;
- }
-
- pressure_client_data->input_dev->name = PRESSURE_CLIENT_DRIVER_NAME;
- set_bit(EV_ABS, pressure_client_data->input_dev->evbit);
- input_set_abs_params(pressure_client_data->input_dev, ABS_ALTITUDE,
- -2147483647, 2147483647, 0, 0);
- input_set_abs_params(pressure_client_data->input_dev, ABS_PRESSURE,
- PRESSURE_MIN, PRESSURE_MAX, 0, 0);
-
- if (input_register_device(pressure_client_data->input_dev)) {
- KDEBUG(M4SH_ERROR, "%s: input device register failed\n",
- __func__);
- input_free_device(pressure_client_data->input_dev);
- goto free_mem;
- }
-
- ret = misc_register(&pressure_client_miscdrv);
- if (ret < 0) {
- KDEBUG(M4SH_ERROR, "Error registering %s driver\n",
- PRESSURE_CLIENT_DRIVER_NAME);
- goto unregister_input_device;
- }
- misc_pressure_data = pressure_client_data;
- ret = m4sensorhub_register_initcall(pressure_driver_init,
- pressure_client_data);
- if (ret < 0) {
- KDEBUG(M4SH_ERROR, "Unable to register init function "
- "for pressure client = %d\n", ret);
- goto unregister_misc_device;
- }
- if (device_create_file(&pdev->dev, &dev_attr_pressure)) {
- KDEBUG(M4SH_ERROR, "Error creating %s sys entry\n",
- PRESSURE_CLIENT_DRIVER_NAME);
- ret = -1;
- goto unregister_initcall;
- }
-
- if (device_create_file(&pdev->dev, &dev_attr_altitude)) {
- KDEBUG(M4SH_ERROR, "Error creating %s sys entry\n",
- PRESSURE_CLIENT_DRIVER_NAME);
- ret = -1;
- goto remove_device_file;
- }
- KDEBUG(M4SH_ERROR, "Initialized %s driver\n", __func__);
- return 0;
-
-remove_device_file:
- device_remove_file(&pdev->dev, &dev_attr_pressure);
-unregister_initcall:
- m4sensorhub_unregister_initcall(pressure_driver_init);
-unregister_misc_device:
- misc_pressure_data = NULL;
- misc_deregister(&pressure_client_miscdrv);
-unregister_input_device:
- input_unregister_device(pressure_client_data->input_dev);
-free_mem:
- platform_set_drvdata(pdev, NULL);
- pressure_client_data->m4sensorhub = NULL;
- kfree(pressure_client_data);
- pressure_client_data = NULL;
- return ret;
-}
-
-static int __exit pressure_client_remove(struct platform_device *pdev)
-{
- struct pressure_client *pressure_client_data =
- platform_get_drvdata(pdev);
-
- device_remove_file(&pdev->dev, &dev_attr_pressure);
- device_remove_file(&pdev->dev, &dev_attr_altitude);
- m4sensorhub_irq_disable(pressure_client_data->m4sensorhub,
- M4SH_IRQ_PRESSURE_DATA_READY);
- m4sensorhub_irq_unregister(pressure_client_data->m4sensorhub,
- M4SH_IRQ_PRESSURE_DATA_READY);
- m4sensorhub_unregister_initcall(pressure_driver_init);
- misc_pressure_data = NULL;
- misc_deregister(&pressure_client_miscdrv);
- input_unregister_device(pressure_client_data->input_dev);
- platform_set_drvdata(pdev, NULL);
- pressure_client_data->m4sensorhub = NULL;
- kfree(pressure_client_data);
- pressure_client_data = NULL;
- return 0;
-}
-
-static void pressure_client_shutdown(struct platform_device *pdev)
-{
- return;
-}
-#ifdef CONFIG_PM
-static int pressure_client_suspend(struct platform_device *pdev,
- pm_message_t message)
-{
- struct pressure_client *pressure_client_data =
- platform_get_drvdata(pdev);
-
- return m4_set_pressure_samplerate(pressure_client_data, -1);
-}
-
-static int pressure_client_resume(struct platform_device *pdev)
-{
- return 0;
-}
-#else
-#define pressure_client_suspend NULL
-#define pressure_client_resume NULL
-#endif
-
-static struct of_device_id m4pressure_match_tbl[] = {
- {.compatible = "mot,m4pressure" },
- {},
-};
-
-static struct platform_driver pressure_client_driver = {
- .probe = pressure_client_probe,
- .remove = __exit_p(pressure_client_remove),
- .shutdown = pressure_client_shutdown,
- .suspend = pressure_client_suspend,
- .resume = pressure_client_resume,
- .driver = {
- .name = PRESSURE_CLIENT_DRIVER_NAME,
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(m4pressure_match_tbl),
- },
-};
-
-static int __init pressure_client_init(void)
-{
- return platform_driver_register(&pressure_client_driver);
-}
-
-static void __exit pressure_client_exit(void)
-{
- platform_driver_unregister(&pressure_client_driver);
-}
-
-module_init(pressure_client_init);
-module_exit(pressure_client_exit);
-
-MODULE_ALIAS("platform:pressure_client");
-MODULE_DESCRIPTION("M4 Sensor Hub Pressure client driver");
-MODULE_AUTHOR("Motorola");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/misc/m4sensorhub_pressure.c b/drivers/misc/m4sensorhub_pressure.c
new file mode 100644
index 00000000000..ae3cbc67d61
--- /dev/null
+++ b/drivers/misc/m4sensorhub_pressure.c
@@ -0,0 +1,420 @@
+/*
+ * 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/platform_device.h>
+#include <linux/input.h>
+#include <linux/m4sensorhub.h>
+#include <linux/m4sensorhub/MemMapPressureSensor.h>
+#include <linux/m4sensorhub/m4sensorhub_registers.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/types.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/m4sensorhub_pressure.h>
+
+#define m4sensorhub_pressure_DRIVER_NAME "m4sensorhub_pressure"
+
+struct m4sensorhub_pressure_drvdata {
+ struct m4sensorhub_data *p_m4sensorhub;
+ int samplerate;
+ bool enable;
+};
+
+#define DATA_SIZE_IN_BITS (sizeof(struct m4sensorhub_pressure_data) * 8)
+
+/* We are ADC with 1 channel */
+static const struct iio_chan_spec m4sensorhub_pressure_channels[] = {
+ {
+ .type = IIO_PRESSURE,
+ /* Channel has a numeric index of 0 */
+ .indexed = 1,
+ .channel = 0,
+ .info_mask_separate =
+ /*
+ * in_pressure0_raw
+ * Raw (unscaled no bias removal etc) measurement
+ * from the device.
+ */
+ BIT(IIO_CHAN_INFO_RAW),
+
+ .scan_index = 0,
+ .scan_type = { /* Description of storage in buffer */
+ .sign = 'u', /* unsigned */
+ .realbits = DATA_SIZE_IN_BITS,
+ .storagebits = DATA_SIZE_IN_BITS,
+ .shift = 0, /* zero shift */
+ },
+ },
+};
+
+
+static void m4_handle_pressure_irq(enum m4sensorhub_irqs int_event,
+ void *p_data)
+{
+ struct iio_dev *p_iio_dev = (struct iio_dev *)p_data;
+ struct m4sensorhub_pressure_drvdata *p_priv_data = iio_priv(p_iio_dev);
+ struct m4sensorhub_data *p_m4sensorhub = p_priv_data->p_m4sensorhub;
+ sPressureData pressure;
+ struct m4sensorhub_pressure_data data;
+
+ m4sensorhub_reg_read(p_m4sensorhub,
+ M4SH_REG_PRESSURE_PRESSURE,
+ (char *)&pressure.pressure);
+ m4sensorhub_reg_read(p_m4sensorhub,
+ M4SH_REG_PRESSURE_ABSOLUTEALTITUDE,
+ (char *)&pressure.absoluteAltitude);
+
+ data.pressure = pressure.pressure;
+ data.altitude = pressure.absoluteAltitude;
+ data.timestamp = iio_get_time_ns();
+
+ iio_push_to_buffers(p_iio_dev, (unsigned char *)&data);
+}
+
+
+static int m4sensorhub_pressure_driver_initcallback(struct init_calldata *p_arg)
+{
+ struct iio_dev *p_iio_dev = (struct iio_dev *)(p_arg->p_data);
+ struct m4sensorhub_data *p_m4sensorhub = p_arg->p_m4sensorhub_data;
+ struct m4sensorhub_pressure_drvdata *p_priv_data = iio_priv(p_iio_dev);
+ int ret;
+
+ p_priv_data->p_m4sensorhub = p_m4sensorhub;
+
+ /* register for pressure interrupt from M4 */
+ ret = m4sensorhub_irq_register(p_m4sensorhub,
+ M4SH_IRQ_PRESSURE_DATA_READY,
+ m4_handle_pressure_irq,
+ p_iio_dev);
+
+ if (ret < 0)
+ pr_err("%s: Failed to register interrupt handler\n", __func__);
+
+ return ret;
+}
+
+/* Sysfs interface for enable and setdelay */
+/* enable */
+static ssize_t m4sensorhub_pressure_store_enable(struct device *p_dev,
+ struct device_attribute *p_attr,
+ const char *p_buf, size_t count)
+{
+ struct platform_device *pdev = to_platform_device(p_dev);
+ struct iio_dev *p_iio_dev =
+ platform_get_drvdata(pdev);
+ struct m4sensorhub_pressure_drvdata *p_priv_data = iio_priv(p_iio_dev);
+ struct m4sensorhub_data *p_m4sensorhub = p_priv_data->p_m4sensorhub;
+ bool requested_state;
+ int ret;
+
+ ret = strtobool(p_buf, &requested_state);
+ if (ret < 0)
+ return ret;
+
+ if (requested_state == false) {
+ ret = m4sensorhub_irq_disable(
+ p_m4sensorhub,
+ M4SH_IRQ_PRESSURE_DATA_READY);
+
+ if (ret < 0) {
+ pr_err("%s: failed to disable irq\n", __func__);
+ return ret;
+ }
+ }
+
+ p_priv_data->enable = requested_state;
+
+ return count;
+}
+
+static ssize_t m4sensorhub_pressure_show_enable(struct device *p_dev,
+ struct device_attribute *p_attr, char *p_buf)
+{
+ struct platform_device *pdev = to_platform_device(p_dev);
+ struct iio_dev *p_iio_dev =
+ platform_get_drvdata(pdev);
+ struct m4sensorhub_pressure_drvdata *p_priv_data = iio_priv(p_iio_dev);
+ int ret = 0;
+ if (p_priv_data->enable)
+ ret = 1;
+ return snprintf(p_buf, PAGE_SIZE, "%d\n", ret);
+}
+
+/* setdelay */
+static ssize_t m4sensorhub_pressure_store_setdelay(struct device *p_dev,
+ struct device_attribute *p_attr,
+ const char *p_buf, size_t count)
+{
+ struct platform_device *pdev = to_platform_device(p_dev);
+ struct iio_dev *p_iio_dev =
+ platform_get_drvdata(pdev);
+ struct m4sensorhub_pressure_drvdata *p_priv_data = iio_priv(p_iio_dev);
+ int ret;
+ int samplerate;
+
+ ret = kstrtoint(p_buf, 10, &samplerate);
+ if (ret < 0)
+ return ret;
+
+ if (samplerate < 0) {
+ pr_err("%s: negative sample rate, rejecting\n", __func__);
+ return -EINVAL;
+ }
+ if (samplerate != p_priv_data->samplerate) {
+ ret = m4sensorhub_reg_write(p_priv_data->p_m4sensorhub,
+ M4SH_REG_PRESSURE_SAMPLERATE,
+ (char *)&samplerate, m4sh_no_mask);
+ if (ret != m4sensorhub_reg_getsize(
+ p_priv_data->p_m4sensorhub,
+ M4SH_REG_PRESSURE_SAMPLERATE)) {
+ pr_err("%s:Unable to set delay\n", __func__);
+ return ret;
+ }
+
+ p_priv_data->samplerate = samplerate;
+
+ ret = m4sensorhub_irq_enable(
+ p_priv_data->p_m4sensorhub,
+ M4SH_IRQ_PRESSURE_DATA_READY);
+ if (ret < 0) {
+ pr_err("%s: failed to disable irq\n", __func__);
+ return ret;
+ }
+ }
+
+ return count;
+}
+
+static ssize_t m4sensorhub_pressure_show_setdelay(struct device *p_dev,
+ struct device_attribute *p_attr, char *p_buf)
+{
+ struct platform_device *pdev = to_platform_device(p_dev);
+ struct iio_dev *p_iio_dev =
+ platform_get_drvdata(pdev);
+ struct m4sensorhub_pressure_drvdata *p_priv_data = iio_priv(p_iio_dev);
+ return snprintf(p_buf, PAGE_SIZE, "%d\n", p_priv_data->samplerate);
+}
+
+static IIO_DEVICE_ATTR(enable, S_IRUGO | S_IWUSR,
+ m4sensorhub_pressure_show_enable,
+ m4sensorhub_pressure_store_enable, 0);
+static IIO_DEVICE_ATTR(setdelay, S_IRUGO | S_IWUSR,
+ m4sensorhub_pressure_show_setdelay,
+ m4sensorhub_pressure_store_setdelay, 0);
+
+#define M4_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr)
+
+static struct attribute *m4sensorhub_pressure_attributes[] = {
+ M4_DEV_ATTR(enable),
+ M4_DEV_ATTR(setdelay),
+ NULL
+};
+
+static const struct attribute_group m4sensorhub_pressure_group = {
+ .attrs = m4sensorhub_pressure_attributes,
+};
+
+static const struct iio_info m4sensorhub_pressure_iio_info = {
+ .driver_module = THIS_MODULE,
+ .attrs = &m4sensorhub_pressure_group,
+};
+
+static int m4sensorhub_pressure_setup_buffer(struct iio_dev *p_iio_dev)
+{
+ struct iio_buffer *p_buffer;
+ int ret;
+ p_buffer = iio_kfifo_allocate(p_iio_dev);
+ if (p_buffer == NULL) {
+ pr_err("%s: failed to allocate buffer\n", __func__);
+ ret = -ENOMEM;
+ return ret;
+ }
+
+ p_iio_dev->buffer = p_buffer;
+
+ /* need timestamps */
+ p_buffer->scan_timestamp = true;
+ ret = iio_buffer_register(p_iio_dev, p_iio_dev->channels,
+ p_iio_dev->num_channels);
+
+ if (ret < 0) {
+ pr_err("%s: failed to register buffer\n", __func__);
+ goto err;
+ }
+ p_buffer->access->set_bytes_per_datum(p_buffer,
+ sizeof(struct m4sensorhub_pressure_data));
+
+ ret = 0;
+ return ret;
+err:
+ iio_kfifo_free(p_buffer);
+
+ return ret;
+}
+
+static int m4sensorhub_pressure_probe(struct platform_device *pdev)
+{
+ int ret = -1;
+ struct iio_dev *p_iio_dev;
+ struct m4sensorhub_pressure_drvdata *p_priv_data;
+
+ p_iio_dev = iio_device_alloc(
+ sizeof(struct m4sensorhub_pressure_drvdata));
+
+ if (p_iio_dev == NULL) {
+ pr_err("%s: no mem", __func__);
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ p_priv_data = iio_priv(p_iio_dev);
+ p_priv_data->samplerate = -1;
+ p_priv_data->enable = false;
+ p_priv_data->p_m4sensorhub = NULL;
+
+ platform_set_drvdata(pdev, p_iio_dev);
+
+ p_iio_dev->info = &m4sensorhub_pressure_iio_info;
+ p_iio_dev->name = m4sensorhub_pressure_DRIVER_NAME;
+ p_iio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_HARDWARE;
+ p_iio_dev->channels = m4sensorhub_pressure_channels;
+ p_iio_dev->num_channels = ARRAY_SIZE(m4sensorhub_pressure_channels);
+
+ /* Register the channel with a buffer */
+ ret = m4sensorhub_pressure_setup_buffer(p_iio_dev);
+ if (ret < 0) {
+ pr_err("%s: can't setup buffer", __func__);
+ goto cleanup1;
+ }
+
+ ret = iio_device_register(p_iio_dev);
+ if (ret < 0) {
+ pr_err("%s: iio_register failed", __func__);
+ goto cleanup2;
+ }
+
+ ret = m4sensorhub_register_initcall(
+ m4sensorhub_pressure_driver_initcallback,
+ p_iio_dev);
+ if (ret < 0) {
+ pr_err("%s:Register init failed, ret = %d\n", __func__, ret);
+ goto cleanup3;
+ }
+
+ return 0;
+cleanup3:
+ iio_device_unregister(p_iio_dev);
+cleanup2:
+ iio_kfifo_free(p_iio_dev->buffer);
+ iio_buffer_unregister(p_iio_dev);
+cleanup1:
+ iio_device_free(p_iio_dev);
+ platform_set_drvdata(pdev, NULL);
+err:
+ return ret;
+}
+
+static int __exit m4sensorhub_pressure_remove(struct platform_device *pdev)
+{
+ struct iio_dev *p_iio_dev =
+ platform_get_drvdata(pdev);
+ struct m4sensorhub_pressure_drvdata *p_priv_data = iio_priv(p_iio_dev);
+
+ m4sensorhub_unregister_initcall(
+ m4sensorhub_pressure_driver_initcallback);
+ m4sensorhub_irq_unregister(p_priv_data->p_m4sensorhub,
+ M4SH_IRQ_PRESSURE_DATA_READY);
+
+ iio_kfifo_free(p_iio_dev->buffer);
+ iio_buffer_unregister(p_iio_dev);
+ iio_device_unregister(p_iio_dev);
+ iio_device_free(p_iio_dev);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static void m4sensorhub_pressure_shutdown(struct platform_device *pdev)
+{
+ return;
+}
+/* when we suspend, we disable pressure IRQ and set samplerate to -1
+when we resume, we wait for the app to re-register and that re-enables
+the sensor. This is global M4 strategy, nothing specific for this driver */
+#ifdef CONFIG_PM
+static int m4sensorhub_pressure_suspend(struct platform_device *pdev,
+ pm_message_t message)
+{
+ struct iio_dev *p_iio_dev =
+ platform_get_drvdata(pdev);
+ struct m4sensorhub_pressure_drvdata *p_priv_data = iio_priv(p_iio_dev);
+ struct m4sensorhub_data *p_m4sensorhub = p_priv_data->p_m4sensorhub;
+ int samplerate = -1;
+
+ m4sensorhub_irq_disable(p_m4sensorhub,
+ M4SH_IRQ_PRESSURE_DATA_READY);
+ m4sensorhub_reg_write(p_m4sensorhub,
+ M4SH_REG_PRESSURE_SAMPLERATE,
+ (char *)&samplerate, m4sh_no_mask);
+ return 0;
+}
+
+static int m4sensorhub_pressure_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+#else
+#define m4sensorhub_pressure_suspend NULL
+#define m4sensorhub_pressure_resume NULL
+#endif
+
+static struct of_device_id m4sensorhub_pressure_match_tbl[] = {
+ { .compatible = "mot,m4sensorhub_pressure" },
+ {},
+};
+
+static struct platform_driver m4sensorhub_pressure_driver = {
+ .probe = m4sensorhub_pressure_probe,
+ .remove = __exit_p(m4sensorhub_pressure_remove),
+ .shutdown = m4sensorhub_pressure_shutdown,
+ .suspend = m4sensorhub_pressure_suspend,
+ .resume = m4sensorhub_pressure_resume,
+ .driver = {
+ .name = m4sensorhub_pressure_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(m4sensorhub_pressure_match_tbl),
+ },
+};
+
+module_platform_driver(m4sensorhub_pressure_driver);
+
+MODULE_ALIAS("platform:m4sensorhub_pressure");
+MODULE_DESCRIPTION("M4 Sensor Hub Pressure IIO driver");
+MODULE_AUTHOR("Motorola");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/iio/m4sensorhub_pressure.h b/include/linux/iio/m4sensorhub_pressure.h
new file mode 100644
index 00000000000..856364f0e3a
--- /dev/null
+++ b/include/linux/iio/m4sensorhub_pressure.h
@@ -0,0 +1,12 @@
+/* HEADER */
+
+#include <linux/types.h>
+
+/* This needs to be thought through when we
+add other sensors */
+
+struct m4sensorhub_pressure_data {
+ int pressure;
+ int altitude;
+ long long timestamp;
+};