summaryrefslogtreecommitdiff
path: root/drivers/hwmon/mma8x5x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/mma8x5x.c')
-rw-r--r--drivers/hwmon/mma8x5x.c441
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);