From f07e8d9799fb413e856d32c489b7a504eee117cb Mon Sep 17 00:00:00 2001 From: linjh Date: Wed, 20 Apr 2011 17:14:19 +0800 Subject: [PATCH 1/3] modify suspend of gps and default close gyroscope --- drivers/input/gsensor/Kconfig | 2 +- drivers/misc/gps/rk29_gps.c | 55 ++++++++++++++++------------------- drivers/misc/gps/rk29_gps.h | 1 - 3 files changed, 26 insertions(+), 32 deletions(-) diff --git a/drivers/input/gsensor/Kconfig b/drivers/input/gsensor/Kconfig index 31b87eb67403..687fcec87527 100644 --- a/drivers/input/gsensor/Kconfig +++ b/drivers/input/gsensor/Kconfig @@ -30,7 +30,7 @@ config GS_MMA8452 config GS_L3G4200D bool "gs_l3g4200d" depends on G_SENSOR_DEVICE - default y + default n help To have support for your specific gsesnor you will have to select the proper drivers which depend on this option. diff --git a/drivers/misc/gps/rk29_gps.c b/drivers/misc/gps/rk29_gps.c index f36b9cc43e02..09eedb74eb12 100644 --- a/drivers/misc/gps/rk29_gps.c +++ b/drivers/misc/gps/rk29_gps.c @@ -108,17 +108,19 @@ int rk29_gps_suspend(struct platform_device *pdev, pm_message_t state) { struct rk29_gps_data *pdata = pdev->dev.platform_data; - if(!pdata) + if(!pdata) { + printk("%s: pdata = NULL ...... \n", __func__); return -1; + } if(pdata->power_flag == 1) { - pdata->suspend = 1; - queue_work(pdata->wq, &pdata->work); + rk29_gps_uart_to_gpio(pdata->uart_id); + pdata->power_down(); + pdata->reset(GPIO_LOW); } printk("%s\n",__FUNCTION__); - return 0; } @@ -126,48 +128,39 @@ int rk29_gps_resume(struct platform_device *pdev) { struct rk29_gps_data *pdata = pdev->dev.platform_data; - if(!pdata) + if(!pdata) { + printk("%s: pdata = NULL ...... \n", __func__); return -1; + } if(pdata->power_flag == 1) { - pdata->suspend = 0; queue_work(pdata->wq, &pdata->work); } printk("%s\n",__FUNCTION__); - return 0; } static void rk29_gps_delay_power_downup(struct work_struct *work) { - //int ret; struct rk29_gps_data *pdata = container_of(work, struct rk29_gps_data, work); if (pdata == NULL) { printk("%s: pdata = NULL\n", __func__); return; } + DBG("%s: suspend=%d\n", __func__, pdata->suspend); + down(&pdata->power_sem); - //if (ret < 0) { - // printk("%s: down power_sem error ret = %d\n", __func__, ret); - // return ; - //} - if (pdata->suspend) { - rk29_gps_uart_to_gpio(pdata->uart_id); - pdata->power_down(); - pdata->reset(GPIO_LOW); - } - else { - pdata->reset(GPIO_LOW); - mdelay(10); - pdata->power_up(); - mdelay(500); - pdata->reset(GPIO_HIGH); - rk29_gps_gpio_to_uart(pdata->uart_id); - } + pdata->reset(GPIO_LOW); + mdelay(5); + pdata->power_up(); + msleep(500); + pdata->reset(GPIO_HIGH); + rk29_gps_gpio_to_uart(pdata->uart_id); + up(&pdata->power_sem); } @@ -182,8 +175,11 @@ ssize_t rk29_gps_read(struct file *filp, char __user *ptr, size_t size, loff_t * { if (ptr == NULL) printk("%s: user space address is NULL\n", __func__); - if (pgps == NULL) + + if (pgps == NULL) { printk("%s: pgps addr is NULL\n", __func__); + return -1; + } put_user(pgps->uart_id, ptr); @@ -206,9 +202,9 @@ int rk29_gps_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, uns switch (cmd){ case ENABLE: pdata->reset(GPIO_LOW); - mdelay(10); + mdelay(5); pdata->power_up(); - mdelay(10); + mdelay(5); rk29_gps_gpio_to_uart(pdata->uart_id); mdelay(500); pdata->reset(GPIO_HIGH); @@ -237,7 +233,7 @@ int rk29_gps_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, uns int rk29_gps_release(struct inode *inode, struct file *filp) { - DBG("rk29_gps_release\n"); + DBG("rk29_gps_release\n"); return 0; } @@ -274,7 +270,6 @@ static int rk29_gps_probe(struct platform_device *pdev) pdata->wq = create_freezeable_workqueue("rk29_gps"); INIT_WORK(&pdata->work, rk29_gps_delay_power_downup); pdata->power_flag = 0; - pdata->suspend = 0; pgps = pdata; diff --git a/drivers/misc/gps/rk29_gps.h b/drivers/misc/gps/rk29_gps.h index 75ce567a35b8..2599b7e4c4b2 100644 --- a/drivers/misc/gps/rk29_gps.h +++ b/drivers/misc/gps/rk29_gps.h @@ -11,7 +11,6 @@ struct rk29_gps_data { int (*reset)(int); int uart_id; int power_flag; - int suspend; struct semaphore power_sem; struct workqueue_struct *wq; struct work_struct work; From fce79ee94b499278e7269b81649be6dcde7c4d42 Mon Sep 17 00:00:00 2001 From: hhb Date: Wed, 20 Apr 2011 20:29:31 +0800 Subject: [PATCH 2/3] rk29phone:fix touch screen gt801's printing log when it sleeps out --- drivers/input/touchscreen/gt801_ts.c | 35 +++++++++++++++++++++------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/drivers/input/touchscreen/gt801_ts.c b/drivers/input/touchscreen/gt801_ts.c index c8bcbad77ef3..42265676bf5b 100755 --- a/drivers/input/touchscreen/gt801_ts.c +++ b/drivers/input/touchscreen/gt801_ts.c @@ -13,6 +13,7 @@ * GNU General Public License for more details. */ + #include #include #include @@ -210,7 +211,10 @@ static void gt801_ts_work_func(struct work_struct *work) x = ((( ((unsigned short)buf[i+ptxh] )<< 8) ) | buf[i+ptxl]); y = (((((unsigned short)buf[i+ptyh] )<< 8) )| buf[i+ptyl]); /* adjust the x and y to proper value added by hhb@rock-chips.com*/ - x = 480-x; + if(x < 480){ + x = 480-x; + } + if(y < 800){ y = 800-y; } @@ -260,11 +264,12 @@ static enum hrtimer_restart gt801_ts_timer_func(struct hrtimer *timer) static irqreturn_t gt801_ts_irq_handler(int irq, void *dev_id) { struct gt801_ts_data *ts = dev_id; - gt801printk("%s=%d,%d\n",__FUNCTION__,ts->client->irq,ts->use_irq); + gt801printk("%s=%d,%d\n",__FUNCTION__,ts->client->irq,ts->use_irq); - //if (ts->use_irq) + if(ts->use_irq){ disable_irq_nosync(ts->client->irq); - queue_work(gt801_wq, &ts->work); + } + queue_work(gt801_wq, &ts->work); return IRQ_HANDLED; } static int __devinit setup_resetPin(struct i2c_client *client, struct gt801_ts_data *ts) @@ -572,6 +577,17 @@ static int gt801_ts_suspend(struct i2c_client *client, pm_message_t mesg) return 0; } + +static void gt801_ts_resume_work_func(struct work_struct *work) +{ + struct gt801_ts_data *ts = container_of(work, struct gt801_ts_data, work); + msleep(50); //touch panel will generate an interrupt when it sleeps out,so as to avoid tihs by delaying 50ms + enable_irq(ts->client->irq); + PREPARE_WORK(&ts->work, gt801_ts_work_func); + printk("enabling gt801_ts IRQ %d\n", ts->client->irq); +} + + static int gt801_ts_resume(struct i2c_client *client) { struct gt801_ts_data *ts = i2c_get_clientdata(client); @@ -581,13 +597,16 @@ static int gt801_ts_resume(struct i2c_client *client) printk("gt801 TS Resume\n"); gpio_set_value(ts->gpio_reset, ts->gpio_reset_active_low? GPIO_HIGH:GPIO_LOW); - msleep(50); + if (ts->use_irq) { - printk("enabling IRQ %d\n", client->irq); - enable_irq(client->irq); + if(!work_pending(&ts->work)){ + PREPARE_WORK(&ts->work, gt801_ts_resume_work_func); + queue_work(gt801_wq, &ts->work); + } } - else + else { hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); + } return 0; } From c75ca5c6d481105b62013dc955a6ddbef6653844 Mon Sep 17 00:00:00 2001 From: lyx Date: Wed, 20 Apr 2011 22:16:13 -0700 Subject: [PATCH 3/3] modify gsensor and compass drivers --- arch/arm/mach-rk29/include/mach/custom_log.h | 85 ++++++++ drivers/input/gsensor/mma8452.c | 213 ++++++++++++++++--- drivers/input/magnetometer/ak8975.c | 33 ++- include/linux/mma8452.h | 27 +-- 4 files changed, 302 insertions(+), 56 deletions(-) create mode 100755 arch/arm/mach-rk29/include/mach/custom_log.h mode change 100644 => 100755 include/linux/mma8452.h diff --git a/arch/arm/mach-rk29/include/mach/custom_log.h b/arch/arm/mach-rk29/include/mach/custom_log.h new file mode 100755 index 000000000000..b4c85cda9dfd --- /dev/null +++ b/arch/arm/mach-rk29/include/mach/custom_log.h @@ -0,0 +1,85 @@ +/* -------------------------------------------------------------------------------------------------------- + * Copyright(C), 2010-2011, Fuzhou Rockchip Co., Ltd. All Rights Reserved. + * + * File: custom_log.h + * + * Desc: ChenZhen 偏好的 log 输出的定制实现. + * + * ----------------------------------------------------------------------------------- + * < 习语 和 缩略语 > : + * + * ----------------------------------------------------------------------------------- + * + * Usage: 调用本 log 机构的 .c 文件, 若要使能这里的 log 机制, + * 则必须在 inclue 本文件之前, "#define ENABLE_DEBUG_LOG" 先. + * Note: + * + * Author: ChenZhen + * + * -------------------------------------------------------------------------------------------------------- + * Version: + * v1.0 + * -------------------------------------------------------------------------------------------------------- + * Log: + ----Fri Nov 19 15:20:28 2010 v1.0 + * + * -------------------------------------------------------------------------------------------------------- + */ + + +#ifndef __CUSTOM_LOG_H__ +#define __CUSTOM_LOG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* --------------------------------------------------------------------------------------------------------- + * Include Files + * --------------------------------------------------------------------------------------------------------- + */ +#include + + +/* --------------------------------------------------------------------------------------------------------- + * Macros Definition + * --------------------------------------------------------------------------------------------------------- + */ + +#ifdef ENABLE_DEBUG_LOG +#define D(fmt, args...) \ + { printk("[File]:%s; [Line]:%d; [Func]:%s(); " fmt "\n", __FILE__, __LINE__, __FUNCTION__, ## args); } +#else +#define D(...) ((void)0) +#endif + +#define W(fmt, args...) \ + { printk("WARNING :: [File]:%s; [Line]:%d; [Func]:%s() :: " fmt "\n", __FILE__, __LINE__, __FUNCTION__, ## args); } + +#define E(fmt, args...) \ + { printk("ERROR :: [File]:%s; [Line]:%d; [Func]:%s() :: " fmt "\n", __FILE__, __LINE__, __FUNCTION__, ## args); } + + + +/* --------------------------------------------------------------------------------------------------------- + * Types and Structures Definition + * --------------------------------------------------------------------------------------------------------- */ + + +/* --------------------------------------------------------------------------------------------------------- + * Global Functions' Prototype + * --------------------------------------------------------------------------------------------------------- + */ + + +/* --------------------------------------------------------------------------------------------------------- + * Inline Functions Implementation + * --------------------------------------------------------------------------------------------------------- + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CUSTOM_LOG_H__ */ + diff --git a/drivers/input/gsensor/mma8452.c b/drivers/input/gsensor/mma8452.c index 2bfd288457d3..3db96749aab2 100755 --- a/drivers/input/gsensor/mma8452.c +++ b/drivers/input/gsensor/mma8452.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -32,11 +33,22 @@ #include #endif -#if 0 -#define mmaprintk(x...) printk(x) +// #define ENABLE_DEBUG_LOG +#include + +#if 1 +#define mmaprintk(x...) D(x) #else #define mmaprintk(x...) #endif + +// #define ENABLE_VERBOSE_LOG +#ifdef ENABLE_VERBOSE_LOG +#define V(x...) D(x) +#else +#define V(x...) +#endif + static int mma8452_probe(struct i2c_client *client, const struct i2c_device_id *id); #define MMA8452_SPEED 200 * 1000 @@ -53,13 +65,48 @@ static DECLARE_WAIT_QUEUE_HEAD(data_ready_wq); static struct early_suspend mma8452_early_suspend; #endif static int revision = -1; +static const char* vendor = "Freescale Semiconductor"; + + +typedef char status_t; +/*status*/ +#define MMA8452_OPEN 1 +#define MMA8452_CLOSE 0 + + +// .! : 设备实例数据类型. +struct mma8452_data { + status_t status; + char curr_tate; + struct input_dev *input_dev; + struct i2c_client *client; + struct work_struct work; + struct delayed_work delaywork; /*report second event*/ + + /** 缓存 sensor 数据. */ + struct mma8452_axis sense_data; + /** 对 "sense_data" 的互斥保护. */ + struct mutex sense_data_mutex; + + /** 标识 "sense_data" 中的数据是否有效. */ + atomic_t data_ready; + /** 用来等待 数据 ready 的等待队列头. */ + wait_queue_head_t data_ready_wq; + + /** 标识 设备被要求 START 采集数据的次数, 对应 MMA_IOCTL_START 可能被调用多次的情况. */ + int start_count; + /** 对 'start_count' 和相关操作的互斥保护. */ + struct mutex operation_mutex; +}; + /* AKM HW info */ static ssize_t gsensor_vendor_show(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t ret = 0; - sprintf(buf, "%#x\n", revision); + // sprintf(buf, "%#x\n", revision); + sprintf(buf, "%s.\n", vendor); ret = strlen(buf) + 1; return ret; @@ -82,7 +129,7 @@ static int gsensor_sysfs_init(void) goto err; } - ret = sysfs_create_file(android_gsensor_kobj, &dev_attr_vendor.attr); + ret = sysfs_create_file(android_gsensor_kobj, &dev_attr_vendor.attr); // "vendor" if (ret) { mmaprintk(KERN_ERR "MMA8452 gsensor_sysfs_init:"\ @@ -206,7 +253,7 @@ static int mma8452_start_dev(struct i2c_client *client, char rate) { int ret = 0; int tmp; - struct mma8452_data *mma8452 = (struct mma8452_data *)i2c_get_clientdata(client); + struct mma8452_data *mma8452 = (struct mma8452_data *)i2c_get_clientdata(client); // mma8452_data 定义在 mma8452.h 中. mmaprintk("-------------------------mma8452 start ------------------------\n"); /* standby */ @@ -309,11 +356,13 @@ static void mma8452_report_value(struct i2c_client *client, struct mma8452_axis input_report_abs(mma8452->input_dev, ABS_Y, axis->y); input_report_abs(mma8452->input_dev, ABS_Z, axis->z); input_sync(mma8452->input_dev); - mmaprintk("Gsensor x==%d y==%d z==%d\n",axis->x,axis->y,axis->z); + V("Gsensor x==%d y==%d z==%d\n",axis->x,axis->y,axis->z); } +/** 在 底半部执行, 具体获取 g sensor 数据. */ static int mma8452_get_data(struct i2c_client *client) { + struct mma8452_data* mma8452 = i2c_get_clientdata(client); char buffer[6]; int ret; struct mma8452_axis axis; @@ -328,7 +377,7 @@ static int mma8452_get_data(struct i2c_client *client) return ret; } while (0); - mmaprintk("0x%02x 0x%02x 0x%02x \n",buffer[0],buffer[1],buffer[2]); + V("0x%02x 0x%02x 0x%02x \n",buffer[0],buffer[1],buffer[2]); axis.x = mma8452_convert_to_int(buffer[0]); axis.y = mma8452_convert_to_int(buffer[1]); @@ -340,14 +389,24 @@ static int mma8452_get_data(struct i2c_client *client) swap(axis.x,axis.y); } - // mmaprintk( "%s: ------------------mma8452_GetData axis = %d %d %d--------------\n", - // __func__, axis.x, axis.y, axis.z); + V( "%s: ------------------mma8452_GetData axis = %d %d %d--------------\n", + __func__, axis.x, axis.y, axis.z); //memcpy(sense_data, &axis, sizeof(axis)); mma8452_report_value(client, &axis); //atomic_set(&data_ready, 0); //wake_up(&data_ready_wq); + /* 互斥地缓存数据. */ + mutex_lock(&(mma8452->sense_data_mutex) ); + mma8452->sense_data = axis; + mutex_unlock(&(mma8452->sense_data_mutex) ); + + /* 置位 data_ready */ + atomic_set(&(mma8452->data_ready), 1); + /* 唤醒 data_ready 等待队列头. */ + wake_up(&(mma8452->data_ready_wq) ); + return 0; } @@ -366,6 +425,37 @@ static int mma8452_trans_buff(char *rbuf, int size) } */ +/** + * 获取当前已经 cache 了的 sensor 数据. + * @param sense_data + * 指向返回用 buffer. + * @param client + * 当前 i2c client 设备实例数据的指针. + * @return + * 若成功, 返回 0; 否则, 返回其它. + */ +static int mma8452_get_cached_data(struct i2c_client* client, struct mma8452_axis* sense_data) +{ + struct mma8452_data* this = (struct mma8452_data *)i2c_get_clientdata(client); + + /* 有超时地, 等待数据 ready. */ + wait_event_interruptible_timeout(this->data_ready_wq, + atomic_read(&(this->data_ready) ), + msecs_to_jiffies(1000) ); + /* 若超时, 且数据没有 ready. */ + if ( 0 == atomic_read(&(this->data_ready) ) ) { + E("waiting 'data_ready_wq' timed out."); + /* 返回 error. */ + return -1; + } + /* 数据已经 ready, 互斥地返回数据. */ + mutex_lock(&(this->sense_data_mutex) ); + *sense_data = this->sense_data; + mutex_unlock(&(this->sense_data_mutex) ); + /* 返回. */ + return 0; +} + static int mma8452_open(struct inode *inode, struct file *file) { return 0;//nonseekable_open(inode, file); @@ -381,13 +471,15 @@ static int mma8452_ioctl(struct inode *inode, struct file *file, unsigned int cm { void __user *argp = (void __user *)arg; - char msg[RBUFF_SIZE + 1]; + // char msg[RBUFF_SIZE + 1]; + struct mma8452_axis sense_data = {0}; int ret = -1; char rate; struct i2c_client *client = container_of(mma8452_device.parent, struct i2c_client, dev); + struct mma8452_data* this = (struct mma8452_data *)i2c_get_clientdata(client); /* 设备数据实例的指针. */ switch (cmd) { - case ECS_IOCTL_APP_SET_RATE: + case MMA_IOCTL_APP_SET_RATE: if (copy_from_user(&rate, argp, sizeof(rate))) return -EFAULT; break; @@ -396,36 +488,73 @@ static int mma8452_ioctl(struct inode *inode, struct file *file, unsigned int cm } switch (cmd) { - case ECS_IOCTL_START: - ret = mma8452_start(client, MMA8452_RATE_12P5); - if (ret < 0) - return ret; - break; - case ECS_IOCTL_CLOSE: - ret = mma8452_close(client); - if (ret < 0) - return ret; - break; - case ECS_IOCTL_APP_SET_RATE: + case MMA_IOCTL_START: + /* 上锁. */ + mutex_lock(&(this->operation_mutex) ); + D("to perform 'MMA_IOCTL_START', former 'start_count' is %d.", this->start_count); + /* 记数 自加. */ + (this->start_count)++; + /* 若是初次 start, 则... */ + if ( 1 == this->start_count ) { + /* 复位 data_ready. */ + atomic_set(&(this->data_ready), 0); + /* 执行具体的对硬件的启动操作. */ + if ( (ret = mma8452_start(client, MMA8452_RATE_12P5) ) < 0 ) { + mutex_unlock(&(this->operation_mutex) ); + return ret; + } + } + /* 解锁. */ + mutex_unlock(&(this->operation_mutex) ); + D("finish 'MMA_IOCTL_START', ret = %d.", ret); + /* 返回. */ + return 0; + + case MMA_IOCTL_CLOSE: + /* 上锁. */ + mutex_lock(&(this->operation_mutex) ); + D("to perform 'MMA_IOCTL_CLOSE', former 'start_count' is %d, PID : %d", this->start_count, get_current()->pid); + /* 若记数自减到 0, 则... */ + if ( 0 == (--(this->start_count) ) ) { + /* 复位 data_ready. */ + atomic_set(&(this->data_ready), 0); + /* 执行具体的对硬件的 stop 操作. */ + if ( (ret = mma8452_close(client) ) < 0 ) { + mutex_unlock(&(this->operation_mutex) ); + return ret; + } + } + /* 解锁. */ + mutex_unlock(&(this->operation_mutex) ); + /* 返回. */ + return 0; + + case MMA_IOCTL_APP_SET_RATE: ret = mma8452_reset_rate(client, rate); if (ret < 0) return ret; break; - /* - case ECS_IOCTL_GETDATA: - ret = mma8452_trans_buff(msg, RBUFF_SIZE); - if (ret < 0) + case MMA_IOCTL_GETDATA: + // ret = mma8452_trans_buff(msg, RBUFF_SIZE); + if ( (ret = mma8452_get_cached_data(client, &sense_data) ) < 0 ) { + E("failed to get cached sense data, ret = %d.", ret); return ret; + } break; - */ default: return -ENOTTY; } switch (cmd) { - case ECS_IOCTL_GETDATA: + case MMA_IOCTL_GETDATA: + /* if (copy_to_user(argp, &msg, sizeof(msg))) return -EFAULT; + */ + if ( copy_to_user(argp, &sense_data, sizeof(sense_data) ) ) { + D("failed to copy sense data to user space."); + return -EFAULT; + } break; default: break; @@ -452,8 +581,8 @@ static void mma8452_delaywork_func(struct work_struct *work) struct i2c_client *client = mma8452->client; if (mma8452_get_data(client) < 0) - mmaprintk(KERN_ERR "MMA8452 mma_work_func: Get data failed\n"); - mmaprintk("%s :int src:0x%02x\n",__FUNCTION__,mma845x_read_reg(mma8452->client,MMA8452_REG_INTSRC)); + E(KERN_ERR "MMA8452 mma_work_func: Get data failed\n"); + V("%s :int src:0x%02x\n",__FUNCTION__,mma845x_read_reg(mma8452->client,MMA8452_REG_INTSRC)); enable_irq(client->irq); } @@ -462,8 +591,9 @@ static irqreturn_t mma8452_interrupt(int irq, void *dev_id) struct mma8452_data *mma8452 = (struct mma8452_data *)dev_id; disable_irq_nosync(irq); + /* .! : 延迟地在 底半部 发起后续操作(读取具体数据). */ schedule_delayed_work(&mma8452->delaywork, msecs_to_jiffies(30)); - mmaprintk("%s :enter\n",__FUNCTION__); + V("%s :enter\n",__FUNCTION__); return IRQ_HANDLED; } @@ -474,6 +604,7 @@ static struct file_operations mma8452_fops = { .ioctl = mma8452_ioctl, }; +/** 控制设备. */ static struct miscdevice mma8452_device = { .minor = MISC_DYNAMIC_MINOR, .name = "mma8452_daemon",//"mma8452_daemon", @@ -548,12 +679,16 @@ static const struct i2c_device_id mma8452_id[] = { { } }; +/** 表征驱动的数据类型定义. */ static struct i2c_driver mma8452_driver = { .driver = { .name = "gs_mma8452", }, .id_table = mma8452_id, - .probe = mma8452_probe, + .probe = mma8452_probe, // .!! : 对 probe() 的调用, 仍是由 注册设备的操作触发的, + // 具体参见 board-rk29sdk.c 中的 board_i2c0_devices. + // 在 board_i2c0_devices 中声明了一个可以使用名称是 "gs_mma8452" 驱动程序的 I2C 设备. + // 同时也体现了 I2C 地址 和 终端号等信息. .remove = __devexit_p(mma8452_remove), #ifndef CONFIG_HAS_EARLYSUSPEND .suspend = &mma8452_suspend, @@ -687,8 +822,18 @@ static int mma8452_probe(struct i2c_client *client, const struct i2c_device_id register_early_suspend(&mma8452_early_suspend); #endif - mma8452->status = -1; printk(KERN_INFO "mma8452 probe ok\n"); + memset(&(mma8452->sense_data), 0, sizeof(struct mma8452_axis) ); + mutex_init(&(mma8452->sense_data_mutex) ); + + atomic_set(&(mma8452->data_ready), 0); + init_waitqueue_head(&(mma8452->data_ready_wq) ); + + mma8452->start_count = 0; + mutex_init(&(mma8452->operation_mutex) ); + + // mma8452->status = -1; + mma8452->status = MMA8452_CLOSE; #if 0 // mma8452_start_test(this_client); mma8452_start(client, MMA8452_RATE_12P5); @@ -711,7 +856,7 @@ static int mma8452_probe(struct i2c_client *client, const struct i2c_device_id exit_alloc_data_failed: ; mmaprintk("%s error\n",__FUNCTION__); - return err; + return -1; } diff --git a/drivers/input/magnetometer/ak8975.c b/drivers/input/magnetometer/ak8975.c index 78210a1d9e11..92970094de22 100755 --- a/drivers/input/magnetometer/ak8975.c +++ b/drivers/input/magnetometer/ak8975.c @@ -34,7 +34,7 @@ #include "ak8975.h" #define AKM8975_DEBUG 1 -#define AKM8975_DEBUG_MSG 1 +#define AKM8975_DEBUG_MSG 0 #define AKM8975_DEBUG_FUNC 0 #define AKM8975_DEBUG_DATA 0 #define MAX_FAILURE_COUNT 3 @@ -179,6 +179,8 @@ static int AKECS_SetMode_SngMeasure(void) { char buffer[2]; + AKMDBG("enter %s\n", __func__); + atomic_set(&data_ready, 0); /* Set measure mode */ @@ -192,6 +194,7 @@ static int AKECS_SetMode_SngMeasure(void) static int AKECS_SetMode_SelfTest(void) { char buffer[2]; + AKMDBG("enter %s\n", __func__); /* Set measure mode */ buffer[0] = AK8975_REG_CNTL; @@ -203,6 +206,7 @@ static int AKECS_SetMode_SelfTest(void) static int AKECS_SetMode_FUSEAccess(void) { char buffer[2]; + AKMDBG("enter %s\n", __func__); /* Set measure mode */ buffer[0] = AK8975_REG_CNTL; @@ -214,6 +218,7 @@ static int AKECS_SetMode_FUSEAccess(void) static int AKECS_SetMode_PowerDown(void) { char buffer[2]; + AKMDBG("enter %s\n", __func__); /* Set powerdown mode */ buffer[0] = AK8975_REG_CNTL; @@ -225,6 +230,7 @@ static int AKECS_SetMode_PowerDown(void) static int AKECS_SetMode(char mode) { int ret; + AKMDBG("enter %s\n", __func__); switch (mode) { case AK8975_MODE_SNG_MEASURE: @@ -253,6 +259,7 @@ static int AKECS_CheckDevice(void) { char buffer[2]; int ret; + AKMDBG("enter %s\n", __func__); /* Set measure mode */ buffer[0] = AK8975_REG_WIA; @@ -279,6 +286,7 @@ static int AKECS_GetData(char *rbuf, int size) return -EINVAL; } #endif + AKMDBG("enter %s\n", __func__); wait_event_interruptible_timeout(data_ready_wq, atomic_read(&data_ready), 1000); if (!atomic_read(&data_ready)) { @@ -321,6 +329,7 @@ static void AKECS_SetYPR(short *rbuf) printk(KERN_INFO " Geomagnetism[LSB]: %6d,%6d,%6d\n", rbuf[9], rbuf[10], rbuf[11]); #endif + AKMDBG("enter %s\n", __func__); /* Report magnetic sensor information */ if (atomic_read(&m_flag)) { input_report_abs(data->input_dev, ABS_RX, rbuf[0]); @@ -349,18 +358,21 @@ static void AKECS_SetYPR(short *rbuf) static int AKECS_GetOpenStatus(void) { + AKMDBG("enter %s\n", __func__); wait_event_interruptible(open_wq, (atomic_read(&open_flag) != 0)); return atomic_read(&open_flag); } static int AKECS_GetCloseStatus(void) { + AKMDBG("enter %s\n", __func__); wait_event_interruptible(open_wq, (atomic_read(&open_flag) <= 0)); return atomic_read(&open_flag); } static void AKECS_CloseDone(void) { + AKMDBG("enter %s\n", __func__); atomic_set(&m_flag, 1); atomic_set(&a_flag, 1); atomic_set(&mv_flag, 1); @@ -398,6 +410,7 @@ akm_aot_ioctl(struct inode *inode, struct file *file, { void __user *argp = (void __user *)arg; short flag; + AKMDBG("enter %s\n", __func__); switch (cmd) { case ECS_IOCTL_APP_SET_MFLAG: @@ -487,6 +500,7 @@ akmd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; + AKMDBG("enter %s\n", __func__); /* NOTE: In this function the size of "char" should be 1-byte. */ char sData[SENSOR_DATA_SIZE];/* for GETDATA */ @@ -629,6 +643,7 @@ static void akm8975_work_func(struct work_struct *work) { char buffer[SENSOR_DATA_SIZE]; int ret; + AKMDBG("enter %s\n", __func__); memset(buffer, 0, SENSOR_DATA_SIZE); buffer[0] = AK8975_REG_ST1; @@ -658,8 +673,9 @@ static irqreturn_t akm8975_interrupt(int irq, void *dev_id) { struct akm8975_data *data = dev_id; AKMFUNC("akm8975_interrupt"); - disable_irq(this_client->irq); + disable_irq_nosync(this_client->irq); schedule_work(&data->work); + AKMDBG("exit %s\n", __func__); return IRQ_HANDLED; } @@ -751,13 +767,22 @@ int akm8975_probe(struct i2c_client *client, const struct i2c_device_id *id) dev_dbg(&akm->client->dev, "no IRQ?\n"); return -ENODEV; }else{ + AKMDBG("gpio %d to irq %d\n", akm->eoc_irq, gpio_to_irq(akm->eoc_irq)); akm->eoc_irq = gpio_to_irq(akm->eoc_irq); } err = gpio_request(client->irq, "ak_8975"); if (err < 0) { dev_err(&client->dev, "failed to request GPIO, error %d\n", err); goto exit3; - } + } + + err = gpio_direction_input(client->irq); + if (err) { + dev_err(&client->dev, "failed to set GPIO direction, error %d\n", err); + goto exit3; + } + gpio_pull_updown(client->irq, GPIOPullDown); + /* IRQ */ err = request_irq(akm->eoc_irq, akm8975_interrupt, IRQ_TYPE_EDGE_RISING, "akm8975_DRDY", akm); @@ -766,6 +791,8 @@ int akm8975_probe(struct i2c_client *client, const struct i2c_device_id *id) goto exit4; } + client->irq = akm->eoc_irq; + /* Declare input device */ akm->input_dev = input_allocate_device(); if (!akm->input_dev) { diff --git a/include/linux/mma8452.h b/include/linux/mma8452.h old mode 100644 new mode 100755 index e2061f0988dc..02b7b27f91d0 --- a/include/linux/mma8452.h +++ b/include/linux/mma8452.h @@ -54,17 +54,18 @@ #define MMA8452_REG_OFF_Y 0x30 //RW #define MMA8452_REG_OFF_Z 0x31 //RW -#define MMAIO 0xA1 +//#define MMAIO 0xA1 +#define MMAIO 'm' /* IOCTLs for MMA8452 library */ -#define ECS_IOCTL_INIT _IO(MMAIO, 0x01) -#define ECS_IOCTL_RESET _IO(MMAIO, 0x04) -#define ECS_IOCTL_CLOSE _IO(MMAIO, 0x02) -#define ECS_IOCTL_START _IO(MMAIO, 0x03) -#define ECS_IOCTL_GETDATA _IOR(MMAIO, 0x08, char[RBUFF_SIZE+1]) +#define MMA_IOCTL_INIT _IO(MMAIO, 0x01) +#define MMA_IOCTL_RESET _IO(MMAIO, 0x04) +#define MMA_IOCTL_CLOSE _IO(MMAIO, 0x02) +#define MMA_IOCTL_START _IO(MMAIO, 0x03) +#define MMA_IOCTL_GETDATA _IOR(MMAIO, 0x08, char[RBUFF_SIZE+1]) /* IOCTLs for APPs */ -#define ECS_IOCTL_APP_SET_RATE _IOW(MMAIO, 0x10, char) +#define MMA_IOCTL_APP_SET_RATE _IOW(MMAIO, 0x10, char) /*rate*/ @@ -89,8 +90,6 @@ #define FREAD_MASK 2 - - /*status*/ #define MMA8452_SUSPEND 2 #define MMA8452_OPEN 1 @@ -115,15 +114,6 @@ struct mma8452_platform_data { */ -struct mma8452_data { - char status; - char curr_tate; - struct input_dev *input_dev; - struct i2c_client *client; - struct work_struct work; - struct delayed_work delaywork; /*report second event*/ -}; - struct mma8452_axis { int x; int y; @@ -132,6 +122,5 @@ struct mma8452_axis { #define GSENSOR_DEV_PATH "/dev/mma8452_daemon" - #endif