diff options
Diffstat (limited to 'drivers/hwmon/mma8x5x.c')
-rw-r--r-- | drivers/hwmon/mma8x5x.c | 441 |
1 files changed, 285 insertions, 156 deletions
diff --git a/drivers/hwmon/mma8x5x.c b/drivers/hwmon/mma8x5x.c index 4b13a2521f86..d77dc515043f 100644 --- a/drivers/hwmon/mma8x5x.c +++ b/drivers/hwmon/mma8x5x.c @@ -34,6 +34,7 @@ #include <linux/hwmon.h> #include <linux/input.h> #include <linux/miscdevice.h> +#include <linux/regulator/consumer.h> #define MMA8X5X_I2C_ADDR 0x1D #define MMA8451_ID 0x1A @@ -155,12 +156,14 @@ struct mma8x5x_data { int position; u8 chip_id; int mode; - int awaken; // is just awake from suspend + int awaken; s64 period_rel; int fifo_wakeup; int fifo_timeout; + u32 int_pin; }; -static struct mma8x5x_data * p_mma8x5x_data = NULL; + +static struct mma8x5x_data *p_mma8x5x_data; /* Addresses scanned */ static const unsigned short normal_i2c[] = { 0x1c, 0x1d, I2C_CLIENT_END }; @@ -205,7 +208,8 @@ static int mma8x5x_data_convert(struct mma8x5x_data *pdata, for (i = 0; i < 3; i++) { data[i] = 0; for (j = 0; j < 3; j++) - data[i] += rawdata[j] * mma8x5x_position_setting[position][i][j]; + data[i] += rawdata[j] * + mma8x5x_position_setting[position][i][j]; } axis_data->x = data[0]; axis_data->y = data[1]; @@ -216,7 +220,8 @@ static int mma8x5x_check_id(int id) { int i = 0; - for (i = 0; i < sizeof(mma8x5x_chip_id) / sizeof(mma8x5x_chip_id[0]); i++) + for (i = 0; i < sizeof(mma8x5x_chip_id) / + sizeof(mma8x5x_chip_id[0]); i++) if (id == mma8x5x_chip_id[i]) return 1; return 0; @@ -226,7 +231,8 @@ static char *mma8x5x_id2name(u8 id) return mma8x5x_names[(id >> 4) - 1]; } -static int mma8x5x_i2c_read_fifo(struct i2c_client *client,u8 reg, char * buf, int len) +static int mma8x5x_i2c_read_fifo(struct i2c_client *client, + u8 reg, char *buf, int len) { char send_buf[] = {reg}; struct i2c_msg msgs[] = { @@ -251,42 +257,51 @@ static int mma8x5x_i2c_read_fifo(struct i2c_client *client,u8 reg, char * buf, i } /*period is ms, return the real period per event*/ -static s64 mma8x5x_odr_set(struct i2c_client * client, int period){ +static s64 mma8x5x_odr_set(struct i2c_client *client, int period) +{ u8 odr; u8 val; s64 period_rel; val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1); - i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1,val &(~0x01)); //standby + /*Standby*/ + i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, val & (~0x01)); val &= ~(0x07 << 3); - if(period >= 640){ /*1.56HZ*/ + if (period >= 640) { + /*1.56HZ*/ odr = 0x7; period_rel = 640 * NSEC_PER_MSEC; - } - else if(period >= 160){ /*6.25HZ*/ + } else if (period >= 160) { + /*6.25HZ*/ odr = 0x06; period_rel = 160 * NSEC_PER_MSEC; - } - else if(period >= 80){ /*12.5HZ*/ + } else if (period >= 80) { + /*12.5HZ*/ odr = 0x05; period_rel = 80 * NSEC_PER_MSEC; - }else if(period >= 20){ /*50HZ*/ + } else if (period >= 20) { + /*50HZ*/ odr = 0x04; period_rel = 20 * NSEC_PER_MSEC; - }else if(period >= 10){ /*100HZ*/ + } else if (period >= 10) { + /*100HZ*/ odr = 0x03; period_rel = 10 * NSEC_PER_MSEC; - }else if(period >= 5){ /*200HZ*/ + } else if (period >= 5) { + /*200HZ*/ odr = 0x02; period_rel = 5 * NSEC_PER_MSEC; - }else if((period * 2) >= 5){ /*400HZ*/ + } else if ((period * 2) >= 5) { + /*400HZ*/ odr = 0x01; period_rel = 2500 * NSEC_PER_USEC; - }else{ /*800HZ*/ + } else { + /*800HZ*/ odr = 0x00; period_rel = 1250 * NSEC_PER_USEC; } val |= (odr << 3); - i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1,val); //standby + /*Standby*/ + i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, val); return period_rel; } static int mma8x5x_device_init(struct i2c_client *client) @@ -335,66 +350,93 @@ static int mma8x5x_read_data(struct i2c_client *client, data->z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5]; return 0; } -static int mma8x5x_fifo_interrupt(struct i2c_client *client,int enable) + +static int mma8x5x_fifo_interrupt(struct i2c_client *client, int enable) { - u8 val,sys_mode; - sys_mode = i2c_smbus_read_byte_data(client,MMA8X5X_CTRL_REG1); - i2c_smbus_write_byte_data(client,MMA8X5X_CTRL_REG1,(sys_mode & (~0x01))); //standby - val = i2c_smbus_read_byte_data(client,MMA8X5X_CTRL_REG4); + u8 val, sys_mode; + sys_mode = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1); + /*standby*/ + i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, + (sys_mode & (~0x01))); + val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG4); val &= ~(0x01 << 6); - if(enable) + if (enable) val |= (0x01 << 6); - i2c_smbus_write_byte_data(client,MMA8X5X_CTRL_REG4,val); - i2c_smbus_write_byte_data(client,MMA8X5X_CTRL_REG1,sys_mode); + i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG4, val); + i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, sys_mode); return 0; } -static int mma8x5x_fifo_setting(struct mma8x5x_data *pdata,int time_out,int is_overwrite) + +static int mma8x5x_fifo_setting(struct mma8x5x_data *pdata, + int time_out, int is_overwrite) { - u8 val,sys_mode,pin_cfg; + u8 val, sys_mode, pin_cfg; struct i2c_client *client = pdata->client; - sys_mode = i2c_smbus_read_byte_data(client,MMA8X5X_CTRL_REG1); - i2c_smbus_write_byte_data(client,MMA8X5X_CTRL_REG1,(sys_mode & (~0x01))); //standby - pin_cfg = i2c_smbus_read_byte_data(client,MMA8X5X_CTRL_REG5); - val = i2c_smbus_read_byte_data(client,MMA8X5X_F_SETUP); + sys_mode = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1); + /*standby*/ + i2c_smbus_write_byte_data(client, + MMA8X5X_CTRL_REG1, + (sys_mode & (~0x01))); + pin_cfg = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG5); + val = i2c_smbus_read_byte_data(client, MMA8X5X_F_SETUP); val &= ~(0x03 << 6); - if(time_out > 0){ - if(is_overwrite) + if (time_out > 0) { + if (is_overwrite) val |= (0x01 << 6); else val |= (0x02 << 6); } - i2c_smbus_write_byte_data(client,MMA8X5X_F_SETUP,val); - i2c_smbus_write_byte_data(client,MMA8X5X_CTRL_REG5,pin_cfg |(0x01 << 6));//route to pin 1 - i2c_smbus_write_byte_data(client,MMA8X5X_CTRL_REG1,sys_mode); - if(time_out > 0){ - pdata->period_rel = mma8x5x_odr_set(client,time_out/32); //fifo len is 32 + i2c_smbus_write_byte_data(client, MMA8X5X_F_SETUP, val); + /*route to pin 1*/ + if (pdata->int_pin == 1) + i2c_smbus_write_byte_data(client, + MMA8X5X_CTRL_REG5, + pin_cfg | (0x01 << 6)); + /*route to pin 1*/ + else + i2c_smbus_write_byte_data(client, + MMA8X5X_CTRL_REG5, + pin_cfg & ~(0x01 << 6)); + + i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, sys_mode); + + if (time_out > 0) { + /*fifo len is 32*/ + pdata->period_rel = mma8x5x_odr_set(client, time_out/32); } return 0; } -static int mma8x5x_read_fifo_data(struct mma8x5x_data *pdata){ - int count,cnt; - u8 buf[256],val; - int i,index; +static int mma8x5x_read_fifo_data(struct mma8x5x_data *pdata) +{ + int count, cnt; + u8 buf[256], val; + int i, index; struct i2c_client *client = pdata->client; struct mma8x5x_fifo *pfifo = &pdata->fifo; struct timespec ts; - val = i2c_smbus_read_byte_data(client,MMA8X5X_STATUS); - if(val & (0x01 << 7)) //fifo overflow - { + val = i2c_smbus_read_byte_data(client, MMA8X5X_STATUS); + /*FIFO overflow*/ + if (val & (0x01 << 7)) { cnt = (val & 0x3f); - count = mma8x5x_i2c_read_fifo(client,MMA8X5X_OUT_X_MSB,buf,MMA8X5X_BUF_SIZE * cnt); - if(count > 0){ + count = mma8x5x_i2c_read_fifo(client, MMA8X5X_OUT_X_MSB, + buf, MMA8X5X_BUF_SIZE * cnt); + if (count > 0) { ktime_get_ts(&ts); - for(i = 0; i < count/MMA8X5X_BUF_SIZE ;i++){ + for (i = 0; i < count/MMA8X5X_BUF_SIZE ; i++) { index = MMA8X5X_BUF_SIZE * i; - pfifo->fifo_data[i].x = ((buf[index] << 8) & 0xff00) | buf[index + 1]; - pfifo->fifo_data[i].y = ((buf[index + 2] << 8) & 0xff00) | buf[index + 3]; - pfifo->fifo_data[i].z = ((buf[index + 4] << 8) & 0xff00) | buf[index + 5]; - mma8x5x_data_convert(pdata, &pfifo->fifo_data[i]); + pfifo->fifo_data[i].x = + ((buf[index] << 8) & 0xff00) | buf[index + 1]; + pfifo->fifo_data[i].y = + ((buf[index + 2] << 8) & 0xff00) | buf[index + 3]; + pfifo->fifo_data[i].z = + ((buf[index + 4] << 8) & 0xff00) | buf[index + 5]; + mma8x5x_data_convert(pdata, + &pfifo->fifo_data[i]); } pfifo->period = pdata->period_rel; pfifo->count = count / MMA8X5X_BUF_SIZE; - pfifo->timestamp = ((s64)ts.tv_sec) * NSEC_PER_SEC + ts.tv_nsec; + pfifo->timestamp = ((s64)ts.tv_sec) * NSEC_PER_SEC + + ts.tv_nsec; return 0; } } @@ -406,7 +448,7 @@ static void mma8x5x_report_data(struct mma8x5x_data *pdata) struct mma8x5x_data_axis data; int ret; ret = mma8x5x_read_data(pdata->client, &data); - if(!ret){ + if (!ret) { mma8x5x_data_convert(pdata, &data); input_report_abs(pdata->idev, ABS_X, data.x); input_report_abs(pdata->idev, ABS_Y, data.y); @@ -414,9 +456,10 @@ static void mma8x5x_report_data(struct mma8x5x_data *pdata) input_sync(pdata->idev); } } -static void mma8x5x_work(struct mma8x5x_data * pdata){ +static void mma8x5x_work(struct mma8x5x_data *pdata) +{ int delay; - if(pdata->active == MMA_ACTIVED){ + if (pdata->active == MMA_ACTIVED) { delay = msecs_to_jiffies(pdata->delay); if (delay >= HZ) delay = round_jiffies_relative(delay); @@ -425,7 +468,9 @@ static void mma8x5x_work(struct mma8x5x_data * pdata){ } static void mma8x5x_dev_poll(struct work_struct *work) { - struct mma8x5x_data *pdata = container_of(work, struct mma8x5x_data,work.work); + struct mma8x5x_data *pdata = container_of(work, + struct mma8x5x_data, + work.work); mma8x5x_report_data(pdata); mma8x5x_work(pdata); } @@ -434,24 +479,24 @@ static irqreturn_t mma8x5x_irq_handler(int irq, void *dev) int ret; u8 int_src; struct mma8x5x_data *pdata = (struct mma8x5x_data *)dev; - int_src = i2c_smbus_read_byte_data(pdata->client,MMA8X5X_INT_SOURCE); - if(int_src & (0x01 << 6)){ + int_src = i2c_smbus_read_byte_data(pdata->client, MMA8X5X_INT_SOURCE); + if (int_src & (0x01 << 6)) { ret = mma8x5x_read_fifo_data(pdata); - if(!ret){ + if (!ret) { atomic_set(&pdata->fifo_ready, 1); wake_up(&pdata->fifo_wq); } - if(pdata->awaken) /*is just awken from suspend*/ - { - mma8x5x_fifo_setting(pdata,pdata->fifo_timeout,0); //10s timeout - mma8x5x_fifo_interrupt(pdata->client,1); + /*is just awken from suspend*/ + if (pdata->awaken) { + /*10s timeout*/ + mma8x5x_fifo_setting(pdata, pdata->fifo_timeout, 0); + mma8x5x_fifo_interrupt(pdata->client, 1); pdata->awaken = 0; } } return IRQ_HANDLED; } - static ssize_t mma8x5x_enable_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -480,34 +525,46 @@ static ssize_t mma8x5x_enable_store(struct device *dev, unsigned long enable; u8 val = 0; - enable = simple_strtoul(buf, NULL, 10); + ret = strict_strtol(buf, 10, &enable); + if (ret) { + dev_err(dev, "string to long error\n"); + return ret; + } mutex_lock(&pdata->data_lock); enable = (enable > 0) ? 1 : 0; if (enable && pdata->active == MMA_STANDBY) { val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1); - ret = i2c_smbus_write_byte_data(client,MMA8X5X_CTRL_REG1, val | 0x01); + ret = i2c_smbus_write_byte_data(client, + MMA8X5X_CTRL_REG1, + val | 0x01); if (!ret) { pdata->active = MMA_ACTIVED; - if(pdata->fifo_timeout <= 0) //continuous mode + /*continuous mode*/ + if (pdata->fifo_timeout <= 0) mma8x5x_work(pdata); - else{ /*fifo mode*/ - mma8x5x_fifo_setting(pdata,pdata->fifo_timeout,0); //no overwirte fifo - mma8x5x_fifo_interrupt(client,1); + else { + /*fifo mode*/ + mma8x5x_fifo_setting(pdata, + pdata->fifo_timeout, 0); + mma8x5x_fifo_interrupt(client, 1); } - printk(KERN_INFO"mma enable setting active \n"); + printk(KERN_INFO"mma enable setting active\n"); } - } else if (enable == 0 && pdata->active == MMA_ACTIVED) { + } else if (enable == 0 && pdata->active == MMA_ACTIVED) { val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1); - ret = i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, val & 0xFE); + ret = i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, + val & 0xFE); if (!ret) { pdata->active = MMA_STANDBY; - if(pdata->fifo_timeout <= 0) //continuous mode + if (pdata->fifo_timeout <= 0) + /*continuous mode*/ cancel_delayed_work_sync(&pdata->work); - else{ /*fifo mode*/ - mma8x5x_fifo_setting(pdata,0,0); //no overwirte fifo - mma8x5x_fifo_interrupt(client,0); + else { + /*fifo mode*/ + mma8x5x_fifo_setting(pdata, 0, 0); + mma8x5x_fifo_interrupt(client, 0); } - printk(KERN_INFO"mma enable setting inactive \n"); + printk(KERN_INFO"mma enable setting inactive\n"); } } mutex_unlock(&pdata->data_lock); @@ -530,14 +587,20 @@ static ssize_t mma8x5x_delay_store(struct device *dev, const char *buf, size_t count) { struct mma8x5x_data *pdata = dev_get_drvdata(dev); - struct i2c_client * client = pdata->client; - int delay; - delay = simple_strtoul(buf, NULL, 10); + struct i2c_client *client = pdata->client; + int ret; + long delay; + ret = strict_strtol(buf, 10, &delay); + if (ret) { + dev_err(dev, "string to long error\n"); + return ret; + } + mutex_lock(&pdata->data_lock); cancel_delayed_work_sync(&pdata->work); - pdata->delay = delay; - if(pdata->active == MMA_ACTIVED && pdata->fifo_timeout <= 0){ - mma8x5x_odr_set(client,delay); + pdata->delay = (int)delay; + if (pdata->active == MMA_ACTIVED && pdata->fifo_timeout <= 0) { + mma8x5x_odr_set(client, (int)delay); mma8x5x_work(pdata); } mutex_unlock(&pdata->data_lock); @@ -551,9 +614,12 @@ static ssize_t mma8x5x_fifo_show(struct device *dev, struct mma8x5x_data *pdata = dev_get_drvdata(dev); mutex_lock(&pdata->data_lock); count = sprintf(&buf[count], "period poll :%d ms\n", pdata->delay); - count += sprintf(&buf[count],"period fifo :%lld ns\n",pdata->period_rel); - count += sprintf(&buf[count],"timeout :%d ms\n", pdata->fifo_timeout); - count += sprintf(&buf[count],"interrupt wake up: %s\n", (pdata->fifo_wakeup ? "yes" : "no")); /*is the interrupt enable*/ + count += sprintf(&buf[count], "period fifo :%lld ns\n", + pdata->period_rel); + count += sprintf(&buf[count], "timeout :%d ms\n", pdata->fifo_timeout); + /*is the interrupt enable*/ + count += sprintf(&buf[count], "interrupt wake up: %s\n", + (pdata->fifo_wakeup ? "yes" : "no")); mutex_unlock(&pdata->data_lock); return count; } @@ -563,27 +629,30 @@ static ssize_t mma8x5x_fifo_store(struct device *dev, const char *buf, size_t count) { struct mma8x5x_data *pdata = dev_get_drvdata(dev); - struct i2c_client * client = pdata->client; - int period,timeout,wakeup; - sscanf(buf,"%d,%d,%d",&period,&timeout,&wakeup); - printk("period %d ,timeout is %d, wake up is :%d\n",period,timeout,wakeup); - if(timeout > 0){ + struct i2c_client *client = pdata->client; + int period, timeout, wakeup; + sscanf(buf, "%d,%d,%d", &period, &timeout, &wakeup); + printk(KERN_INFO"period %d ,timeout is %d, wake up is :%d\n", + period, timeout, wakeup); + if (timeout > 0) { mutex_lock(&pdata->data_lock); cancel_delayed_work_sync(&pdata->work); pdata->delay = period; mutex_unlock(&pdata->data_lock); - mma8x5x_fifo_setting(pdata,timeout,0); //no overwirte fifo - mma8x5x_fifo_interrupt(client,1); + /*no overwirte fifo*/ + mma8x5x_fifo_setting(pdata, timeout, 0); + mma8x5x_fifo_interrupt(client, 1); pdata->fifo_timeout = timeout; pdata->fifo_wakeup = wakeup; - }else{ - mma8x5x_fifo_setting(pdata,timeout,0); //no overwirte fifo - mma8x5x_fifo_interrupt(client,0); + } else { + /*no overwirte fifo*/ + mma8x5x_fifo_setting(pdata, timeout, 0); + mma8x5x_fifo_interrupt(client, 0); pdata->fifo_timeout = timeout; pdata->fifo_wakeup = wakeup; mutex_lock(&pdata->data_lock); pdata->delay = period; - if(pdata->active == MMA_ACTIVED) + if (pdata->active == MMA_ACTIVED) mma8x5x_work(pdata); mutex_unlock(&pdata->data_lock); } @@ -606,10 +675,15 @@ static ssize_t mma8x5x_position_store(struct device *dev, const char *buf, size_t count) { struct mma8x5x_data *pdata = dev_get_drvdata(dev); - int position; - position = simple_strtoul(buf, NULL, 10); + int ret; + long position; + ret = strict_strtol(buf, 10, &position); + if (ret) { + dev_err(dev, "string to long error\n"); + return ret; + } mutex_lock(&pdata->data_lock); - pdata->position = position; + pdata->position = (int)position; mutex_unlock(&pdata->data_lock); return count; } @@ -646,12 +720,13 @@ static int mma8x5x_detect(struct i2c_client *client, chip_id = i2c_smbus_read_byte_data(client, MMA8X5X_WHO_AM_I); if (!mma8x5x_check_id(chip_id)) return -ENODEV; - printk(KERN_INFO "check %s i2c address 0x%x \n", + printk(KERN_INFO"check %s i2c address 0x%x\n", mma8x5x_id2name(chip_id), client->addr); strlcpy(info->type, "mma8x5x", I2C_NAME_SIZE); return 0; } -static int mma8x5x_open(struct inode *inode, struct file *file){ +static int mma8x5x_open(struct inode *inode, struct file *file) +{ int err; err = nonseekable_open(inode, file); if (err) @@ -659,27 +734,33 @@ static int mma8x5x_open(struct inode *inode, struct file *file){ file->private_data = p_mma8x5x_data; return 0; } -static ssize_t mma8x5x_read(struct file *file, char __user *buf, size_t size, loff_t *ppos){ +static ssize_t mma8x5x_read(struct file *file, + char __user *buf, + size_t size, loff_t *ppos) +{ struct mma8x5x_data *pdata = file->private_data; int ret = 0; if (!(file->f_flags & O_NONBLOCK)) { - ret = wait_event_interruptible(pdata->fifo_wq, (atomic_read(&pdata->fifo_ready) != 0)); + ret = wait_event_interruptible(pdata->fifo_wq, + (atomic_read(&pdata->fifo_ready) != 0)); if (ret) return ret; } if (!atomic_read(&pdata->fifo_ready)) return -ENODEV; - if(size < sizeof(struct mma8x5x_fifo)){ - printk(KERN_ERR "the buffer leght less than need\n"); + if (size < sizeof(struct mma8x5x_fifo)) { + printk(KERN_ERR"the buffer leght less than need\n"); return -ENOMEM; } - if(!copy_to_user(buf,&pdata->fifo,sizeof(struct mma8x5x_fifo))){ - atomic_set(&pdata->fifo_ready,0); + if (!copy_to_user(buf, &pdata->fifo, sizeof(struct mma8x5x_fifo))) { + atomic_set(&pdata->fifo_ready, 0); return size; } return -ENOMEM ; } -static unsigned int mma8x5x_poll(struct file * file, struct poll_table_struct * wait){ +static unsigned int mma8x5x_poll(struct file *file, + struct poll_table_struct *wait) +{ struct mma8x5x_data *pdata = file->private_data; poll_wait(file, &pdata->fifo_wq, wait); if (atomic_read(&pdata->fifo_ready)) @@ -707,8 +788,29 @@ static int mma8x5x_probe(struct i2c_client *client, struct input_dev *idev; struct mma8x5x_data *pdata; struct i2c_adapter *adapter; - struct device_node *of_node = client->dev.of_node; - u32 pos = 0; + struct device_node *of_node = client->dev.of_node; + u32 pos = 0; + struct regulator *vdd, *vdd_io; + u32 irq_flag; + struct irq_data *irq_data; + + vdd = devm_regulator_get(&client->dev, "vdd"); + if (!IS_ERR(vdd)) { + result = regulator_enable(vdd); + if (result) { + dev_err(&client->dev, "vdd set voltage error\n"); + return result; + } + } + + vdd_io = devm_regulator_get(&client->dev, "vddio"); + if (!IS_ERR(vdd_io)) { + result = regulator_enable(vdd_io); + if (result) { + dev_err(&client->dev, "vddio set voltage error\n"); + return result; + } + } adapter = to_i2c_adapter(client->dev.parent); result = i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE | @@ -716,7 +818,6 @@ static int mma8x5x_probe(struct i2c_client *client, if (!result) goto err_out; - printk(KERN_ERR"%s here 7", __func__); chip_id = i2c_smbus_read_byte_data(client, MMA8X5X_WHO_AM_I); if (!mma8x5x_check_id(chip_id)) { @@ -734,37 +835,30 @@ static int mma8x5x_probe(struct i2c_client *client, goto err_out; } - printk(KERN_ERR"%s here 6", __func__); /* Initialize the MMA8X5X chip */ - memset(pdata,0,sizeof(struct mma8x5x_data)); + memset(pdata, 0, sizeof(struct mma8x5x_data)); pdata->client = client; pdata->chip_id = chip_id; pdata->mode = MODE_2G; pdata->fifo_wakeup = 0; pdata->fifo_timeout = 0; - printk(KERN_ERR"%s here 0", __func__); - result = of_property_read_u32(of_node, "position",&pos ); - - printk(KERN_ERR"%s here result=%d pos=%d", __func__, result, pos); - if (result) - pos = 1; + result = of_property_read_u32(of_node, "position", &pos); + if (result) + pos = 1; pdata->position = (int)pos; p_mma8x5x_data = pdata; mutex_init(&pdata->data_lock); i2c_set_clientdata(client, pdata); - printk(KERN_ERR"%s here 12", __func__); mma8x5x_device_init(client); - printk(KERN_ERR"%s here 13", __func__); idev = input_allocate_device(); if (!idev) { result = -ENOMEM; dev_err(&client->dev, "alloc input device failed!\n"); goto err_alloc_input_device; } - printk(KERN_ERR"%s here 1", __func__); idev->name = "FreescaleAccelerometer"; idev->uniq = mma8x5x_id2name(pdata->chip_id); idev->id.bustype = BUS_I2C; @@ -772,9 +866,8 @@ static int mma8x5x_probe(struct i2c_client *client, input_set_abs_params(idev, ABS_X, -0x7fff, 0x7fff, 0, 0); input_set_abs_params(idev, ABS_Y, -0x7fff, 0x7fff, 0, 0); input_set_abs_params(idev, ABS_Z, -0x7fff, 0x7fff, 0, 0); - dev_set_drvdata(&idev->dev,pdata); - pdata->idev= idev ; - printk(KERN_ERR"%s here 2", __func__); + dev_set_drvdata(&idev->dev, pdata); + pdata->idev = idev; result = input_register_device(pdata->idev); if (result) { dev_err(&client->dev, "register input device failed!\n"); @@ -789,28 +882,53 @@ static int mma8x5x_probe(struct i2c_client *client, goto err_create_sysfs; } init_waitqueue_head(&pdata->fifo_wq); - if(client->irq){ - printk(KERN_ERR"%s here 3", __func__); - result= request_threaded_irq(client->irq,NULL, mma8x5x_irq_handler, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->dev.driver->name, pdata); + + if (client->irq) { + irq_data = irq_get_irq_data(client->irq); + irq_flag = irqd_get_trigger_type(irq_data); + irq_flag |= IRQF_ONESHOT; + result = request_threaded_irq(client->irq, NULL, + mma8x5x_irq_handler, + irq_flag, + client->dev.driver->name, + pdata); if (result < 0) { - dev_err(&client->dev, "failed to register MMA8x5x irq %d!\n", + dev_err(&client->dev, + "failed to register MMA8x5x irq %d!\n", client->irq); goto err_register_irq; - }else{ + } else { result = misc_register(&mma8x5x_dev); if (result) { - dev_err(&client->dev,"register fifo device error\n"); + dev_err(&client->dev, + "register fifo device error\n"); goto err_reigster_dev; } } + + result = of_property_read_u32(of_node, + "interrupt-route", + &pdata->int_pin); + if (result) { + result = -EINVAL; + dev_err(&client->dev, + "Can't find interrupt-pin value\n"); + goto err_reigster_dev; + + } + if (pdata->int_pin == 0 || pdata->int_pin > 2) { + result = -EINVAL; + dev_err(&client->dev, + "The interrupt-pin value is invalid\n"); + goto err_reigster_dev; + } } printk(KERN_INFO"mma8x5x device driver probe successfully\n"); return 0; err_reigster_dev: - free_irq(client->irq,pdata); + free_irq(client->irq, pdata); err_register_irq: - sysfs_remove_group(&idev->dev.kobj,&mma8x5x_attr_group); + sysfs_remove_group(&idev->dev.kobj, &mma8x5x_attr_group); err_create_sysfs: input_unregister_device(pdata->idev); err_register_input_device: @@ -820,13 +938,14 @@ err_alloc_input_device: err_out: return result; } + static int mma8x5x_remove(struct i2c_client *client) { struct mma8x5x_data *pdata = i2c_get_clientdata(client); struct input_dev *idev = pdata->idev; mma8x5x_device_stop(client); if (pdata) { - sysfs_remove_group(&idev->dev.kobj,&mma8x5x_attr_group); + sysfs_remove_group(&idev->dev.kobj, &mma8x5x_attr_group); input_unregister_device(pdata->idev); input_free_device(pdata->idev); kfree(pdata); @@ -839,17 +958,19 @@ static int mma8x5x_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct mma8x5x_data *pdata = i2c_get_clientdata(client); - if(pdata->fifo_timeout <= 0){ + if (pdata->fifo_timeout <= 0) { if (pdata->active == MMA_ACTIVED) mma8x5x_device_stop(client); - }else{ - if (pdata->active == MMA_ACTIVED){ - if (pdata->fifo_wakeup){ - mma8x5x_fifo_setting(pdata,10000,0); //10s timeout , overwrite - mma8x5x_fifo_interrupt(client,1); - }else{ - mma8x5x_fifo_interrupt(client,0); - mma8x5x_fifo_setting(pdata,10000,1); //10s timeout , overwrite + } else { + if (pdata->active == MMA_ACTIVED) { + if (pdata->fifo_wakeup) { + /*10s timeout , overwrite*/ + mma8x5x_fifo_setting(pdata, 10000, 0); + mma8x5x_fifo_interrupt(client, 1); + } else { + mma8x5x_fifo_interrupt(client, 0); + /*10s timeout , overwrite*/ + mma8x5x_fifo_setting(pdata, 10000, 1); } } } @@ -861,15 +982,18 @@ static int mma8x5x_resume(struct device *dev) int val = 0; struct i2c_client *client = to_i2c_client(dev); struct mma8x5x_data *pdata = i2c_get_clientdata(client); - if(pdata->fifo_timeout <= 0){ + if (pdata->fifo_timeout <= 0) { if (pdata->active == MMA_ACTIVED) { - val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1); - i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, val | 0x01); + val = i2c_smbus_read_byte_data(client, + MMA8X5X_CTRL_REG1); + i2c_smbus_write_byte_data(client, + MMA8X5X_CTRL_REG1, val | 0x01); } - }else{ + } else { if (pdata->active == MMA_ACTIVED) { - mma8x5x_fifo_interrupt(client,1); - pdata->awaken = 1; //awake from suspend + mma8x5x_fifo_interrupt(client, 1); + /*Awake from suspend*/ + pdata->awaken = 1; } } return 0; @@ -878,9 +1002,14 @@ static int mma8x5x_resume(struct device *dev) #endif static const struct i2c_device_id mma8x5x_id[] = { - { "mma8x5x", 0 }, - { } + {"mma8451", 0}, + {"mma8452", 0}, + {"mma8453", 0}, + {"mma8652", 0}, + {"mma8653", 0}, + {} }; + MODULE_DEVICE_TABLE(i2c, mma8x5x_id); static SIMPLE_DEV_PM_OPS(mma8x5x_pm_ops, mma8x5x_suspend, mma8x5x_resume); |