diff options
author | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
---|---|---|
committer | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
commit | 871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch) | |
tree | 8718f573808810c2a1e8cb8fb6ac469093ca2784 /drivers/input/sensor/mmc328x_msensor | |
parent | 9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff) | |
download | FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2 FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip |
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized.
Changes are basically to make it look like kernel structure.
Diffstat (limited to 'drivers/input/sensor/mmc328x_msensor')
-rwxr-xr-x | drivers/input/sensor/mmc328x_msensor/Makefile | 4 | ||||
-rwxr-xr-x | drivers/input/sensor/mmc328x_msensor/mecs.c | 433 | ||||
-rwxr-xr-x | drivers/input/sensor/mmc328x_msensor/mecs.h | 60 | ||||
-rwxr-xr-x | drivers/input/sensor/mmc328x_msensor/mmc328x.c | 505 | ||||
-rwxr-xr-x | drivers/input/sensor/mmc328x_msensor/mmc328x.h | 91 |
5 files changed, 1093 insertions, 0 deletions
diff --git a/drivers/input/sensor/mmc328x_msensor/Makefile b/drivers/input/sensor/mmc328x_msensor/Makefile new file mode 100755 index 00000000..bdf4598d --- /dev/null +++ b/drivers/input/sensor/mmc328x_msensor/Makefile @@ -0,0 +1,4 @@ +s_wmt_msensor_mmc328x-objs += mmc328x.o +obj-m += s_wmt_msensor_mmc328x.o +s_wmt_generic_mecs-objs += mecs.o +obj-m += s_wmt_generic_mecs.o
\ No newline at end of file diff --git a/drivers/input/sensor/mmc328x_msensor/mecs.c b/drivers/input/sensor/mmc328x_msensor/mecs.c new file mode 100755 index 00000000..335ad266 --- /dev/null +++ b/drivers/input/sensor/mmc328x_msensor/mecs.c @@ -0,0 +1,433 @@ +/* + * Copyright (C) 2010 MEMSIC, 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 + * + */ + +#include <linux/interrupt.h> +#include <linux/i2c.h> +#include <linux/slab.h> +#include <linux/miscdevice.h> +#include <linux/delay.h> +#include <linux/input.h> +#include <linux/workqueue.h> +#include <linux/freezer.h> +#include <asm/uaccess.h> +//#include <linux/export.h> +#include <linux/module.h> +#include "mecs.h" + +#define DEBUG 0 + +#define ECS_DATA_DEV_NAME "ecompass_data" +#define ECS_CTRL_DEV_NAME "ecompass_ctrl" + +static int ecs_ctrl_open(struct inode *inode, struct file *file); +static int ecs_ctrl_release(struct inode *inode, struct file *file); +static int ecs_ctrl_ioctl(struct file *file, unsigned int cmd, unsigned long arg); + +static DECLARE_WAIT_QUEUE_HEAD(open_wq); + +static atomic_t open_count; +static atomic_t open_flag; +static atomic_t reserve_open_flag; + +static atomic_t a_flag; +static atomic_t m_flag; +static atomic_t o_flag; + +static short ecompass_delay = 0; + + +static struct input_dev *ecs_data_device; + +static struct file_operations ecs_ctrl_fops = { + .owner = THIS_MODULE, + .open = ecs_ctrl_open, + .release = ecs_ctrl_release, + .unlocked_ioctl = ecs_ctrl_ioctl, +}; + +static struct miscdevice ecs_ctrl_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = ECS_CTRL_DEV_NAME, + .fops = &ecs_ctrl_fops, +}; + +static int ecs_ctrl_open(struct inode *inode, struct file *file) +{ +#if 1 + atomic_set(&reserve_open_flag, 1); + atomic_set(&open_flag, 1); + atomic_set(&open_count, 1); + wake_up(&open_wq); + + return 0; +#else + int ret = -1; + + if (atomic_cmpxchg(&open_count, 0, 1) == 0) { + if (atomic_cmpxchg(&open_flag, 0, 1) == 0) { + atomic_set(&reserve_open_flag, 1); + wake_up(&open_wq); + ret = 0; + } + } + + return ret; +#endif +} + +static int ecs_ctrl_release(struct inode *inode, struct file *file) +{ + atomic_set(&reserve_open_flag, 0); + atomic_set(&open_flag, 0); + atomic_set(&open_count, 0); + wake_up(&open_wq); + + return 0; +} + +static int ecs_ctrl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + void __user *pa = (void __user *)arg; + short flag; + short delay; + int parms[4]; + int ypr[12]; + unsigned int uval = 0; + + switch (cmd) { + case ECOMPASS_IOC_SET_MODE: + break; + case ECOMPASS_IOC_SET_DELAY: + if (copy_from_user(&delay, pa, sizeof(delay))) + return -EFAULT; + ecompass_delay = delay; + break; + case ECOMPASS_IOC_GET_DELAY: + delay = ecompass_delay; + if (copy_to_user(pa, &delay, sizeof(delay))) + return -EFAULT; + break; + + case ECOMPASS_IOC_SET_AFLAG: + if (copy_from_user(&flag, pa, sizeof(flag))) + return -EFAULT; + if (flag < 0 || flag > 1) + return -EINVAL; + atomic_set(&a_flag, flag); + break; + case ECOMPASS_IOC_GET_AFLAG: + flag = atomic_read(&a_flag); + if (copy_to_user(pa, &flag, sizeof(flag))) + return -EFAULT; + break; + case ECOMPASS_IOC_SET_MFLAG: + if (copy_from_user(&flag, pa, sizeof(flag))) + return -EFAULT; + if (flag < 0 || flag > 1) + return -EINVAL; + atomic_set(&m_flag, flag); + break; + case ECOMPASS_IOC_GET_MFLAG: + flag = atomic_read(&m_flag); + if (copy_to_user(pa, &flag, sizeof(flag))) + return -EFAULT; + break; + case ECOMPASS_IOC_SET_OFLAG: + if (copy_from_user(&flag, pa, sizeof(flag))) + return -EFAULT; + if (flag < 0 || flag > 1) + return -EINVAL; + atomic_set(&o_flag, flag); + break; + case ECOMPASS_IOC_GET_OFLAG: + flag = atomic_read(&o_flag); + if (copy_to_user(pa, &flag, sizeof(flag))) + return -EFAULT; + break; + + case ECOMPASS_IOC_SET_APARMS: + if (copy_from_user(parms, pa, sizeof(parms))) + return -EFAULT; + /* acceleration x-axis */ + input_set_abs_params(ecs_data_device, ABS_X, + parms[0], parms[1], parms[2], parms[3]); + /* acceleration y-axis */ + input_set_abs_params(ecs_data_device, ABS_Y, + parms[0], parms[1], parms[2], parms[3]); + /* acceleration z-axis */ + input_set_abs_params(ecs_data_device, ABS_Z, + parms[0], parms[1], parms[2], parms[3]); + break; + case ECOMPASS_IOC_GET_APARMS: + break; + case ECOMPASS_IOC_SET_MPARMS: + if (copy_from_user(parms, pa, sizeof(parms))) + return -EFAULT; + /* magnetic raw x-axis */ + input_set_abs_params(ecs_data_device, ABS_HAT0X, + parms[0], parms[1], parms[2], parms[3]); + /* magnetic raw y-axis */ + input_set_abs_params(ecs_data_device, ABS_HAT0Y, + parms[0], parms[1], parms[2], parms[3]); + /* magnetic raw z-axis */ + input_set_abs_params(ecs_data_device, ABS_BRAKE, + parms[0], parms[1], parms[2], parms[3]); + break; + case ECOMPASS_IOC_GET_MPARMS: + break; + case ECOMPASS_IOC_SET_OPARMS_YAW: + if (copy_from_user(parms, pa, sizeof(parms))) + return -EFAULT; + /* orientation yaw */ + input_set_abs_params(ecs_data_device, ABS_RX, + parms[0], parms[1], parms[2], parms[3]); + break; + case ECOMPASS_IOC_GET_OPARMS_YAW: + break; + case ECOMPASS_IOC_SET_OPARMS_PITCH: + if (copy_from_user(parms, pa, sizeof(parms))) + return -EFAULT; + /* orientation pitch */ + input_set_abs_params(ecs_data_device, ABS_RY, + parms[0], parms[1], parms[2], parms[3]); + break; + case ECOMPASS_IOC_GET_OPARMS_PITCH: + break; + case ECOMPASS_IOC_SET_OPARMS_ROLL: + if (copy_from_user(parms, pa, sizeof(parms))) + return -EFAULT; + /* orientation roll */ + input_set_abs_params(ecs_data_device, ABS_RZ, + parms[0], parms[1], parms[2], parms[3]); + break; + case ECOMPASS_IOC_GET_OPARMS_ROLL: + break; + + case ECOMPASS_IOC_SET_YPR: + if (copy_from_user(ypr, pa, sizeof(ypr))) + return -EFAULT; + /* Report acceleration sensor information */ + if (atomic_read(&a_flag)) { + input_report_abs(ecs_data_device, ABS_X, ypr[0]); + input_report_abs(ecs_data_device, ABS_Y, ypr[1]); + input_report_abs(ecs_data_device, ABS_Z, ypr[2]); + input_report_abs(ecs_data_device, ABS_WHEEL, ypr[3]); + } + + /* Report magnetic sensor information */ + if (atomic_read(&m_flag)) { + input_report_abs(ecs_data_device, ABS_HAT0X, ypr[4]); + input_report_abs(ecs_data_device, ABS_HAT0Y, ypr[5]); + input_report_abs(ecs_data_device, ABS_BRAKE, ypr[6]); + input_report_abs(ecs_data_device, ABS_GAS, ypr[7]); + } + + /* Report orientation information */ + if (atomic_read(&o_flag)) { + input_report_abs(ecs_data_device, ABS_RX, ypr[8]); + input_report_abs(ecs_data_device, ABS_RY, ypr[9]); + input_report_abs(ecs_data_device, ABS_RZ, ypr[10]); + input_report_abs(ecs_data_device, ABS_RUDDER, ypr[11]); + } + + input_sync(ecs_data_device); + break; + + case WMT_IOCTL_SENSOR_GET_DRVID: + uval = 0; + if (copy_to_user((unsigned int*)arg, &uval, sizeof(unsigned int))) + { + return -EFAULT; + } + + default: + break; + } + + return 0; +} + +static ssize_t ecs_ctrl_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + + sprintf(buf, "ecompass_ctrl");//!!! + ret = strlen(buf) + 1; + + return ret; +} + +static DEVICE_ATTR(ecs_ctrl, S_IRUGO, ecs_ctrl_show, NULL); + +//********************** +static struct input_dev *g_input; +struct timer_list mytimer; +static void rep_pwer(long var) +{ + static int i = 0; + i++; +#if 0 + input_report_abs(g_input, ABS_X,i); + input_report_abs(g_input, ABS_Y, i); + input_report_abs(g_input, ABS_Z, i); + //input_report_abs(ecs_data_device, ABS_GAS, 2); + input_sync(g_input); +#endif + + input_report_abs(ecs_data_device, ABS_HAT0X,i); + input_report_abs(ecs_data_device, ABS_HAT0Y, i); + input_report_abs(ecs_data_device, ABS_BRAKE, i); + input_report_abs(ecs_data_device, ABS_GAS, 2); + input_sync(ecs_data_device); + //printk("<<<<memscid timer\n"); + mod_timer(&mytimer, jiffies + HZ/10); +} +//********************************** + +static int __init ecompass_init(void) +{ + int res = 0; + + pr_info("ecompass driver: init\n"); + + //*******************here want to report KEY_POWER using timer*** to test suspend & resume + init_timer(&mytimer); + mytimer.function = rep_pwer; + mytimer.expires = jiffies + 2*HZ; + mytimer.data = 100; + // add_timer(&mytimer); + printk("<<<<%s add timer ok!\n", __FUNCTION__); + + + int err=0; + g_input=input_allocate_device(); + if (!g_input) + return -ENOMEM; + else + printk(KERN_INFO "input device allocate Success !!\n"); + /* Setup input device */ + set_bit(EV_ABS, g_input->evbit); + /* Accelerometer [-78.5, 78.5]m/s2 in Q16 */ + input_set_abs_params(g_input, ABS_HAT0X, -5144576, 5144576, 0, 0); + input_set_abs_params(g_input, ABS_HAT0Y, -5144576, 5144576, 0, 0); + input_set_abs_params(g_input, ABS_BRAKE, -5144576, 5144576, 0, 0); + + /* Set InputDevice Name */ + g_input->name = "ecompass_data"; + + /* Register */ + //err = input_register_device(g_input); + //*****************************************2013-4-13 + + ecs_data_device = input_allocate_device(); + if (!ecs_data_device) { + res = -ENOMEM; + pr_err("%s: failed to allocate input device\n", __FUNCTION__); + goto out; + } + + set_bit(EV_ABS, ecs_data_device->evbit); + + /* 32768 == 1g, range -4g ~ +4g */ + /* acceleration x-axis */ + input_set_abs_params(ecs_data_device, ABS_X, + -32768*4, 32768*4, 0, 0); + /* acceleration y-axis */ + input_set_abs_params(ecs_data_device, ABS_Y, + -32768*4, 32768*4, 0, 0); + /* acceleration z-axis */ + input_set_abs_params(ecs_data_device, ABS_Z, + -32768*4, 32768*4, 0, 0); + /* acceleration status, 0 ~ 3 */ + input_set_abs_params(ecs_data_device, ABS_WHEEL, + 0, 100, 0, 0); + + /* 32768 == 1gauss, range -4gauss ~ +4gauss */ + /* magnetic raw x-axis */ + input_set_abs_params(ecs_data_device, ABS_HAT0X, + -32768*4, 32768*4, 0, 0); + /* magnetic raw y-axis */ + input_set_abs_params(ecs_data_device, ABS_HAT0Y, + -32768*4, 32768*4, 0, 0); + /* magnetic raw z-axis */ + input_set_abs_params(ecs_data_device, ABS_BRAKE, + -32768*4, 32768*4, 0, 0); + /* magnetic raw status, 0 ~ 3 */ + input_set_abs_params(ecs_data_device, ABS_GAS, + 0, 100, 0, 0); + + /* 65536 == 360degree */ + /* orientation yaw, 0 ~ 360 */ + input_set_abs_params(ecs_data_device, ABS_RX, + 0, 65536, 0, 0); + /* orientation pitch, -180 ~ 180 */ + input_set_abs_params(ecs_data_device, ABS_RY, + -65536/2, 65536/2, 0, 0); + /* orientation roll, -90 ~ 90 */ + input_set_abs_params(ecs_data_device, ABS_RZ, + -65536/4, 65536/4, 0, 0); + /* orientation status, 0 ~ 3 */ + input_set_abs_params(ecs_data_device, ABS_RUDDER, + 0, 100, 0, 0); + + ecs_data_device->name = ECS_DATA_DEV_NAME; +#if 1 + res = input_register_device(ecs_data_device); + if (res) { + pr_err("%s: unable to register input device: %s\n", + __FUNCTION__, ecs_data_device->name); + goto out_free_input; + } +#endif + + res = misc_register(&ecs_ctrl_device); + if (res) { + pr_err("%s: ecs_ctrl_device register failed\n", __FUNCTION__); + goto out_free_input; + } + res = device_create_file(ecs_ctrl_device.this_device, &dev_attr_ecs_ctrl); + if (res) { + pr_err("%s: device_create_file failed\n", __FUNCTION__); + goto out_deregister_misc; + } + + return 0; + +out_deregister_misc: + misc_deregister(&ecs_ctrl_device); +out_free_input: + input_free_device(ecs_data_device); +out: + return res; +} + +static void __exit ecompass_exit(void) +{ + pr_info("ecompass driver: exit\n"); + device_remove_file(ecs_ctrl_device.this_device, &dev_attr_ecs_ctrl); + misc_deregister(&ecs_ctrl_device); + input_free_device(ecs_data_device); +} + +module_init(ecompass_init); +module_exit(ecompass_exit); + +MODULE_DESCRIPTION("MEMSIC eCompass Driver"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/input/sensor/mmc328x_msensor/mecs.h b/drivers/input/sensor/mmc328x_msensor/mecs.h new file mode 100755 index 00000000..c328e585 --- /dev/null +++ b/drivers/input/sensor/mmc328x_msensor/mecs.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2010 MEMSIC, 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 + * + */ + +/* + * Definitions for ECOMPASS magnetic sensor chip. + */ +#ifndef __ECOMPASS_H__ +#define __ECOMPASS_H__ + +#include <linux/ioctl.h> + +/* Use 'e' as magic number */ +#define ECOMPASS_IOM 'e' + +/* IOCTLs for ECOMPASS device */ +#define ECOMPASS_IOC_SET_MODE _IOW(ECOMPASS_IOM, 0x00, short) +#define ECOMPASS_IOC_SET_DELAY _IOW(ECOMPASS_IOM, 0x01, short) +#define ECOMPASS_IOC_GET_DELAY _IOR(ECOMPASS_IOM, 0x02, short) + +#define ECOMPASS_IOC_SET_AFLAG _IOW(ECOMPASS_IOM, 0x10, short) +#define ECOMPASS_IOC_GET_AFLAG _IOR(ECOMPASS_IOM, 0x11, short) +#define ECOMPASS_IOC_SET_MFLAG _IOW(ECOMPASS_IOM, 0x12, short) +#define ECOMPASS_IOC_GET_MFLAG _IOR(ECOMPASS_IOM, 0x13, short) +#define ECOMPASS_IOC_SET_OFLAG _IOW(ECOMPASS_IOM, 0x14, short) +#define ECOMPASS_IOC_GET_OFLAG _IOR(ECOMPASS_IOM, 0x15, short) + +#define ECOMPASS_IOC_SET_APARMS _IOW(ECOMPASS_IOM, 0x20, int[4]) +#define ECOMPASS_IOC_GET_APARMS _IOR(ECOMPASS_IOM, 0x21, int[4]) +#define ECOMPASS_IOC_SET_MPARMS _IOW(ECOMPASS_IOM, 0x22, int[4]) +#define ECOMPASS_IOC_GET_MPARMS _IOR(ECOMPASS_IOM, 0x23, int[4]) +#define ECOMPASS_IOC_SET_OPARMS_YAW _IOW(ECOMPASS_IOM, 0x24, int[4]) +#define ECOMPASS_IOC_GET_OPARMS_YAW _IOR(ECOMPASS_IOM, 0x25, int[4]) +#define ECOMPASS_IOC_SET_OPARMS_PITCH _IOW(ECOMPASS_IOM, 0x26, int[4]) +#define ECOMPASS_IOC_GET_OPARMS_PITCH _IOR(ECOMPASS_IOM, 0x27, int[4]) +#define ECOMPASS_IOC_SET_OPARMS_ROLL _IOW(ECOMPASS_IOM, 0x28, int[4]) +#define ECOMPASS_IOC_GET_OPARMS_ROLL _IOR(ECOMPASS_IOM, 0x29, int[4]) + +#define ECOMPASS_IOC_SET_YPR _IOW(ECOMPASS_IOM, 0x30, int[12]) + +#define WMTGSENSOR_IOCTL_MAGIC 0x09 +#define WMT_IOCTL_SENSOR_GET_DRVID _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x04, unsigned int) +#endif /* __ECOMPASS_H__ */ + diff --git a/drivers/input/sensor/mmc328x_msensor/mmc328x.c b/drivers/input/sensor/mmc328x_msensor/mmc328x.c new file mode 100755 index 00000000..4148b5f1 --- /dev/null +++ b/drivers/input/sensor/mmc328x_msensor/mmc328x.c @@ -0,0 +1,505 @@ +/*
+ * Copyright (C) 2011 MEMSIC, 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
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/miscdevice.h>
+#include <linux/mutex.h>
+#include <linux/mm.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/sysctl.h>
+#include <asm/uaccess.h>
+#include <linux/input.h>
+//#include <linux/mmc328x.h>
+#include "mmc328x.h"
+#define DEBUG 0
+#define MAX_FAILURE_COUNT 3
+#define READMD 0
+
+#define MMC328X_DELAY_TM 10 /* ms */
+#define MMC328X_DELAY_RM 10 /* ms */
+#define MMC328X_DELAY_STDN 1 /* ms */
+#define MMC328X_DELAY_RRM 1 /* ms */
+
+#define MMC328X_RETRY_COUNT 3
+#define MMC328X_RRM_INTV 100
+
+
+//******************************* move from memsicd 2013-4-26
+#define MMC328X_OFFSET_X 4096
+#define MMC328X_OFFSET_Y 4096
+#define MMC328X_OFFSET_Z 4096
+//******************************************
+
+#define MMC328X_DEV_NAME "mmc328x"
+#define CONFIG_SENSORS_MMC328xMA_MAG //add rambo 2013-4-20
+struct i2c_client *g_client;
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+static u32 read_idx = 0;
+
+static struct i2c_client *this_client;
+
+static struct wmt_msensor_data l_sensorconfig = {
+ .op = 0,
+ .int_gpio = 3,
+ .samp = 5,
+ .xyz_axis = {
+ {ABS_X, -1},
+ {ABS_Y, 1},
+ {ABS_Z, -1},
+ },
+ .sensor_proc = NULL,
+ .isdbg = 0,
+ .sensor_samp = 10, // 1 sample/second
+ .sensor_enable = 1, // enable sensor
+ .test_pass = 0, // for test program
+ .offset={0,0,0},
+};
+
+static int get_axisset(void)
+{
+ char varbuf[64];
+ int n;
+ int varlen;
+
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+ if (wmt_getsyspara("wmt.io.msensor328x", varbuf, &varlen)) {
+ printk("Can't get gsensor config in u-boot!!!!\n");
+ //return -1;
+ } else {
+ n = sscanf(varbuf, "%d:%d:%d:%d:%d:%d",
+
+ &(l_sensorconfig.xyz_axis[0][0]),
+ &(l_sensorconfig.xyz_axis[0][1]),
+ &(l_sensorconfig.xyz_axis[1][0]),
+ &(l_sensorconfig.xyz_axis[1][1]),
+ &(l_sensorconfig.xyz_axis[2][0]),
+ &(l_sensorconfig.xyz_axis[2][1])
+
+ );
+ if (n != 6) {
+ printk("gsensor format is error in u-boot!!!\n");
+ return -1;
+ }
+ l_sensorconfig.sensor_samp = l_sensorconfig.samp;
+
+ printk("get the sensor config: %d:%d:%d:%d:%d:%d\n",
+
+ l_sensorconfig.xyz_axis[0][0],
+ l_sensorconfig.xyz_axis[0][1],
+ l_sensorconfig.xyz_axis[1][0],
+ l_sensorconfig.xyz_axis[1][1],
+ l_sensorconfig.xyz_axis[2][0],
+ l_sensorconfig.xyz_axis[2][1]
+ );
+ }
+ return 0;
+}
+
+
+static int mmc328x_i2c_rx_data(char *buf, int len)
+{
+ uint8_t i;
+ struct i2c_msg msgs[] = {
+ {
+ .addr = this_client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = buf,
+ },
+ {
+ .addr = this_client->addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = buf,
+ }
+ };
+
+ for (i = 0; i < MMC328X_RETRY_COUNT; i++) {
+ if (i2c_transfer(this_client->adapter, msgs, 2) >= 0) {
+ break;
+ }
+ mdelay(10);
+ }
+
+ if (i >= MMC328X_RETRY_COUNT) {
+ pr_err("%s: retry over %d\n", __FUNCTION__, MMC328X_RETRY_COUNT);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int mmc328x_i2c_tx_data(char *buf, int len)
+{
+ uint8_t i;
+ struct i2c_msg msg[] = {
+ {
+ .addr = this_client->addr,
+ .flags = 0,
+ .len = len,
+ .buf = buf,
+ }
+ };
+
+ for (i = 0; i < MMC328X_RETRY_COUNT; i++) {
+ if (i2c_transfer(this_client->adapter, msg, 1) >= 0) {
+ break;
+ }
+ mdelay(10);
+ }
+
+ if (i >= MMC328X_RETRY_COUNT) {
+ pr_err("%s: retry over %d\n", __FUNCTION__, MMC328X_RETRY_COUNT);
+ return -EIO;
+ }
+ return 0;
+}
+
+static int mmc328x_open(struct inode *inode, struct file *file)
+{
+ return nonseekable_open(inode, file);
+}
+
+static int mmc328x_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int mmc328x_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ void __user *pa = (void __user *)arg;
+ unsigned char data[16] = {0};
+ int vec[3] = {0};
+ int tmp[3] = {0};
+
+ int MD_times = 0;
+
+ switch (cmd) {
+ case MMC328X_IOC_TM:
+ data[0] = MMC328X_REG_CTRL;
+ data[1] = MMC328X_CTRL_TM;
+ if (mmc328x_i2c_tx_data(data, 2) < 0) {
+ return -EFAULT;
+ }
+ /* wait TM done for coming data read */
+ msleep(MMC328X_DELAY_TM);
+ break;
+ case MMC328X_IOC_RM:
+ data[0] = MMC328X_REG_CTRL;
+ data[1] = MMC328X_CTRL_RM;
+ if (mmc328x_i2c_tx_data(data, 2) < 0) {
+ return -EFAULT;
+ }
+ /* wait external capacitor charging done for next SET*/
+ msleep(MMC328X_DELAY_RM);
+ break;
+ case MMC328X_IOC_RRM:
+ data[0] = MMC328X_REG_CTRL;
+ data[1] = MMC328X_CTRL_RRM;
+ if (mmc328x_i2c_tx_data(data, 2) < 0) {
+ return -EFAULT;
+ }
+ /* wait external capacitor charging done for next RRM */
+ msleep(MMC328X_DELAY_RM);
+ break;
+ case MMC328X_IOC_READ:
+ data[0] = MMC328X_REG_DATA;
+ if (mmc328x_i2c_rx_data(data, 6) < 0) {
+ return -EFAULT;
+ }
+ tmp[0] = data[1] << 8 | data[0];
+ tmp[1] = data[3] << 8 | data[2];
+ tmp[2] = data[5] << 8 | data[4];
+ tmp[2] = 8192 - tmp[2] ;
+ //add 2013-4-26
+ tmp[0] -= MMC328X_OFFSET_X;
+ tmp[1] -= MMC328X_OFFSET_Y;
+ tmp[2] -= MMC328X_OFFSET_Z;
+ //add end
+ vec[0] = tmp[l_sensorconfig.xyz_axis[0][0]]*l_sensorconfig.xyz_axis[0][1];
+
+ vec[1] = tmp[l_sensorconfig.xyz_axis[1][0]]*l_sensorconfig.xyz_axis[1][1];
+
+ vec[2] = tmp[l_sensorconfig.xyz_axis[2][0]]*l_sensorconfig.xyz_axis[2][1];
+
+ #if DEBUG
+ printk("[X - %04x] [Y - %04x] [Z - %04x]\n",
+ vec[0], vec[1], vec[2]);
+ #endif
+ if (copy_to_user(pa, vec, sizeof(vec))) {
+ return -EFAULT;
+ }
+ break;
+ case MMC328X_IOC_READXYZ:
+ /* do RM every MMC328X_RRM_INTV times read */
+ if (!(read_idx % MMC328X_RRM_INTV)) {
+#ifdef CONFIG_SENSORS_MMC328xMA_MAG
+ data[0] = MMC328X_REG_CTRL;
+ data[1] = MMC328X_CTRL_RRM;
+ mmc328x_i2c_tx_data(data, 2);
+ msleep(MMC328X_DELAY_RRM);
+#endif
+ /* RM */
+ data[0] = MMC328X_REG_CTRL;
+ data[1] = MMC328X_CTRL_RM;
+ /* not check return value here, assume it always OK */
+ mmc328x_i2c_tx_data(data, 2);
+ /* wait external capacitor charging done for next RM */
+ msleep(MMC328X_DELAY_RM);
+ }
+ read_idx++;
+
+ /* send TM cmd before read */
+ data[0] = MMC328X_REG_CTRL;
+ data[1] = MMC328X_CTRL_TM;
+ /* not check return value here, assume it always OK */
+ mmc328x_i2c_tx_data(data, 2);
+ /* wait TM done for coming data read */
+ msleep(MMC328X_DELAY_TM);
+#if READMD
+ /* Read MD */
+ data[0] = MMC328X_REG_DS;
+ if (mmc328x_i2c_rx_data(data, 1) < 0) {
+ return -EFAULT;
+ }
+ while (!(data[0] & 0x01)) {
+ msleep(1);
+ /* Read MD again*/
+ data[0] = MMC328X_REG_DS;
+ if (mmc328x_i2c_rx_data(data, 1) < 0) {
+ return -EFAULT;
+ }
+
+ if (data[0] & 0x01) break;
+ MD_times++;
+ if (MD_times > 2) {
+ #if DEBUG
+ printk("TM not work!!");
+ #endif
+ return -EFAULT;
+ }
+ }
+#endif
+ /* read xyz raw data */
+ data[0] = MMC328X_REG_DATA;
+ if (mmc328x_i2c_rx_data(data, 6) < 0) {
+ return -EFAULT;
+ }
+ tmp[0] = data[1] << 8 | data[0];
+ tmp[1] = data[3] << 8 | data[2];
+ tmp[2] = data[5] << 8 | data[4];
+ tmp[2] = 8192 - tmp[2];
+ //add 2013-4-26
+ tmp[0] -= MMC328X_OFFSET_X;
+ tmp[1] -= MMC328X_OFFSET_Y;
+ tmp[2] -= MMC328X_OFFSET_Z;
+ //add
+ vec[0] = tmp[l_sensorconfig.xyz_axis[0][0]]*l_sensorconfig.xyz_axis[0][1];
+
+ vec[1] = tmp[l_sensorconfig.xyz_axis[1][0]]*l_sensorconfig.xyz_axis[1][1];
+
+ vec[2] = tmp[l_sensorconfig.xyz_axis[2][0]]*l_sensorconfig.xyz_axis[2][1];
+
+
+
+ #if DEBUG
+ printk("[X - %04x] [Y - %04x] [Z - %04x]\n",
+ vec[0], vec[1], vec[2]);
+ #endif
+ if (copy_to_user(pa, vec, sizeof(vec))) {
+ return -EFAULT;
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static ssize_t mmc328x_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+
+ sprintf(buf, "MMC328X");//!!!
+ ret = strlen(buf) + 1;
+
+ return ret;
+}
+
+static DEVICE_ATTR(mmc328x, S_IRUGO, mmc328x_show, NULL);
+
+static struct file_operations mmc328x_fops = {
+ .owner = THIS_MODULE,
+ .open = mmc328x_open,
+ .release = mmc328x_release,
+ .unlocked_ioctl = mmc328x_ioctl,
+};
+
+static struct miscdevice mmc328x_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = MMC328X_DEV_NAME,
+ .fops = &mmc328x_fops,
+};
+
+static int mmc328x_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ unsigned char data[16] = {0};
+ int res = 0;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ pr_err("%s: functionality check failed\n", __FUNCTION__);
+ res = -ENODEV;
+ goto out;
+ }
+ this_client = client;
+
+ res = misc_register(&mmc328x_device);//
+ if (res) {
+ pr_err("%s: mmc328x_device register failed\n", __FUNCTION__);
+ goto out;
+ }
+ res = device_create_file(&client->dev, &dev_attr_mmc328x);//
+ if (res) {
+ pr_err("%s: device_create_file failed\n", __FUNCTION__);
+ goto out_deregister;
+ }
+
+ /* send RM/RRM cmd to mag sensor first of all */
+#ifdef CONFIG_SENSORS_MMC328xMA_MAG
+ data[0] = MMC328X_REG_CTRL;
+ data[1] = MMC328X_CTRL_RRM;
+ if (mmc328x_i2c_tx_data(data, 2) < 0) {
+ }
+ msleep(MMC328X_DELAY_RRM);
+ data[0] = MMC328X_REG_CTRL;
+ data[1] = MMC328X_CTRL_TM;
+ if (mmc328x_i2c_tx_data(data, 2) < 0) {
+ }
+ msleep(5*MMC328X_DELAY_TM);
+#endif
+
+ data[0] = MMC328X_REG_CTRL;
+ data[1] = MMC328X_CTRL_RM;
+ if (mmc328x_i2c_tx_data(data, 2) < 0) {
+ /* assume RM always success */
+ }
+#ifndef CONFIG_SENSORS_MMC328xMA_MAG
+ /* wait external capacitor charging done for next RM */
+ msleep(MMC328X_DELAY_RM);
+#else
+ msleep(10*MMC328X_DELAY_RM);
+ data[0] = MMC328X_REG_CTRL;
+ data[1] = MMC328X_CTRL_TM;
+ if (mmc328x_i2c_tx_data(data, 2) < 0) {
+ }
+#endif
+
+ return 0;
+
+out_deregister:
+ misc_deregister(&mmc328x_device);
+out:
+ return res;
+}
+
+static int mmc328x_remove(struct i2c_client *client)
+{
+ device_remove_file(&client->dev, &dev_attr_mmc328x);
+ misc_deregister(&mmc328x_device);
+
+ return 0;
+}
+
+static const struct i2c_device_id mmc328x_id[] = {
+ { MMC328X_I2C_NAME, 0 },
+ { }
+};
+
+static struct i2c_driver mmc328x_driver = {
+ .probe = mmc328x_probe,
+ .remove = mmc328x_remove,
+ .id_table = mmc328x_id,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = MMC328X_I2C_NAME,
+ },
+};
+
+//****************************add by rambo to create i2c client 2013-4-18
+static struct i2c_board_info mmc328x_board_info =
+{
+ .type = MMC328X_I2C_NAME,
+ .addr = MMC328X_I2C_ADDR,
+};
+
+//******************************************
+
+static int __init mmc328x_init(void)
+{
+ int ret;
+ pr_info("mmc328x driver: init\n");
+
+ ret = get_axisset();
+ struct i2c_adapter *adapter;
+ adapter = i2c_get_adapter(0);
+ if (!adapter)
+ {
+ printk("<<<<<%s i2c get adapter fail!\n", __FUNCTION__);
+ return -1;
+ }
+ g_client = i2c_new_device(adapter, &mmc328x_board_info);
+ if (!g_client)
+ {
+ printk("<<<<%s i2c new device fail!\n", __FUNCTION__);
+ i2c_put_adapter(adapter);
+ return -1;
+ }
+ i2c_put_adapter(adapter);
+
+ return i2c_add_driver(&mmc328x_driver);
+}
+
+static void __exit mmc328x_exit(void)
+{
+ if (g_client != NULL)
+ {
+ i2c_unregister_device(g_client);
+ }
+ pr_info("mmc328x driver: exit\n");
+ i2c_del_driver(&mmc328x_driver);
+}
+
+module_init(mmc328x_init);
+module_exit(mmc328x_exit);
+
+MODULE_DESCRIPTION("MEMSIC MMC328X Magnetic Sensor Driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/input/sensor/mmc328x_msensor/mmc328x.h b/drivers/input/sensor/mmc328x_msensor/mmc328x.h new file mode 100755 index 00000000..f272ea1d --- /dev/null +++ b/drivers/input/sensor/mmc328x_msensor/mmc328x.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2010 MEMSIC, 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 + * + */ + +/* + * Definitions for mmc328x magnetic sensor chip. + */ +#ifndef __MMC328X_H__ +#define __MMC328X_H__ + +#include <linux/ioctl.h> + +#define MMC328X_I2C_NAME "mmc328x" + +/* + * This address comes must match the part# on your target. + * Address to the sensor part# support as following list: + * MMC3280MS - 0110000b + * MMC3281MS - 0110001b + * MMC3282MS - 0110010b + * MMC3283MS - 0110011b + * MMC3284MS - 0110100b + * MMC3285MS - 0110101b + * MMC3286MS - 0110110b + * MMC3287MS - 0110111b + * Please refer to sensor datasheet for detail. + */ + struct wmt_msensor_data{ + // for control + int int_gpio; //0-3 + int op; + int samp; + int xyz_axis[3][2]; // (axis,direction) + struct proc_dir_entry* sensor_proc; + struct input_dev *input_dev; + //struct work_struct work; + struct delayed_work work; // for polling + struct workqueue_struct *queue; + int isdbg; + int sensor_samp; // + int sensor_enable; // 0 --> disable sensor, 1 --> enable sensor + int test_pass; + int offset[3]; + struct i2c_client *client; +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend earlysuspend; +#endif + +}; +#define MMC328X_I2C_ADDR 0x30 + +/* MMC328X register address */ +#define MMC328X_REG_CTRL 0x07 +#define MMC328X_REG_DATA 0x00 +#define MMC328X_REG_DS 0x06 + +/* MMC328X control bit */ +#define MMC328X_CTRL_TM 0x01 +#define MMC328X_CTRL_RM 0x20 +#define MMC328X_CTRL_RRM 0x40 +#define MMC328X_CTRL_NOBOOST 0x10 + +/* Use 'm' as magic number */ +#define MMC328X_IOM 'm' + +/* IOCTLs for MMC328X device */ +#define MMC328X_IOC_TM _IO (MMC328X_IOM, 0x00) +#define MMC328X_IOC_RM _IO (MMC328X_IOM, 0x01) +#define MMC328X_IOC_READ _IOR(MMC328X_IOM, 0x02, int[3]) +#define MMC328X_IOC_READXYZ _IOR(MMC328X_IOM, 0x03, int[3]) +#define MMC328X_IOC_RRM _IO (MMC328X_IOM, 0x04) +#define MMC328X_IOC_NOBOOST _IO (MMC328X_IOM, 0x05) + +#endif /* __MMC328X_H__ */ + |