Index: linux-2.6.35/drivers/misc/mpu3050/mlsl.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.35/drivers/misc/mpu3050/mlsl.h    2010-12-22
14:09:28.000000000 +0800
@@ -0,0 +1,103 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    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, see
<http://www.gnu.org/licenses/>.
+  $
+ */
+
+#ifndef __MSSL_H__
+#define __MSSL_H__
+
+#include "mltypes.h"
+#include "mpu.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ------------ */
+/* - Defines. - */
+/* ------------ */
+
+/*
+ * NOTE : to properly support Yamaha compass reads,
+ * the max transfer size should be at least 9 B.
+ * Length in bytes, typically a power of 2 >= 2
+ */
+#define SERIAL_MAX_TRANSFER_SIZE 30
+
+/* ---------------------- */
+/* - Types definitions. - */
+/* ---------------------- */
+
+/* --------------------- */
+/* - Function p-types. - */
+/* --------------------- */
+
+       tMLError MLSLSerialOpen(char const *port,
+                               void **sl_handle);
+       tMLError MLSLSerialReset(void *sl_handle);
+       tMLError MLSLSerialClose(void *sl_handle);
+
+       tMLError MLSLSerialWriteSingle(void *sl_handle,
+                                      unsigned char slaveAddr,
+                                      unsigned char registerAddr,
+                                      unsigned char data);
+
+       tMLError MLSLSerialRead(void *sl_handle,
+                               unsigned char slaveAddr,
+                               unsigned char registerAddr,
+                               unsigned short length,
+                               unsigned char *data);
+
+       tMLError MLSLSerialWrite(void *sl_handle,
+                                unsigned char slaveAddr,
+                                unsigned short length,
+                                unsigned char const *data);
+
+       tMLError MLSLSerialReadMem(void *sl_handle,
+                                  unsigned char slaveAddr,
+                                  unsigned short memAddr,
+                                  unsigned short length,
+                                  unsigned char *data);
+
+       tMLError MLSLSerialWriteMem(void *sl_handle,
+                                   unsigned char slaveAddr,
+                                   unsigned short memAddr,
+                                   unsigned short length,
+                                   unsigned char const *data);
+
+       tMLError MLSLSerialReadFifo(void *sl_handle,
+                                   unsigned char slaveAddr,
+                                   unsigned short length,
+                                   unsigned char *data);
+
+       tMLError MLSLSerialWriteFifo(void *sl_handle,
+                                    unsigned char slaveAddr,
+                                    unsigned short length,
+                                    unsigned char const *data);
+
+       tMLError MLSLWriteCal(unsigned char *cal, unsigned int len);
+       tMLError MLSLReadCal(unsigned char *cal, unsigned int len);
+       tMLError MLSLGetCalLength(unsigned int *len);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+#endif                         /* MLSL_H */
Index: linux-2.6.35/drivers/misc/mpu3050/mpu-i2c.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.35/drivers/misc/mpu3050/mpu-i2c.c 2010-12-22
14:09:28.000000000 +0800
@@ -0,0 +1,204 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    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, see
<http://www.gnu.org/licenses/>.
+  $
+ */
+
+/**
+ *  @defgroup
+ *  @brief
+ *
+ *  @{
+ *      @file   mpu-i2c.c
+ *      @brief
+ *
+ */
+
+#include <mlos.h>
+
+#include <linux/i2c.h>
+#include "mpu.h"
+
+int sensor_i2c_write(struct i2c_adapter *i2c_adap,
+                    unsigned char address,
+                    unsigned int len, unsigned char const *data)
+{
+       struct i2c_msg msgs[1];
+       int res;
+
+       if (NULL == data || NULL == i2c_adap)
+               return -EINVAL;
+
+       msgs[0].addr = address;
+       msgs[0].flags = 0;      /* write */
+       msgs[0].buf = (unsigned char *) data;
+       msgs[0].len = len;
+
+       res = i2c_transfer(i2c_adap, msgs, 1);
+       if (res < 1)
+               return res;
+       else
+               return 0;
+}
+
+int sensor_i2c_write_register(struct i2c_adapter *i2c_adap,
+                             unsigned char address,
+                             unsigned char reg, unsigned char value)
+{
+       unsigned char data[2];
+
+       data[0] = reg;
+       data[1] = value;
+       return sensor_i2c_write(i2c_adap, address, 2, data);
+}
+
+int sensor_i2c_read(struct i2c_adapter *i2c_adap,
+                   unsigned char address,
+                   unsigned char reg,
+                   unsigned int len, unsigned char *data)
+{
+       struct i2c_msg msgs[2];
+       int res;
+
+       if (NULL == data || NULL == i2c_adap)
+               return -EINVAL;
+
+       msgs[0].addr = address;
+       msgs[0].flags = 0;      /* write */
+       msgs[0].buf = &reg;
+       msgs[0].len = 1;
+
+       msgs[1].addr = address;
+       msgs[1].flags = I2C_M_RD;
+       msgs[1].buf = data;
+       msgs[1].len = len;
+
+       res = i2c_transfer(i2c_adap, msgs, 2);
+       if (res < 2)
+               return res;
+       else
+               return 0;
+}
+
+int mpu_memory_read(struct i2c_adapter *i2c_adap,
+                   unsigned char mpu_addr,
+                   unsigned short mem_addr,
+                   unsigned int len, unsigned char *data)
+{
+       unsigned char bank[2];
+       unsigned char addr[2];
+       unsigned char buf;
+
+       struct i2c_msg msgs[1];
+       int ret;
+
+       if (NULL == data || NULL == i2c_adap)
+               return -EINVAL;
+
+       bank[0] = MPUREG_BANK_SEL;
+       bank[1] = mem_addr >> 8;
+
+       addr[0] = MPUREG_MEM_START_ADDR;
+       addr[1] = mem_addr & 0xFF;
+
+       buf = MPUREG_MEM_R_W;
+
+       /* Write Message */
+       msgs[0].addr = mpu_addr;
+       msgs[0].flags = 0;
+       msgs[0].buf = bank;
+       msgs[0].len = sizeof(bank);
+       ret = i2c_transfer(i2c_adap, msgs, 1);
+
+       msgs[0].addr = mpu_addr;
+       msgs[0].flags = 0;
+       msgs[0].buf = addr;
+       msgs[0].len = sizeof(addr);
+       ret = i2c_transfer(i2c_adap, msgs, 1);
+
+       msgs[0].addr = mpu_addr;
+       msgs[0].flags = 0;
+       msgs[0].buf = &buf;
+       msgs[0].len = 1;
+       ret = i2c_transfer(i2c_adap, msgs, 1);
+
+       msgs[0].addr = mpu_addr;
+       msgs[0].flags = I2C_M_RD;
+       msgs[0].buf = data;
+       msgs[0].len = len;
+
+       ret = i2c_transfer(i2c_adap, msgs, 1);
+       if (ret != 1)
+               return ret;
+       else
+               return 0;
+}
+
+int mpu_memory_write(struct i2c_adapter *i2c_adap,
+                    unsigned char mpu_addr,
+                    unsigned short mem_addr,
+                    unsigned int len, unsigned char const *data)
+{
+       unsigned char bank[2];
+       unsigned char addr[2];
+       unsigned char buf[513];
+
+       struct i2c_msg msgs[1];
+       int ret;
+
+       if (NULL == data || NULL == i2c_adap)
+               return -EINVAL;
+       if (len >= (sizeof(buf) - 1))
+               return -ENOMEM;
+
+       bank[0] = MPUREG_BANK_SEL;
+       bank[1] = mem_addr >> 8;
+
+       addr[0] = MPUREG_MEM_START_ADDR;
+       addr[1] = mem_addr & 0xFF;
+
+       buf[0] = MPUREG_MEM_R_W;
+
+       memcpy(buf + 1, data, len);
+
+       /* Write Message */
+       msgs[0].addr = mpu_addr;
+       msgs[0].flags = 0;
+       msgs[0].buf = bank;
+       msgs[0].len = sizeof(bank);
+       ret = i2c_transfer(i2c_adap, msgs, 1);
+
+       msgs[0].addr = mpu_addr;
+       msgs[0].flags = 0;
+       msgs[0].buf = addr;
+       msgs[0].len = sizeof(addr);
+       ret = i2c_transfer(i2c_adap, msgs, 1);
+
+       msgs[0].addr = mpu_addr;
+       msgs[0].flags = 0;
+       msgs[0].buf = (unsigned char *) buf;
+       msgs[0].len = len + 1;
+
+       ret = i2c_transfer(i2c_adap, msgs, 1);
+       if (ret != 1)
+               return ret;
+       else
+               return 0;
+}
+
+/**
+ *  @}
+ */
Index: linux-2.6.35/drivers/misc/mpu3050/mldl_cfg.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.35/drivers/misc/mpu3050/mldl_cfg.h        2010-12-22
14:09:28.000000000 +0800
@@ -0,0 +1,105 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    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, see
<http://www.gnu.org/licenses/>.
+  $
+ */
+
+/**
+ *  @addtogroup MLDL
+ *
+ *  @{
+ *      @file   mldl_cfg.h
+ *      @brief  The Motion Library Driver Layer Configuration header
file.
+ */
+
+#ifndef __MLDL_CFG_H__
+#define __MLDL_CFG_H__
+
+/* ------------------ */
+/* - Include Files. - */
+/* ------------------ */
+
+#include "mlsl.h"
+#include "mpu.h"
+
+/* --------------------- */
+/* -    Defines.       - */
+/* --------------------- */
+
+#define SAMPLING_PERIOD(mldl_cfg) \
+       (((((mldl_cfg->lpf) == 0) || ((mldl_cfg->lpf) == 7))
\
+               ? (8000)
\
+               : (1000))
\
+               / (mldl_cfg->divider + 1))
+
+/* --------------------- */
+/* -    Variables.     - */
+/* --------------------- */
+
+/* Platform data for the MPU */
+struct mldl_cfg {
+       /* MPU related configuration */
+       unsigned char addr;
+       unsigned char int_config;
+       unsigned char ext_sync;
+       unsigned char full_scale;
+       unsigned char lpf;
+       unsigned char clk_src;
+       unsigned char divider;
+       unsigned char dmp_enable;
+       unsigned char fifo_enable;
+       unsigned char dmp_cfg1;
+       unsigned char dmp_cfg2;
+       unsigned char gyro_power;
+       unsigned char offset_tc[MPU_NUM_AXES];
+       unsigned char ram[MPU_MEM_NUM_RAM_BANKS][MPU_MEM_BANK_SIZE];
+
+       /* MPU Related stored status and info */
+       unsigned char silicon_revision;
+       unsigned char product_id;
+       unsigned short trim;
+
+       /* Driver/Kernel related state information */
+       int is_suspended;
+
+       /* Slave related information */
+       struct ext_slave_descr *accel;
+       struct ext_slave_descr *compass;
+
+       struct mpu3050_platform_data *pdata;
+};
+
+
+int mpu3050_open(struct mldl_cfg *mldl_cfg, void *mlsl_handle);
+int mpu3050_resume(struct mldl_cfg *mldl_cfg, void *mlsl_handle,
+                  void *accel_handle,
+                  void *compass_handle,
+                  bool resume_accel, bool resume_compass);
+int mpu3050_suspend(struct mldl_cfg *mldl_cfg, void *mlsl_handle,
+                   void *accel_handle,
+                   void *compass_handle,
+                   bool suspend_accel, bool suspend_compass);
+int mpu3050_read_accel(struct mldl_cfg *mldl_cfg, void *mlsl_handle,
+                      unsigned char *data);
+int mpu3050_read_compass(struct mldl_cfg *mldl_cfg, void *mlsl_handle,
+                        unsigned char *data);
+
+
+#endif                         /* __MLDL_CFG_H__ */
+
+/**
+ *...@}
+ */
Index: linux-2.6.35/drivers/misc/mpu3050/mpuirq.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.35/drivers/misc/mpu3050/mpuirq.c  2010-12-23
11:16:17.000000000 +0800
@@ -0,0 +1,465 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    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, see
<http://www.gnu.org/licenses/>.
+  $
+ */
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/stat.h>
+#include <linux/irq.h>
+#include <linux/signal.h>
+#include <linux/miscdevice.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/workqueue.h>
+#include <linux/poll.h>
+#include <linux/input.h>
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#include "mpu.h"
+#include "mpuirq.h"
+#include "mldl_cfg.h"
+#include "mlsl.h"
+#include "mpu-i2c.h"
+#include "accel/bma023.h"
+
+#define MPUIRQ_NAME "mpuirq"
+
+/* function which gets accel data and sends it to MPU */
+
+DECLARE_WAIT_QUEUE_HEAD(mpuirq_wait);
+DECLARE_WAIT_QUEUE_HEAD(accelirq_wait);
+
+static DEFINE_SPINLOCK(accel_lock);
+
+struct mpuirq_dev_data {
+       struct work_struct work;
+       struct i2c_client *mpu_client;
+       struct miscdevice *dev;
+       int irq;
+       int pid;
+       int accel_divider;
+       int data_ready;
+       int timeout;
+};
+
+struct accelirq_dev_data {
+       struct work_struct work;
+       struct i2c_client *mpu_client;
+       struct input_dev *accel_input;
+       int irq;
+       int data_ready;
+       int timeout;
+       int freq;
+};
+
+static struct mpuirq_dev_data mpuirq_dev_data;
+static struct accelirq_dev_data accelirq_dev_data;
+static struct mpuirq_data mpuirq_data;
+static char *interface = MPUIRQ_NAME;
+
+static void mpu_accel_data_work_fcn(struct work_struct *work);
+static void accel_data_work_fcn(struct work_struct *work);
+
+static int accel_input_open(struct input_dev *input){
+       struct mldl_cfg *mldl_cfg = (struct mldl_cfg *)
i2c_get_clientdata(accelirq_dev_data.mpu_client);
+       struct accel_config *aconfig = accel_get_config();
+       aconfig->enable_count_hg_lg = 0x02;
+       mpu3050_suspend(mldl_cfg, accelirq_dev_data.mpu_client->adapter,
+
i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num),
+
i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num),
+                       1, 1);
+       mldl_cfg->accel->resume(accelirq_dev_data.mpu_client->adapter, 
+                                                       mldl_cfg->accel,

+
&mldl_cfg->pdata->accel);
+       aconfig->enable_count_hg_lg = 0x00;
+       return 0;
+}
+
+static void accel_input_close(struct input_dev *input){
+       struct mldl_cfg *mldl_cfg = (struct mldl_cfg *)
i2c_get_clientdata(accelirq_dev_data.mpu_client);
+       mpu3050_suspend(mldl_cfg, accelirq_dev_data.mpu_client->adapter,
+
i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num),
+
i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num),
+                       1, 0);
+}
+
+static int accel_input_init(void){
+       int res = 0;
+       accelirq_dev_data.accel_input = input_allocate_device();
+       if(!accelirq_dev_data.accel_input){
+               res = -ENOMEM;
+               printk(KERN_ERR "%s: accel input device memory alloc
failed\n",__func__);
+               goto error;
+       }
+       set_bit(EV_ABS, accelirq_dev_data.accel_input->evbit);
+       accelirq_dev_data.accel_input->name = "bma023_accel";
+       accelirq_dev_data.accel_input->id.bustype = BUS_I2C;
+       accelirq_dev_data.accel_input->id.product  = 0x69;
+       accelirq_dev_data.accel_input->open = accel_input_open;
+       accelirq_dev_data.accel_input->close = accel_input_close;
+//     accelirq_dev_data.accel_input->phys = "accel/input0";
+       input_set_abs_params(accelirq_dev_data.accel_input, ABS_X, -255,
255, 0, 0);
+       input_set_abs_params(accelirq_dev_data.accel_input, ABS_Y, -255,
255, 0, 0);
+       input_set_abs_params(accelirq_dev_data.accel_input, ABS_Z, -255,
255, 0, 0);
+
+       res = input_register_device(accelirq_dev_data.accel_input);
+       if(res){
+               printk(KERN_ERR "%s: accel input device register
failed\n",__func__);
+               goto reg_fail;
+       }
+       return res;
+reg_fail:
+       input_unregister_device(accelirq_dev_data.accel_input);
+error:
+       return res;
+}
+
+
+static int mpuirq_open(struct inode *inode, struct file *file)
+{
+       dev_dbg(mpuirq_dev_data.dev->this_device,
+               "%s current->pid %d\n", __func__, current->pid);
+       mpuirq_dev_data.pid = current->pid;
+       file->private_data = &mpuirq_dev_data;
+       /* we could do some checking on the flags supplied by "open" */
+       /* i.e. O_NONBLOCK */
+       /* -> set some flag to disable interruptible_sleep_on in
mpuirq_read */
+       return 0;
+}
+
+/* close function - called when the "file" /dev/mpuirq is closed in
userspace */
+static int mpuirq_release(struct inode *inode, struct file *file)
+{
+       dev_dbg(mpuirq_dev_data.dev->this_device, "mpuirq_release\n");
+       return 0;
+}
+
+/* read function called when from /dev/mpuirq is read */
+static ssize_t mpuirq_read(struct file *file,
+                          char *buf, size_t count, loff_t * ppos)
+{
+       int len, err;
+       struct mpuirq_dev_data *p_mpuirq_dev_data = file->private_data;
+
+       if (!mpuirq_dev_data.data_ready) {
+               wait_event_interruptible_timeout(mpuirq_wait,
+                                                mpuirq_dev_data.
+                                                data_ready,
+
mpuirq_dev_data.timeout);
+       }
+
+       if (mpuirq_dev_data.data_ready && NULL != buf
+           && count >= sizeof(mpuirq_data)) {
+               err = copy_to_user(buf, &mpuirq_data,
sizeof(mpuirq_data));
+       } else {
+               return 0;
+       }
+       if (err != 0) {
+               dev_err(p_mpuirq_dev_data->dev->this_device,
+                       "Copy to user returned %d\n", err);
+               return -EFAULT;
+       }
+       mpuirq_dev_data.data_ready = 0;
+       len = sizeof(mpuirq_data);
+       return len;
+}
+
+unsigned int mpuirq_poll(struct file *file, struct poll_table_struct
*poll)
+{
+       int mask = 0;
+       struct mpuirq_dev_data *p_mpuirq_dev_data = file->private_data;
+
+       poll_wait(file, &mpuirq_wait, poll);
+       if (mpuirq_dev_data.data_ready)
+               mask |= POLLIN | POLLRDNORM;
+       dev_dbg(p_mpuirq_dev_data->dev->this_device,
+               "%s: returning %d\n", __func__, mask);
+       return mask;
+}
+
+/* ioctl - I/O control */
+static long mpuirq_ioctl(struct file *file,
+                        unsigned int cmd, unsigned long arg)
+{
+       int retval = 0;
+       int data;
+
+       switch (cmd) {
+       case MPUIRQ_SET_TIMEOUT:
+               mpuirq_dev_data.timeout = arg;
+               break;
+
+       case MPUIRQ_GET_INTERRUPT_CNT:
+               data = mpuirq_data.interruptcount - 1;
+               if (mpuirq_data.interruptcount > 1)
+                       mpuirq_data.interruptcount = 1;
+
+               if (copy_to_user((int *) arg, &data, sizeof(int)))
+                       return -EFAULT;
+               break;
+       case MPUIRQ_GET_IRQ_TIME:
+               if (copy_to_user((int *) arg, &mpuirq_data.irqtime,
+                                sizeof(mpuirq_data.irqtime)))
+                       return -EFAULT;
+               mpuirq_data.irqtime = 0;
+               break;
+       case MPUIRQ_SET_FREQUENCY_DIVIDER:
+               mpuirq_dev_data.accel_divider = arg;
+               break;
+       default:
+               retval = -EINVAL;
+       }
+       return retval;
+}
+
+static void accel_data_work_fcn(struct work_struct *work){
+       signed short axis_data[3];
+       struct accelirq_dev_data *irq_dev_data =
+           (struct accelirq_dev_data *) work;
+       struct mldl_cfg *mldl_cfg = (struct mldl_cfg *)
+           i2c_get_clientdata(irq_dev_data->mpu_client);
+       struct i2c_adapter *accel_adapter;
+       accel_adapter =
i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
+       if(bma023_read_accel_xyz(accel_adapter, mldl_cfg, axis_data) <
0){
+               printk("accel work: read xyz of accel failed\n");
+               return;
+       }
+       input_event(irq_dev_data->accel_input, EV_ABS, ABS_X,
axis_data[0]);
+       input_event(irq_dev_data->accel_input, EV_ABS, ABS_Y,
axis_data[1]);
+       input_event(irq_dev_data->accel_input, EV_ABS, ABS_Z,
axis_data[2]);
+       input_sync(irq_dev_data->accel_input);
+}
+static void mpu_accel_data_work_fcn(struct work_struct *work)
+{
+       struct mpuirq_dev_data *mpuirq_dev_data =
+           (struct mpuirq_dev_data *) work;
+       struct mldl_cfg *mldl_cfg =
+           (struct mldl_cfg *)
+           i2c_get_clientdata(mpuirq_dev_data->mpu_client);
+       struct i2c_adapter *accel_adapter;
+       unsigned char wbuff[16];
+       unsigned char rbuff[16];
+       int ii;
+
+       accel_adapter =
i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
+       mldl_cfg->accel->read(accel_adapter,
+                             mldl_cfg->accel,
+                             &mldl_cfg->pdata->accel, rbuff);
+
+
+       /* @todo add other data formats here as well */
+       if (EXT_SLAVE_BIG_ENDIAN == mldl_cfg->accel->endian) {
+               for (ii = 0; ii < 3; ii++) {
+                       wbuff[2 * ii + 1] = rbuff[2 * ii + 1];
+                       wbuff[2 * ii + 2] = rbuff[2 * ii + 0];
+               }
+       } else {
+               memcpy(wbuff + 1, rbuff, mldl_cfg->accel->len);
+       }
+
+       wbuff[7] = 0;
+       wbuff[8] = 1;           /*set semaphore */
+
+       mpu_memory_write(mpuirq_dev_data->mpu_client->adapter,
+                        mldl_cfg->addr, 0x0108, 8, wbuff);
+}
+
+static irqreturn_t accelirq_handler(int irq, void *dev_id)
+{
+       static int accel_count;
+       static unsigned long flags;
+       accel_count++;
+       if(!(accelirq_dev_data.freq > 0))
+               return -1;
+       spin_lock_irqsave(&accel_lock, flags);
+       if(accel_count % accelirq_dev_data.freq == 0){
+               accel_count &= 0;
+               schedule_work((struct work_struct *)
(&accelirq_dev_data));
+       }
+       spin_unlock_irqrestore(&accel_lock, flags);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t mpuirq_handler(int irq, void *dev_id)
+{
+       static int mycount;
+       struct timeval irqtime;
+       mycount++;
+
+       mpuirq_data.interruptcount++;
+
+       /* wake up (unblock) for reading data from userspace */
+       /* and ignore first interrupt generated in module init */
+       if (mpuirq_data.interruptcount > 1) {
+               mpuirq_dev_data.data_ready = 1;
+
+               do_gettimeofday(&irqtime);
+               mpuirq_data.irqtime = (((long long) irqtime.tv_sec) <<
32);
+               mpuirq_data.irqtime += irqtime.tv_usec;
+
+               if ((mpuirq_dev_data.accel_divider >= 0) &&
+                   (0 ==
+                    (mycount % (mpuirq_dev_data.accel_divider + 1)))) {
+                       schedule_work((struct work_struct
+                                      *) (&mpuirq_dev_data));
+               }
+
+               wake_up_interruptible(&mpuirq_wait);
+       }
+
+       return IRQ_HANDLED;
+
+}
+
+/* define which file operations are supported */
+const struct file_operations mpuirq_fops = {
+       .owner = THIS_MODULE,
+       .read = mpuirq_read,
+       .poll = mpuirq_poll,
+
+#if HAVE_COMPAT_IOCTL
+       .compat_ioctl = mpuirq_ioctl,
+#endif
+#if HAVE_UNLOCKED_IOCTL
+       .unlocked_ioctl = mpuirq_ioctl,
+#endif
+       .open = mpuirq_open,
+       .release = mpuirq_release,
+};
+
+static struct miscdevice mpuirq_device = {
+       .minor = MISC_DYNAMIC_MINOR,
+       .name = MPUIRQ_NAME,
+       .fops = &mpuirq_fops,
+};
+
+int mpuirq_init(struct i2c_client *mpu_client)
+{
+       int res;
+       struct mldl_cfg *mldl_cfg =
+           (struct mldl_cfg *) i2c_get_clientdata(mpu_client);
+
+       /* work_struct initialization */
+       INIT_WORK((struct work_struct *) &mpuirq_dev_data,
+                 mpu_accel_data_work_fcn);
+       INIT_WORK((struct work_struct *) &accelirq_dev_data,
+                 accel_data_work_fcn);
+
+       mpuirq_dev_data.mpu_client = mpu_client;
+       accelirq_dev_data.mpu_client = mpu_client;
+
+       dev_info(&mpu_client->adapter->dev,
+                "Module Param interface = %s\n", interface);
+
+       accelirq_dev_data.irq = 299;
+       accelirq_dev_data.data_ready = 0;
+       accelirq_dev_data.timeout = 0;
+       accelirq_dev_data.freq = 1;
+
+       if(mldl_cfg->accel){
+           if (accelirq_dev_data.irq) {
+               res = request_irq(accelirq_dev_data.irq,
+
accelirq_handler,
+
(IRQF_TRIGGER_RISING),
+                                 "accel_irq", &accelirq_dev_data.irq);
+               if (res) {
+                   dev_err(&mpu_client->adapter->dev,
+                                               "accel: cannot register
IRQ %d\n", accelirq_dev_data.irq);
+               } else {
+                               res = accel_input_init();
+                               if(res)
+
dev_err(&mpu_client->adapter->dev,
+
"accel_input_register returned %d\n", res);
+                       }
+           } else {
+                       printk(KERN_ERR "accel irq: cannot regist irq
%d\n", accelirq_dev_data.irq);
+               res = 0;
+           }
+       } else {
+               printk(KERN_ERR "accel irq: No Accel\n");
+               res = 0;
+       }
+
+       mpuirq_dev_data.irq = mpu_client->irq;
+       mpuirq_dev_data.pid = 0;
+       mpuirq_dev_data.accel_divider = -1;
+       mpuirq_dev_data.data_ready = 0;
+       mpuirq_dev_data.timeout = 0;
+       mpuirq_dev_data.dev = &mpuirq_device;
+
+       if (mpuirq_dev_data.irq) {
+               unsigned long flags;
+               if (BIT_ACTL_LOW ==
+                   ((mldl_cfg->pdata->int_config) & BIT_ACTL))
+                       flags = IRQF_TRIGGER_FALLING;
+               else
+                       flags = IRQF_TRIGGER_RISING;
+
+               res =
+                   request_irq(mpuirq_dev_data.irq, mpuirq_handler,
flags,
+                               interface, &mpuirq_dev_data.irq);
+               if (res) {
+                       dev_err(&mpu_client->adapter->dev,
+                               "myirqtest: cannot register IRQ %d\n",
+                               mpuirq_dev_data.irq);
+               } else {
+                       res = misc_register(&mpuirq_device);
+                       if (res < 0) {
+                               dev_err(&mpu_client->adapter->dev,
+                                       "misc_register returned %d\n",
+                                       res);
+                               free_irq(mpuirq_dev_data.irq,
+                                        &mpuirq_dev_data.irq);
+                       }
+               }
+       } else {
+               res = 0;
+       }
+       return res;
+}
+
+void mpuirq_exit(void)
+{
+       /* Free the IRQ first before flushing the work */
+       if (mpuirq_dev_data.irq > 0)
+               free_irq(mpuirq_dev_data.irq, &mpuirq_dev_data.irq);
+
+       if (accelirq_dev_data.irq > 0)
+               free_irq(accelirq_dev_data.irq, &accelirq_dev_data.irq);
+
+       flush_scheduled_work();
+       input_unregister_device(accelirq_dev_data.accel_input);
+
+       dev_info(mpuirq_device.this_device, "Unregistering %s\n",
+                MPUIRQ_NAME);
+       misc_deregister(&mpuirq_device);
+
+       return;
+}
+
+module_param(interface, charp, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(interface, "The Interface name");

_______________________________________________
MeeGo-kernel mailing list
[email protected]
http://lists.meego.com/listinfo/meego-kernel

Reply via email to