From: root Date: Fri, 17 Dec 2010 08:23:55 +0000 (+0800) Subject: [xjh] gsensor with debug open X-Git-Tag: firefly_0821_release~10927 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=9d886535b3208a336722303a0839dff1c369bdee;p=firefly-linux-kernel-4.4.55.git [xjh] gsensor with debug open --- diff --git a/arch/arm/mach-rk29/board-rk29sdk.c b/arch/arm/mach-rk29/board-rk29sdk.c index d26ee77df61e..0b29186672f9 100755 --- a/arch/arm/mach-rk29/board-rk29sdk.c +++ b/arch/arm/mach-rk29/board-rk29sdk.c @@ -338,6 +338,32 @@ struct p1003_platform_data p1003_info = { }; #endif +/*MMA8452 gsensor*/ +#if defined (CONFIG_GS_MMA8452) +#define MMA8452_INT_PIN RK29_PIN0_PA3 + +int mma8452_init_platform_hw(void) +{ + + if(gpio_request(MMA8452_INT_PIN,NULL) != 0){ + gpio_free(MMA8452_INT_PIN); + printk("mma8452_init_platform_hw gpio_request error\n"); + return -EIO; + } + gpio_pull_updown(MMA8452_INT_PIN, 1); + return 0; +} + + +struct mma8452_platform_data mma8452_info = { + .model= 8452, + .swap_xy = 0, + .init_platform_hw= mma8452_init_platform_hw, + +}; +#endif + + /***************************************************************************************** * i2c devices @@ -451,6 +477,16 @@ static struct i2c_board_info __initdata board_i2c0_devices[] = { ///.irq = RK2818_PIN_PA4, }, #endif +#if defined (CONFIG_GS_MMA8452) + { + .type = "gs_mma8452", + .addr = 0x1c, + .flags = 0, + .irq = MMA8452_INT_PIN, + .platform_data = &mma8452_info, + }, +#endif + }; #endif diff --git a/arch/arm/mach-rk29/include/mach/board.h b/arch/arm/mach-rk29/include/mach/board.h index e5a14b4a3fba..93fceaf0169e 100755 --- a/arch/arm/mach-rk29/include/mach/board.h +++ b/arch/arm/mach-rk29/include/mach/board.h @@ -131,6 +131,16 @@ struct p1003_platform_data { void (*exit_platform_hw)(void); }; +struct mma8452_platform_data { + u16 model; + u16 swap_xy; + int (*get_pendown_state)(void); + int (*init_platform_hw)(void); + int (*mma8452_platform_sleep)(void); + int (*mma8452_platform_wakeup)(void); + void (*exit_platform_hw)(void); +}; + void __init rk29_map_common_io(void); void __init rk29_clock_init(void); diff --git a/drivers/input/gsensor/Kconfig b/drivers/input/gsensor/Kconfig index 748d69c17b54..8297f901039f 100644 --- a/drivers/input/gsensor/Kconfig +++ b/drivers/input/gsensor/Kconfig @@ -19,4 +19,13 @@ config GS_MMA7660 To have support for your specific gsesnor you will have to select the proper drivers which depend on this option. +config GS_MMA8452 + bool "gs_mma8452" + depends on G_SENSOR_DEVICE + default y + help + To have support for your specific gsesnor you will have to + select the proper drivers which depend on this option. + + endif diff --git a/drivers/input/gsensor/Makefile b/drivers/input/gsensor/Makefile index bd0a069ceeb7..c537a7d9ca5c 100644 --- a/drivers/input/gsensor/Makefile +++ b/drivers/input/gsensor/Makefile @@ -1,3 +1,4 @@ # gsensor drivers obj-$(CONFIG_GS_MMA7660) += mma7660.o +obj-$(CONFIG_GS_MMA8452) += mma8452.o diff --git a/drivers/input/gsensor/mma8452.c b/drivers/input/gsensor/mma8452.c new file mode 100644 index 000000000000..e10e4c329fbe --- /dev/null +++ b/drivers/input/gsensor/mma8452.c @@ -0,0 +1,696 @@ +/* drivers/i2c/chips/mma8452.c - mma8452 compass driver + * + * Copyright (C) 2007-2008 HTC Corporation. + * Author: Hou-Kun Chen + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_ANDROID_POWER +#include +#endif + +#if 1 +#define mmaprintk(x...) printk(x) +#else +#define mmaprintk(x...) +#endif +static int mma8452_probe(struct i2c_client *client, const struct i2c_device_id *id); + +#define MMA8452_SPEED 200 * 1000 + +/* Addresses to scan -- protected by sense_data_mutex */ +//static char sense_data[RBUFF_SIZE + 1]; +static struct i2c_client *this_client; +static struct miscdevice mma8452_device; + +static DECLARE_WAIT_QUEUE_HEAD(data_ready_wq); + +#ifdef CONFIG_ANDROID_POWER +static android_early_suspend_t mma8452_early_suspend; +#endif +static int revision = -1; +/* 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); + ret = strlen(buf) + 1; + + return ret; +} + +static DEVICE_ATTR(vendor, 0444, gsensor_vendor_show, NULL); + +static struct kobject *android_gsensor_kobj; + +static int gsensor_sysfs_init(void) +{ + int ret ; + + android_gsensor_kobj = kobject_create_and_add("android_gsensor", NULL); + if (android_gsensor_kobj == NULL) { + mmaprintk(KERN_ERR + "MMA8452 gsensor_sysfs_init:"\ + "subsystem_register failed\n"); + ret = -ENOMEM; + goto err; + } + + ret = sysfs_create_file(android_gsensor_kobj, &dev_attr_vendor.attr); + if (ret) { + mmaprintk(KERN_ERR + "MMA8452 gsensor_sysfs_init:"\ + "sysfs_create_group failed\n"); + goto err4; + } + + return 0 ; +err4: + kobject_del(android_gsensor_kobj); +err: + return ret ; +} + +static int mma8452_rx_data(struct i2c_client *client, char *rxData, int length) +{ + int ret = 0; + char reg = rxData[0]; + ret = i2c_master_reg8_recv(client, reg, rxData, length, MMA8452_SPEED); + return (ret > 0)? 0 : ret; +} + +static int mma8452_tx_data(struct i2c_client *client, char *txData, int length) +{ + int ret = 0; + char reg = txData[0]; + ret = i2c_master_reg8_send(client, reg, &txData[1], length-1, MMA8452_SPEED); + return (ret > 0)? 0 : ret; +} + +static char mma845x_read_reg(struct i2c_client *client,int addr) +{ + char tmp; + int ret = 0; + + tmp = addr; + ret = mma8452_tx_data(client, &tmp, 1); + ret = mma8452_rx_data(client, &tmp, 1); + return tmp; +} + +static int mma845x_write_reg(struct i2c_client *client,int addr,int value) +{ + char buffer[3]; + int ret = 0; + + buffer[0] = addr; + buffer[1] = value; + ret = mma8452_tx_data(client, &buffer[0], 2); + return ret; +} + + +static char mma8452_get_devid(struct i2c_client *client) +{ + mmaprintk("mma8452 devid:%x\n",mma845x_read_reg(client,MMA8452_REG_WHO_AM_I)); + return mma845x_read_reg(client,MMA8452_REG_WHO_AM_I); +} + +static int mma845x_active(struct i2c_client *client,int enable) +{ + int tmp; + int ret = 0; + + tmp = mma845x_read_reg(client,MMA8452_REG_CTRL_REG1); + if(enable) + tmp |=ACTIVE_MASK; + else + tmp &=~ACTIVE_MASK; + mmaprintk("mma845x_active %s (0x%x)\n",enable?"active":"standby",tmp); + ret = mma845x_write_reg(client,MMA8452_REG_CTRL_REG1,tmp); + return ret; +} + +static int mma8452_start_test(struct i2c_client *client) +{ + int ret = 0; + int tmp; + + mmaprintk("-------------------------mma8452 start test------------------------\n"); + + /* standby */ + mma845x_active(client,0); + mmaprintk("mma8452 MMA8452_REG_SYSMOD:%x\n",mma845x_read_reg(client,MMA8452_REG_SYSMOD)); + + /* disable FIFO FMODE = 0*/ + ret = mma845x_write_reg(client,MMA8452_REG_F_SETUP,0); + mmaprintk("mma8452 MMA8452_REG_F_SETUP:%x\n",mma845x_read_reg(client,MMA8452_REG_F_SETUP)); + + /* set full scale range to 2g */ + ret = mma845x_write_reg(client,MMA8452_REG_XYZ_DATA_CFG,0); + mmaprintk("mma8452 MMA8452_REG_XYZ_DATA_CFG:%x\n",mma845x_read_reg(client,MMA8452_REG_XYZ_DATA_CFG)); + + /* set bus 8bit/14bit(FREAD = 1,FMODE = 0) ,data rate*/ + tmp = (MMA8452_RATE_12P5<< MMA8452_RATE_SHIFT) | FREAD_MASK; + ret = mma845x_write_reg(client,MMA8452_REG_CTRL_REG1,tmp); + mmaprintk("mma8452 MMA8452_REG_CTRL_REG1:%x\n",mma845x_read_reg(client,MMA8452_REG_CTRL_REG1)); + + mmaprintk("mma8452 MMA8452_REG_SYSMOD:%x\n",mma845x_read_reg(client,MMA8452_REG_SYSMOD)); + + ret = mma845x_write_reg(client,MMA8452_REG_CTRL_REG3,5); + mmaprintk("mma8452 MMA8452_REG_CTRL_REG3:%x\n",mma845x_read_reg(client,MMA8452_REG_CTRL_REG3)); + + ret = mma845x_write_reg(client,MMA8452_REG_CTRL_REG4,1); + mmaprintk("mma8452 MMA8452_REG_CTRL_REG4:%x\n",mma845x_read_reg(client,MMA8452_REG_CTRL_REG4)); + + ret = mma845x_write_reg(client,MMA8452_REG_CTRL_REG5,1); + mmaprintk("mma8452 MMA8452_REG_CTRL_REG5:%x\n",mma845x_read_reg(client,MMA8452_REG_CTRL_REG5)); + + mmaprintk("mma8452 MMA8452_REG_SYSMOD:%x\n",mma845x_read_reg(client,MMA8452_REG_SYSMOD)); + mma845x_active(client,1); + mmaprintk("mma8452 MMA8452_REG_SYSMOD:%x\n",mma845x_read_reg(client,MMA8452_REG_SYSMOD)); + + enable_irq(client->irq); + msleep(50); + + return ret; +} + +static int mma8452_start_dev(struct i2c_client *client, char rate) +{ + int ret = 0; + int tmp; + + mmaprintk("-------------------------mma8452 start ------------------------\n"); + /* standby */ + mma845x_active(client,0); + mmaprintk("mma8452 MMA8452_REG_SYSMOD:%x\n",mma845x_read_reg(client,MMA8452_REG_SYSMOD)); + + /* disable FIFO FMODE = 0*/ + ret = mma845x_write_reg(client,MMA8452_REG_F_SETUP,0); + mmaprintk("mma8452 MMA8452_REG_F_SETUP:%x\n",mma845x_read_reg(client,MMA8452_REG_F_SETUP)); + + /* set full scale range to 2g */ + ret = mma845x_write_reg(client,MMA8452_REG_XYZ_DATA_CFG,0); + mmaprintk("mma8452 MMA8452_REG_XYZ_DATA_CFG:%x\n",mma845x_read_reg(client,MMA8452_REG_XYZ_DATA_CFG)); + + /* set bus 8bit/14bit(FREAD = 1,FMODE = 0) ,data rate*/ + tmp = (rate<< MMA8452_RATE_SHIFT) | FREAD_MASK; + ret = mma845x_write_reg(client,MMA8452_REG_CTRL_REG1,tmp); + mmaprintk("mma8452 MMA8452_REG_CTRL_REG1:%x\n",mma845x_read_reg(client,MMA8452_REG_CTRL_REG1)); + + mmaprintk("mma8452 MMA8452_REG_SYSMOD:%x\n",mma845x_read_reg(client,MMA8452_REG_SYSMOD)); + + ret = mma845x_write_reg(client,MMA8452_REG_CTRL_REG3,5); + mmaprintk("mma8452 MMA8452_REG_CTRL_REG3:%x\n",mma845x_read_reg(client,MMA8452_REG_CTRL_REG3)); + + ret = mma845x_write_reg(client,MMA8452_REG_CTRL_REG4,1); + mmaprintk("mma8452 MMA8452_REG_CTRL_REG4:%x\n",mma845x_read_reg(client,MMA8452_REG_CTRL_REG4)); + + ret = mma845x_write_reg(client,MMA8452_REG_CTRL_REG5,1); + mmaprintk("mma8452 MMA8452_REG_CTRL_REG5:%x\n",mma845x_read_reg(client,MMA8452_REG_CTRL_REG5)); + + mmaprintk("mma8452 MMA8452_REG_SYSMOD:%x\n",mma845x_read_reg(client,MMA8452_REG_SYSMOD)); + mma845x_active(client,1); + mmaprintk("mma8452 MMA8452_REG_SYSMOD:%x\n",mma845x_read_reg(client,MMA8452_REG_SYSMOD)); + + enable_irq(client->irq); + return ret; + +} + +static int mma8452_start(struct i2c_client *client, char rate) +{ + struct mma8452_data *mma8452 = (struct mma8452_data *)i2c_get_clientdata(client); + + if (mma8452->status == MMA8452_OPEN) { + return 0; + } + mma8452->status = MMA8452_OPEN; + return mma8452_start_dev(client, rate); +} + +static int mma8452_close_dev(struct i2c_client *client) +{ + disable_irq_nosync(client->irq); + return mma845x_active(client,0); +} + +static int mma8452_close(struct i2c_client *client) +{ + struct mma8452_data *mma8452 = (struct mma8452_data *)i2c_get_clientdata(client); + + mma8452->status = MMA8452_CLOSE; + + return mma8452_close_dev(client); +} + +static int mma8452_reset_rate(struct i2c_client *client, char rate) +{ + int ret = 0; + + mmaprintk("\n----------------------------mma8452_reset_rate------------------------\n"); + + ret = mma8452_close_dev(client); + ret = mma8452_start_dev(client, rate); + + return ret ; +} + +static inline int mma8452_convert_to_int(char value) +{ + int result; + + if (value < MMA8452_BOUNDARY) { + result = value * MMA8452_GRAVITY_STEP; + } else { + result = ~(((~value & 0x7f) + 1)* MMA8452_GRAVITY_STEP) + 1; + } + + return result; +} + +static void mma8452_report_value(struct i2c_client *client, struct mma8452_axis *axis) +{ + struct mma8452_data *mma8452 = i2c_get_clientdata(client); + //struct mma8452_axis *axis = (struct mma8452_axis *)rbuf; + + /* Report acceleration sensor information */ + input_report_abs(mma8452->input_dev, ABS_X, axis->x); + 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); +} + +static int mma8452_get_data(struct i2c_client *client) +{ + char buffer[6]; + int ret; + struct mma8452_axis axis; + struct mma8452_platform_data *pdata = pdata = client->dev.platform_data; + + do { + memset(buffer, 0, 3); + buffer[0] = MMA8452_REG_X_OUT_MSB; + ret = mma8452_tx_data(client, &buffer[0], 1); + ret = mma8452_rx_data(client, &buffer[0], 3); + if (ret < 0) + return ret; + } while (0); + + mmaprintk("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]); + axis.z = mma8452_convert_to_int(buffer[2]); + + if(pdata->swap_xy) + { + axis.y = -axis.y; + swap(axis.x,axis.y); + } + + // mmaprintk( "%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); + + return 0; +} + +/* +static int mma8452_trans_buff(char *rbuf, int size) +{ + //wait_event_interruptible_timeout(data_ready_wq, + // atomic_read(&data_ready), 1000); + wait_event_interruptible(data_ready_wq, + atomic_read(&data_ready)); + + atomic_set(&data_ready, 0); + memcpy(rbuf, &sense_data[0], size); + + return 0; +} +*/ + +static int mma8452_open(struct inode *inode, struct file *file) +{ + return 0;//nonseekable_open(inode, file); +} + +static int mma8452_release(struct inode *inode, struct file *file) +{ + return 0; +} + +static int mma8452_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + + void __user *argp = (void __user *)arg; + char msg[RBUFF_SIZE + 1]; + int ret = -1; + char rate; + struct i2c_client *client = container_of(mma8452_device.parent, struct i2c_client, dev); + + switch (cmd) { + case ECS_IOCTL_APP_SET_RATE: + if (copy_from_user(&rate, argp, sizeof(rate))) + return -EFAULT; + break; + default: + break; + } + + 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: + 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) + return ret; + break; + */ + default: + return -ENOTTY; + } + + switch (cmd) { + case ECS_IOCTL_GETDATA: + if (copy_to_user(argp, &msg, sizeof(msg))) + return -EFAULT; + break; + default: + break; + } + + return 0; +} + +static void mma8452_work_func(struct work_struct *work) +{ + struct mma8452_data *mma8452 = container_of(work, struct mma8452_data, work); + struct i2c_client *client = mma8452->client; + + if (mma8452_get_data(client) < 0) + mmaprintk(KERN_ERR "MMA8452 mma_work_func: Get data failed\n"); + + enable_irq(client->irq); +} + +static void mma8452_delaywork_func(struct work_struct *work) +{ + struct delayed_work *delaywork = container_of(work, struct delayed_work, work); + struct mma8452_data *mma8452 = container_of(delaywork, struct mma8452_data, delaywork); + 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)); + enable_irq(client->irq); +} + +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__); + return IRQ_HANDLED; +} + +static struct file_operations mma8452_fops = { + .owner = THIS_MODULE, + .open = mma8452_open, + .release = mma8452_release, + .ioctl = mma8452_ioctl, +}; + +static struct miscdevice mma8452_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = "mma8452_daemon",//"mma8452_daemon", + .fops = &mma8452_fops, +}; + +static int mma8452_remove(struct i2c_client *client) +{ + struct mma8452_data *mma8452 = i2c_get_clientdata(client); + + misc_deregister(&mma8452_device); + input_unregister_device(mma8452->input_dev); + input_free_device(mma8452->input_dev); + free_irq(client->irq, mma8452); + kfree(mma8452); +#ifdef CONFIG_ANDROID_POWER + android_unregister_early_suspend(&mma8452_early_suspend); +#endif + this_client = NULL; + return 0; +} + +#ifdef CONFIG_ANDROID_POWER +static int mma8452_suspend(android_early_suspend_t *h) +{ + struct i2c_client *client = container_of(mma8452_device.parent, struct i2c_client, dev); + mmaprintk("Gsensor mma7760 enter suspend\n"); + return mma8452_close_dev(client); +} + +static int mma8452_resume(android_early_suspend_t *h) +{ + struct i2c_client *client = container_of(mma8452_device.parent, struct i2c_client, dev); + struct mma8452_data *mma8452 = (struct mma8452_data *)i2c_get_clientdata(client); + mmaprintk("Gsensor mma7760 resume!!\n"); + return mma8452_start_dev(mma8452->curr_tate); +} +#else +static int mma8452_suspend(struct i2c_client *client, pm_message_t mesg) +{ + mmaprintk("Gsensor mma7760 enter 2 level suspend\n"); + return mma8452_close_dev(client); +} +static int mma8452_resume(struct i2c_client *client) +{ + struct mma8452_data *mma8452 = (struct mma8452_data *)i2c_get_clientdata(client); + mmaprintk("Gsensor mma7760 2 level resume!!\n"); + return mma8452_start_dev(client, mma8452->curr_tate); +} +#endif + +static const struct i2c_device_id mma8452_id[] = { + {"gs_mma8452", 0}, + { } +}; + +static struct i2c_driver mma8452_driver = { + .driver = { + .name = "gs_mma8452", + }, + .id_table = mma8452_id, + .probe = mma8452_probe, + .remove = __devexit_p(mma8452_remove), +#ifndef CONFIG_ANDROID_POWER + .suspend = &mma8452_suspend, + .resume = &mma8452_resume, +#endif +}; + + +static int mma8452_init_client(struct i2c_client *client) +{ + struct mma8452_data *mma8452; + int ret; + mma8452 = i2c_get_clientdata(client); + mmaprintk("gpio_to_irq(%d) is %d\n",client->irq,gpio_to_irq(client->irq)); + if ( !gpio_is_valid(client->irq)) { + mmaprintk("+++++++++++gpio_is_invalid\n"); + return -EINVAL; + } + ret = gpio_request(client->irq, "mma8452_int"); + if (ret) { + mmaprintk( "failed to request mma7990_trig GPIO%d\n",gpio_to_irq(client->irq)); + return ret; + } + ret = gpio_direction_input(client->irq); + if (ret) { + mmaprintk("failed to set mma7990_trig GPIO gpio input\n"); + return ret; + } + gpio_pull_updown(client->irq, GPIOPullUp); + client->irq = gpio_to_irq(client->irq); + ret = request_irq(client->irq, mma8452_interrupt, IRQF_TRIGGER_LOW, client->dev.driver->name, mma8452); + mmaprintk("request irq is %d,ret is 0x%x\n",client->irq,ret); + if (ret ) { + mmaprintk(KERN_ERR "mma8452_init_client: request irq failed,ret is %d\n",ret); + return ret; + } + disable_irq(client->irq); + init_waitqueue_head(&data_ready_wq); + + return 0; +} + +static int mma8452_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct mma8452_data *mma8452; + struct mma8452_platform_data *pdata = pdata = client->dev.platform_data; + int err; + + mmaprintk("%s enter\n",__FUNCTION__); + + mma8452 = kzalloc(sizeof(struct mma8452_data), GFP_KERNEL); + if (!mma8452) { + mmaprintk("[mma8452]:alloc data failed.\n"); + err = -ENOMEM; + goto exit_alloc_data_failed; + } + + INIT_WORK(&mma8452->work, mma8452_work_func); + INIT_DELAYED_WORK(&mma8452->delaywork, mma8452_delaywork_func); + + mma8452->client = client; + i2c_set_clientdata(client, mma8452); + + this_client = client; + + err = mma8452_init_client(client); + if (err < 0) { + mmaprintk(KERN_ERR + "mma8452_probe: mma8452_init_client failed\n"); + goto exit_request_gpio_irq_failed; + } + + mma8452->input_dev = input_allocate_device(); + if (!mma8452->input_dev) { + err = -ENOMEM; + mmaprintk(KERN_ERR + "mma8452_probe: Failed to allocate input device\n"); + goto exit_input_allocate_device_failed; + } + + set_bit(EV_ABS, mma8452->input_dev->evbit); + + /* x-axis acceleration */ + input_set_abs_params(mma8452->input_dev, ABS_X, -20000, 20000, 0, 0); //2g full scale range + /* y-axis acceleration */ + input_set_abs_params(mma8452->input_dev, ABS_Y, -20000, 20000, 0, 0); //2g full scale range + /* z-axis acceleration */ + input_set_abs_params(mma8452->input_dev, ABS_Z, -20000, 20000, 0, 0); //2g full scale range + + mma8452->input_dev->name = "compass"; + mma8452->input_dev->dev.parent = &client->dev; + + err = input_register_device(mma8452->input_dev); + if (err < 0) { + mmaprintk(KERN_ERR + "mma8452_probe: Unable to register input device: %s\n", + mma8452->input_dev->name); + goto exit_input_register_device_failed; + } + + mma8452_device.parent = &client->dev; + err = misc_register(&mma8452_device); + if (err < 0) { + mmaprintk(KERN_ERR + "mma8452_probe: mmad_device register failed\n"); + goto exit_misc_device_register_mma8452_device_failed; + } + + err = gsensor_sysfs_init(); + if (err < 0) { + mmaprintk(KERN_ERR + "mma8452_probe: gsensor sysfs init failed\n"); + goto exit_gsensor_sysfs_init_failed; + } + +#ifdef CONFIG_ANDROID_POWER + mma8452_early_suspend.suspend = mma8452_suspend; + mma8452_early_suspend.resume = mma8452_resume; + mma8452_early_suspend.level = 0x2; + android_register_early_suspend(&mma8452_early_suspend); +#endif + mma8452_get_devid(this_client); + mmaprintk(KERN_INFO "mma8452 probe ok\n"); + + + mma8452->status = -1; +#if 1 +// mma8452_start_test(this_client); + mma8452_start(client, MMA8452_RATE_12P5); +#endif + return 0; + +exit_gsensor_sysfs_init_failed: + misc_deregister(&mma8452_device); +exit_misc_device_register_mma8452_device_failed: + input_unregister_device(mma8452->input_dev); +exit_input_register_device_failed: + input_free_device(mma8452->input_dev); +exit_input_allocate_device_failed: + free_irq(client->irq, mma8452); +exit_request_gpio_irq_failed: + kfree(mma8452); +exit_alloc_data_failed: + ; + mmaprintk("%s error\n",__FUNCTION__); + return err; +} + + +static int __init mma8452_i2c_init(void) +{ + return i2c_add_driver(&mma8452_driver); +} + +static void __exit mma8452_i2c_exit(void) +{ + i2c_del_driver(&mma8452_driver); +} + +module_init(mma8452_i2c_init); +module_exit(mma8452_i2c_exit); + diff --git a/include/linux/mma8452.h b/include/linux/mma8452.h new file mode 100644 index 000000000000..195db4ff7b36 --- /dev/null +++ b/include/linux/mma8452.h @@ -0,0 +1,136 @@ +/* + * Definitions for mma8452 compass chip. + */ +#ifndef MMA8452_H +#define MMA8452_H + +#include + +/* Default register settings */ +#define RBUFF_SIZE 12 /* Rx buffer size */ + +#define MMA8452_REG_STATUS 0x0 //RO +#define MMA8452_REG_X_OUT_MSB 0x1 //RO +#define MMA8452_REG_X_OUT_LSB 0x2 //RO +#define MMA8452_REG_Y_OUT_MSB 0x3 //RO +#define MMA8452_REG_Y_OUT_LSB 0x4 //RO +#define MMA8452_REG_Z_OUT_MSB 0x5 //RO +#define MMA8452_REG_Z_OUT_LSB 0x6 //RO +#define MMA8452_REG_F_SETUP 0x9 //RW + +#define MMA8452_REG_SYSMOD 0xB //RO +#define MMA8452_REG_INTSRC 0xC //RO +#define MMA8452_REG_WHO_AM_I 0xD //RO +#define MMA8452_REG_XYZ_DATA_CFG 0xE //RW +#define MMA8452_REG_HP_FILTER_CUTOFF 0xF //RW +#define MMA8452_REG_PL_STATUS 0x10 //RO +#define MMA8452_REG_PL_CFG 0x11 //RW +#define MMA8452_REG_PL_COUNT 0x12 //RW +#define MMA8452_REG_PL_BF_ZCOMP 0x13 //RW +#define MMA8452_REG_P_L_THS_REG 0x14 //RW +#define MMA8452_REG_FF_MT_CFG 0x15 //RW +#define MMA8452_REG_FF_MT_SRC 0x16 //RO +#define MMA8452_REG_FF_MT_THS 0x17 //RW +#define MMA8452_REG_FF_MT_COUNT 0x18 //RW +#define MMA8452_REG_TRANSIENT_CFG 0x1D //RW +#define MMA8452_REG_TRANSIENT_SRC 0x1E //RO +#define MMA8452_REG_TRANSIENT_THS 0x1F //RW +#define MMA8452_REG_TRANSIENT_COUNT 0x20 //RW +#define MMA8452_REG_PULSE_CFG 0x21 //RW +#define MMA8452_REG_PULSE_SRC 0x22 //RO +#define MMA8452_REG_PULSE_THSX 0x23 //RW +#define MMA8452_REG_PULSE_THSY 0x24 //RW +#define MMA8452_REG_PULSE_THSZ 0x25 //RW +#define MMA8452_REG_PULSE_TMLT 0x26 //RW +#define MMA8452_REG_PULSE_LTCY 0x27 //RW +#define MMA8452_REG_PULSE_WIND 0x28 //RW +#define MMA8452_REG_ASLP_COUNT 0x29 //RW +#define MMA8452_REG_CTRL_REG1 0x2A //RW +#define MMA8452_REG_CTRL_REG2 0x2B //RW +#define MMA8452_REG_CTRL_REG3 0x2C //RW +#define MMA8452_REG_CTRL_REG4 0x2D //RW +#define MMA8452_REG_CTRL_REG5 0x2E //RW +#define MMA8452_REG_OFF_X 0x2F //RW +#define MMA8452_REG_OFF_Y 0x30 //RW +#define MMA8452_REG_OFF_Z 0x31 //RW + +#define MMAIO 0xA1 + +/* 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]) + +/* IOCTLs for APPs */ +#define ECS_IOCTL_APP_SET_RATE _IOW(MMAIO, 0x10, char) + + +/*rate*/ +#define MMA8452_RATE_800 0 +#define MMA8452_RATE_400 1 +#define MMA8452_RATE_200 2 +#define MMA8452_RATE_100 3 +#define MMA8452_RATE_50 4 +#define MMA8452_RATE_12P5 5 +#define MMA8452_RATE_6P25 6 +#define MMA8452_RATE_1P56 7 +#define MMA8452_RATE_SHIFT 3 + + +#define MMA8452_ASLP_RATE_50 0 +#define MMA8452_ASLP_RATE_12P5 1 +#define MMA8452_ASLP_RATE_6P25 2 +#define MMA8452_ASLP_RATE_1P56 3 +#define MMA8452_ASLP_RATE_SHIFT 6 + +#define ACTIVE_MASK 1 +#define FREAD_MASK 2 + + + + +/*status*/ +#define MMA8452_OPEN 1 +#define MMA8452_CLOSE 0 + + + +//#define MMA8452_IIC_ADDR 0x98 +#define MMA8452_REG_LEN 11 +#define MMA8452_GRAVITY_STEP 156 //2g full scale range +#define MMA8452_PRECISION 8 //8bit data +#define MMA8452_BOUNDARY (0x1 << (MMA8452_PRECISION - 1)) +#define MMA8452_TOTAL_TIME 10 + + +/* +struct mma8452_platform_data { + int reset; + int clk_on; + int intr; +}; + +*/ + +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; + int z; +}; + +#define GSENSOR_DEV_PATH "/dev/mma8452_daemon" + + +#endif +