summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorguoyin.chen <guoyin.chen@freescale.com>2013-06-18 18:25:32 +0800
committerguoyin.chen <guoyin.chen@freescale.com>2013-06-26 17:14:15 +0800
commit42dac4e485bb620ac7f57544e347820599024388 (patch)
tree67b7db0b3edbaeb5bc8fc63b30b729bc7b25f9b1
parent0f2d6ad7875b8cf1efc2d1f41b865ec5251770f1 (diff)
ENGR00268599-1 Integrate Fsl_Sensor_Android_v4.0 update for sensor driver
Update sensor driver from Fsl_Sensor_Android_v4.0 release Signed-off-by: guoyin.chen <guoyin.chen@freescale.com>
-rwxr-xr-xdrivers/hwmon/Kconfig16
-rwxr-xr-xdrivers/hwmon/Makefile3
-rwxr-xr-xdrivers/hwmon/mag3110.c481
-rw-r--r--drivers/hwmon/mma8x5x.c561
-rw-r--r--drivers/hwmon/mxc_mma8450.c392
-rw-r--r--drivers/hwmon/mxc_mma8451.c521
6 files changed, 837 insertions, 1137 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index b42baef3dcd0..3fdc73765c9f 100755
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1419,14 +1419,12 @@ config SENSORS_MAG3110
This driver can also be built as a module. If so, the module
will be called mag3110.
-config MXC_MMA8450
- tristate "MMA8450 device driver"
- depends on I2C
- default y
-
-config MXC_MMA8451
- tristate "MMA8451 device driver"
- depends on I2C
- default y
+config SENSORS_MMA8X5X
+ tristate "MMA8451/MMA8452/MMA8453/MMA8652/MMA8653 device driver"
+ depends on I2C && SYSFS
+ default n
+ help
+ If you say yes here you get support for the Freescale
+ MMA8451/MMA8452/MMA8453/MMA8652/MMA8653 sensors.
endif # HWMON
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index fc6e6b43a287..71e7a24ef8db 100755
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -120,8 +120,7 @@ obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o
obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o
obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o
obj-$(CONFIG_SENSORS_MAG3110) += mag3110.o
-obj-$(CONFIG_MXC_MMA8450) += mxc_mma8450.o
-obj-$(CONFIG_MXC_MMA8451) += mxc_mma8451.o
+obj-$(CONFIG_SENSORS_MMA8X5X) += mma8x5x.o
obj-$(CONFIG_SENSORS_DA9052) += da9052-adc.o
obj-$(CONFIG_SENSORS_IMX_AHCI) += imx_ahci_hwmon.o
diff --git a/drivers/hwmon/mag3110.c b/drivers/hwmon/mag3110.c
index f17212553355..67681e2a25d1 100755
--- a/drivers/hwmon/mag3110.c
+++ b/drivers/hwmon/mag3110.c
@@ -1,6 +1,6 @@
/*
*
- * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -31,21 +31,26 @@
#include <linux/wait.h>
#include <linux/workqueue.h>
+#define ABS_STATUS ABS_WHEEL
+
#define MAG3110_DRV_NAME "mag3110"
-#define MAG3110_ID 0xC4
-#define MAG3110_XYZ_DATA_LEN 6
-#define MAG3110_STATUS_ZYXDR 0x08
+#define MAG3110_ID 0xC4
+#define MAG3110_XYZ_DATA_LEN 6
+#define MAG3110_STATUS_ZYXDR 0x08
#define MAG3110_AC_MASK (0x01)
#define MAG3110_AC_OFFSET 0
#define MAG3110_DR_MODE_MASK (0x7 << 5)
#define MAG3110_DR_MODE_OFFSET 5
-#define MAG3110_IRQ_USED 1
+#define MAG3110_IRQ_USED 1
+
+#define POLL_INTERVAL_MAX 500
+#define POLL_INTERVAL_MIN 1
+#define POLL_INTERVAL 100
+/* if sensor is standby ,set POLL_STOP_TIME to slow down the poll */
+#define POLL_STOP_TIME 200
-#define POLL_INTERVAL_MIN 100
-#define POLL_INTERVAL_MAX 1000
-#define POLL_INTERVAL 500
-#define INT_TIMEOUT 1000
+#define INT_TIMEOUT 1000
/* register enum for mag3110 registers */
enum {
MAG3110_DR_STATUS = 0x00,
@@ -73,57 +78,61 @@ enum {
MAG_STANDBY,
MAG_ACTIVED
};
+struct mag3110_data_axis {
+ short x;
+ short y;
+ short z;
+};
+
struct mag3110_data {
struct i2c_client *client;
struct input_polled_dev *poll_dev;
- struct device *hwmon_dev;
+ /* mag3110 calibrated data report input dev */
+ struct input_dev *cal_input;
+ struct mutex data_lock;
wait_queue_head_t waitq;
bool data_ready;
u8 ctl_reg1;
int active;
int position;
};
-static short MAGHAL[8][3][3] = {
- {{ 0, 1, 0}, {-1, 0, 0}, {0, 0, 1} },
- {{ 1, 0, 0}, { 0, 1, 0}, {0, 0, 1} },
- {{ 0, -1, 0}, { 1, 0, 0}, {0, 0, 1} },
- {{-1, 0, 0}, { 0, -1, 0}, {0, 0, 1} },
+static short mag3110_position_setting[8][3][3] = {
+ { { 0, -1, 0 }, { 1, 0, 0 }, { 0, 0, -1 } },
+ { { -1, 0, 0 }, { 0, -1, 0 }, { 0, 0, -1 } },
+ { { 0, 1, 0 }, { -1, 0, 0 }, { 0, 0, -1 } },
+ { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, -1 } },
- {{ 0, 1, 0}, { 1, 0, 0}, {0, 0, -1} },
- {{ 1, 0, 0}, { 0, -1, 0}, {0, 0, -1} },
- {{ 0, -1, 0}, {-1, 0, 0}, {0, 0, -1} },
- {{-1, 0, 0}, { 0, 1, 0}, {0, 0, -1} },
+ { { 0, -1, 0 }, { -1, 0, 0 }, { 0, 0, 1 } },
+ { { -1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } },
+ { { 0, 1, 0 }, { 1, 0, 0 }, { 0, 0, 1 } },
+ { { 1, 0, 0 }, { 0, -1, 0 }, { 0, 0, 1 } },
};
-static struct mag3110_data *mag3110_pdata;
/*!
* This function do one mag3110 register read.
*/
-static DEFINE_MUTEX(mag3110_lock);
-static int mag3110_adjust_position(short *x, short *y, short *z)
+static int mag3110_data_convert(int position,
+ struct mag3110_data_axis *axis_data)
{
short rawdata[3], data[3];
int i, j;
- int position = mag3110_pdata->position;
+
if (position < 0 || position > 7)
position = 0;
-
- rawdata[0] = *x;
- rawdata[1] = *y;
- rawdata[2] = *z;
-
+ rawdata[0] = axis_data->x;
+ rawdata[1] = axis_data->y;
+ rawdata[2] = axis_data->z;
for (i = 0; i < 3; i++) {
data[i] = 0;
for (j = 0; j < 3; j++)
- data[i] += rawdata[j] * MAGHAL[position][i][j];
+ data[i] += rawdata[j] * mag3110_position_setting[position][i][j];
}
- *x = data[0];
- *y = data[1];
- *z = data[2];
+ axis_data->x = data[0];
+ axis_data->y = data[1];
+ axis_data->z = data[2];
return 0;
}
-
static int mag3110_read_reg(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
@@ -146,10 +155,10 @@ static int mag3110_write_reg(struct i2c_client *client, u8 reg, char value)
* This function do multiple mag3110 registers read.
*/
static int mag3110_read_block_data(struct i2c_client *client, u8 reg,
- int count, u8 *addr)
+ int count, u8 *addr)
{
if (i2c_smbus_read_i2c_block_data
- (client, reg, count, addr) < count) {
+ (client, reg, count, addr) < count) {
dev_err(&client->dev, "i2c block read failed\n");
return -1;
}
@@ -177,157 +186,198 @@ static int mag3110_init_client(struct i2c_client *client)
}
/***************************************************************
- *
- * read sensor data from mag3110
- *
- ***************************************************************/
-static int mag3110_read_data(short *x, short *y, short *z)
+*
+* read sensor data from mag3110
+*
+***************************************************************/
+static int mag3110_read_data(struct i2c_client *client,
+ struct mag3110_data_axis *pdata)
{
- struct mag3110_data *data;
+ struct mag3110_data *mag = i2c_get_clientdata(client);
u8 tmp_data[MAG3110_XYZ_DATA_LEN];
-#if !MAG3110_IRQ_USED
- int retry = 3;
- int result;
-#endif
- if (!mag3110_pdata || mag3110_pdata->active == MAG_STANDBY)
+ if (!mag || mag->active == MAG_STANDBY)
return -EINVAL;
-
- data = mag3110_pdata;
#if MAG3110_IRQ_USED
if (!wait_event_interruptible_timeout
- (data->waitq, data->data_ready != 0,
- msecs_to_jiffies(INT_TIMEOUT))) {
- dev_dbg(&data->client->dev, "interrupt not received\n");
+ (mag->waitq, mag->data_ready != 0,
+ msecs_to_jiffies(INT_TIMEOUT))) {
+ dev_dbg(&mag->client->dev, "interrupt not received\n");
return -ETIME;
}
-#else
- do {
- msleep(1);
- result = i2c_smbus_read_byte_data(data->client,
- MAG3110_DR_STATUS);
- retry--;
- } while (!(result & MAG3110_STATUS_ZYXDR) && retry > 0);
- /* Clear data_ready flag after data is read out */
- if (retry == 0) {
- printk(KERN_DEBUG "magd wait data ready timeout....\n");
- return -EINVAL;
- }
#endif
-
- data->data_ready = 0;
-
- if (mag3110_read_block_data(data->client,
- MAG3110_OUT_X_MSB, MAG3110_XYZ_DATA_LEN, tmp_data) < 0)
+ mag->data_ready = 0;
+ if (mag3110_read_block_data(client,
+ MAG3110_OUT_X_MSB,
+ MAG3110_XYZ_DATA_LEN, tmp_data) < 0)
return -1;
-
- *x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1];
- *y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3];
- *z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5];
+ pdata->x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1];
+ pdata->y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3];
+ pdata->z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5];
return 0;
}
-static void report_abs(void)
+static void mag3110_report_data(struct mag3110_data *mag)
{
- struct input_dev *idev;
- short x, y, z;
- mutex_lock(&mag3110_lock);
- if (mag3110_read_data(&x, &y, &z) != 0)
+ struct input_polled_dev *poll_dev = mag->poll_dev;
+ struct input_dev *idev = poll_dev->input;
+ struct mag3110_data_axis data;
+
+ mutex_lock(&mag->data_lock);
+ if (mag3110_read_data(mag->client, &data) != 0) {
+ poll_dev->poll_interval = POLL_STOP_TIME;
goto out;
- mag3110_adjust_position(&x, &y, &z);
- idev = mag3110_pdata->poll_dev->input;
- input_report_abs(idev, ABS_X, x);
- input_report_abs(idev, ABS_Y, y);
- input_report_abs(idev, ABS_Z, z);
+ } else if (poll_dev->poll_interval == POLL_STOP_TIME)
+ poll_dev->poll_interval = POLL_INTERVAL;
+ mag3110_data_convert(mag->position, &data);
+ idev = mag->poll_dev->input;
+ input_report_abs(idev, ABS_X, data.x);
+ input_report_abs(idev, ABS_Y, data.y);
+ input_report_abs(idev, ABS_Z, data.z);
input_sync(idev);
out:
- mutex_unlock(&mag3110_lock);
+ mutex_unlock(&mag->data_lock);
}
static void mag3110_dev_poll(struct input_polled_dev *dev)
{
- report_abs();
+ struct mag3110_data * mag = (struct mag3110_data *)dev->private;
+
+ mag3110_report_data(mag);
}
#if MAG3110_IRQ_USED
-static irqreturn_t mag3110_irq_handler(int irq, void *dev_id)
+static irqreturn_t mag3110_irq_handler(int irq, void *dev)
{
- mag3110_pdata->data_ready = 1;
- wake_up_interruptible(&mag3110_pdata->waitq);
+ struct mag3110_data *mag = (struct mag3110_data *)dev;
+
+ mag->data_ready = 1;
+ wake_up_interruptible(&mag->waitq);
return IRQ_HANDLED;
}
#endif
+static int mag3110_reigister_caldata_input(struct mag3110_data *mag)
+{
+ struct input_dev *idev;
+ struct i2c_client *client = mag->client;
+ int ret;
+
+ idev = input_allocate_device();
+ if (!idev) {
+ dev_err(&client->dev, "alloc calibrated data device error\n");
+ return -EINVAL;
+ }
+ idev->name = "eCompass";
+ idev->id.bustype = BUS_I2C;
+ idev->evbit[0] = BIT_MASK(EV_ABS);
+ input_set_abs_params(idev, ABS_X, -15000, 15000, 0, 0);
+ input_set_abs_params(idev, ABS_Y, -15000, 15000, 0, 0);
+ input_set_abs_params(idev, ABS_Z, -15000, 15000, 0, 0);
+ input_set_abs_params(idev, ABS_RX, 0, 36000, 0, 0);
+ input_set_abs_params(idev, ABS_RY, -18000, 18000, 0, 0);
+ input_set_abs_params(idev, ABS_RZ, -9000, 9000, 0, 0);
+ input_set_abs_params(idev, ABS_STATUS, 0, 3, 0, 0);
+ ret = input_register_device(idev);
+ if (ret) {
+ dev_err(&client->dev, "register poll device failed!\n");
+ return -EINVAL;
+ }
+ mag->cal_input = idev;
+ return 0;
+}
+static int mag3110_unreigister_caldata_input(struct mag3110_data *mag)
+{
+ struct input_dev *idev = mag->cal_input;
+
+ if (idev) {
+ input_unregister_device(idev);
+ input_free_device(idev);
+ }
+ mag->cal_input = NULL;
+ return 0;
+}
static ssize_t mag3110_enable_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr, char *buf)
{
- struct i2c_client *client;
+ struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+ struct mag3110_data *mag = (struct mag3110_data *)(poll_dev->private);
+ struct i2c_client *client = mag->client;
int val;
- mutex_lock(&mag3110_lock);
- client = mag3110_pdata->client;
- val = mag3110_read_reg(client, MAG3110_CTRL_REG1) & MAG3110_AC_MASK;
- mutex_unlock(&mag3110_lock);
+ mutex_lock(&mag->data_lock);
+ val = mag3110_read_reg(client, MAG3110_CTRL_REG1);
+ val &= MAG3110_AC_MASK;
+ mutex_unlock(&mag->data_lock);
return sprintf(buf, "%d\n", val);
}
static ssize_t mag3110_enable_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct i2c_client *client;
+ struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+ struct mag3110_data *mag = (struct mag3110_data *)(poll_dev->private);
+ struct i2c_client *client = mag->client;
int reg, ret, enable;
u8 tmp_data[MAG3110_XYZ_DATA_LEN];
enable = simple_strtoul(buf, NULL, 10);
- mutex_lock(&mag3110_lock);
- client = mag3110_pdata->client;
+ mutex_lock(&mag->data_lock);
+ client = mag->client;
reg = mag3110_read_reg(client, MAG3110_CTRL_REG1);
- if (enable && mag3110_pdata->active == MAG_STANDBY) {
+ if (enable && mag->active == MAG_STANDBY) {
reg |= MAG3110_AC_MASK;
ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, reg);
if (!ret)
- mag3110_pdata->active = MAG_ACTIVED;
- } else if (!enable && mag3110_pdata->active == MAG_ACTIVED) {
+ mag->active = MAG_ACTIVED;
+ printk(KERN_INFO"mag3110 set active\n");
+ } else if (!enable && mag->active == MAG_ACTIVED) {
reg &= ~MAG3110_AC_MASK;
ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, reg);
if (!ret)
- mag3110_pdata->active = MAG_STANDBY;
+ mag->active = MAG_STANDBY;
+ printk(KERN_INFO"mag3110 set inactive\n");
+
}
- if (mag3110_pdata->active == MAG_ACTIVED) {
+ if (mag->active == MAG_ACTIVED) {
msleep(100);
/* Read out MSB data to clear interrupt flag automatically */
mag3110_read_block_data(client, MAG3110_OUT_X_MSB,
- MAG3110_XYZ_DATA_LEN, tmp_data);
+ MAG3110_XYZ_DATA_LEN, tmp_data);
}
- mutex_unlock(&mag3110_lock);
+ mutex_unlock(&mag->data_lock);
return count;
}
static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
- mag3110_enable_show, mag3110_enable_store);
+ mag3110_enable_show, mag3110_enable_store);
static ssize_t mag3110_dr_mode_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr, char *buf)
{
- struct i2c_client *client;
+ struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+ struct mag3110_data *mag = (struct mag3110_data *)(poll_dev->private);
+ struct i2c_client *client = mag->client;
int val;
- client = mag3110_pdata->client;
+ client = mag->client;
val = (mag3110_read_reg(client, MAG3110_CTRL_REG1)
- & MAG3110_DR_MODE_MASK) >> MAG3110_DR_MODE_OFFSET;
+ & MAG3110_DR_MODE_MASK) >> MAG3110_DR_MODE_OFFSET;
return sprintf(buf, "%d\n", val);
}
static ssize_t mag3110_dr_mode_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct i2c_client *client ;
+ struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+ struct mag3110_data *mag = (struct mag3110_data *)(poll_dev->private);
+ struct i2c_client *client = mag->client;
int reg, ret;
unsigned long val;
@@ -335,9 +385,9 @@ static ssize_t mag3110_dr_mode_store(struct device *dev,
if ((strict_strtoul(buf, 10, &val) < 0) || (val > 7))
return -EINVAL;
- client = mag3110_pdata->client;
+ client = mag->client;
reg = mag3110_read_reg(client, MAG3110_CTRL_REG1) &
- ~MAG3110_DR_MODE_MASK;
+ ~MAG3110_DR_MODE_MASK;
reg |= (val << MAG3110_DR_MODE_OFFSET);
/* MAG3110_CTRL_REG1 bit 5-7: data rate mode */
ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, reg);
@@ -348,32 +398,36 @@ static ssize_t mag3110_dr_mode_store(struct device *dev,
}
static DEVICE_ATTR(dr_mode, S_IWUSR | S_IRUGO,
- mag3110_dr_mode_show, mag3110_dr_mode_store);
+ mag3110_dr_mode_show, mag3110_dr_mode_store);
static ssize_t mag3110_position_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr, char *buf)
{
+ struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+ struct mag3110_data *mag = (struct mag3110_data *)(poll_dev->private);
int val;
- mutex_lock(&mag3110_lock);
- val = mag3110_pdata->position;
- mutex_unlock(&mag3110_lock);
+
+ mutex_lock(&mag->data_lock);
+ val = mag->position;
+ mutex_unlock(&mag->data_lock);
return sprintf(buf, "%d\n", val);
}
-
static ssize_t mag3110_position_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
+ struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+ struct mag3110_data *mag = (struct mag3110_data *)(poll_dev->private);
int position;
+
position = simple_strtoul(buf, NULL, 10);
- mutex_lock(&mag3110_lock);
- mag3110_pdata->position = position;
- mutex_unlock(&mag3110_lock);
+ mutex_lock(&mag->data_lock);
+ mag->position = position;
+ mutex_unlock(&mag->data_lock);
return count;
}
-
static DEVICE_ATTR(position, S_IWUSR | S_IRUGO,
- mag3110_position_show, mag3110_position_store);
+ mag3110_position_show, mag3110_position_store);
static struct attribute *mag3110_attributes[] = {
&dev_attr_enable.attr,
@@ -383,22 +437,22 @@ static struct attribute *mag3110_attributes[] = {
};
static const struct attribute_group mag3110_attr_group = {
- .attrs = mag3110_attributes,
+ .attrs = mag3110_attributes,
};
static int __devinit mag3110_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+ const struct i2c_device_id *id)
{
struct i2c_adapter *adapter;
struct input_dev *idev;
- struct mag3110_data *data;
+ struct mag3110_data *mag;
int ret = 0;
adapter = to_i2c_adapter(client->dev.parent);
if (!i2c_check_functionality(adapter,
- I2C_FUNC_SMBUS_BYTE |
- I2C_FUNC_SMBUS_BYTE_DATA |
- I2C_FUNC_SMBUS_I2C_BLOCK))
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_I2C_BLOCK))
return -EIO;
dev_info(&client->dev, "check mag3110 chip ID\n");
@@ -406,106 +460,104 @@ static int __devinit mag3110_probe(struct i2c_client *client,
if (MAG3110_ID != ret) {
dev_err(&client->dev,
- "read chip ID 0x%x is not equal to 0x%x!\n",
- ret, MAG3110_ID);
+ "read chip ID 0x%x is not equal to 0x%x!\n", ret,
+ MAG3110_ID);
return -EINVAL;
}
- data = kzalloc(sizeof(struct mag3110_data), GFP_KERNEL);
- if (!data)
+ mag = kzalloc(sizeof(struct mag3110_data), GFP_KERNEL);
+ if (!mag)
return -ENOMEM;
- data->client = client;
- i2c_set_clientdata(client, data);
+ mag->client = client;
+ mag->active = MAG_STANDBY;
+ mag->position = *(int *)client->dev.platform_data;
+ mutex_init(&mag->data_lock);
+ i2c_set_clientdata(client, mag);
/* Init queue */
- init_waitqueue_head(&data->waitq);
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- dev_err(&client->dev, "hwmon register failed!\n");
- ret = PTR_ERR(data->hwmon_dev);
- goto error_rm_dev_sysfs;
- }
+ init_waitqueue_head(&mag->waitq);
/*input poll device register */
- data->poll_dev = input_allocate_polled_device();
- if (!data->poll_dev) {
+ mag->poll_dev = input_allocate_polled_device();
+ if (!mag->poll_dev) {
dev_err(&client->dev, "alloc poll device failed!\n");
ret = -ENOMEM;
- goto error_rm_hwmon_dev;
+ goto error_alloc_poll_dev;
}
- data->poll_dev->poll = mag3110_dev_poll;
- data->poll_dev->poll_interval = POLL_INTERVAL;
- data->poll_dev->poll_interval_min = POLL_INTERVAL_MIN;
- data->poll_dev->poll_interval_max = POLL_INTERVAL_MAX;
- idev = data->poll_dev->input;
- idev->name = MAG3110_DRV_NAME;
+ mag->poll_dev->poll = mag3110_dev_poll;
+ mag->poll_dev->poll_interval = POLL_STOP_TIME;
+ mag->poll_dev->poll_interval_max = POLL_INTERVAL_MAX;
+ mag->poll_dev->poll_interval_min = POLL_INTERVAL_MIN;
+ mag->poll_dev->private = mag;
+ idev = mag->poll_dev->input;
+ idev->name = "FreescaleMagnetometer";
idev->id.bustype = BUS_I2C;
idev->evbit[0] = BIT_MASK(EV_ABS);
- input_set_abs_params(idev, ABS_X, -15000, 15000, 0, 0);
- input_set_abs_params(idev, ABS_Y, -15000, 15000, 0, 0);
- input_set_abs_params(idev, ABS_Z, -15000, 15000, 0, 0);
- ret = input_register_polled_device(data->poll_dev);
+ 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);
+ ret = input_register_polled_device(mag->poll_dev);
if (ret) {
dev_err(&client->dev, "register poll device failed!\n");
- goto error_free_poll_dev;
+ goto error_reg_poll_dev;
+ }
+ ret = mag3110_reigister_caldata_input(mag);
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "failed to register calibrated input device!\n");
+ goto erorr_reg_caldev;
}
-
/*create device group in sysfs as user interface */
ret = sysfs_create_group(&idev->dev.kobj, &mag3110_attr_group);
if (ret) {
- dev_err(&client->dev, "create device file failed!\n");
+ dev_err(&client->dev, "create sysfs device file failed!\n");
ret = -EINVAL;
- goto error_rm_poll_dev;
+ goto error_reg_sysfs;
}
+
/* set irq type to edge rising */
#if MAG3110_IRQ_USED
ret = request_irq(client->irq, mag3110_irq_handler,
- IRQF_TRIGGER_RISING, client->dev.driver->name, idev);
+ IRQF_TRIGGER_RISING, client->dev.driver->name, mag);
if (ret < 0) {
dev_err(&client->dev, "failed to register irq %d!\n",
- client->irq);
- goto error_rm_dev_sysfs;
+ client->irq);
+ goto error_reg_irq;
}
#endif
/* Initialize mag3110 chip */
+
mag3110_init_client(client);
- mag3110_pdata = data;
- mag3110_pdata->active = MAG_STANDBY;
- mag3110_pdata->position = *(int *)client->dev.platform_data;
dev_info(&client->dev, "mag3110 is probed\n");
return 0;
-error_rm_dev_sysfs:
+#if MAG3110_IRQ_USED
+error_reg_irq:
sysfs_remove_group(&client->dev.kobj, &mag3110_attr_group);
-error_rm_poll_dev:
- input_unregister_polled_device(data->poll_dev);
-error_free_poll_dev:
- input_free_polled_device(data->poll_dev);
-error_rm_hwmon_dev:
- hwmon_device_unregister(data->hwmon_dev);
-
- kfree(data);
- mag3110_pdata = NULL;
-
+#endif
+error_reg_sysfs:
+ mag3110_unreigister_caldata_input(mag);
+erorr_reg_caldev:
+ input_unregister_polled_device(mag->poll_dev);
+error_reg_poll_dev:
+ input_free_polled_device(mag->poll_dev);
+error_alloc_poll_dev:
+ kfree(mag);
return ret;
}
static int __devexit mag3110_remove(struct i2c_client *client)
{
- struct mag3110_data *data;
+ struct mag3110_data *mag = i2c_get_clientdata(client);
int ret;
- data = i2c_get_clientdata(client);
-
- data->ctl_reg1 = mag3110_read_reg(client, MAG3110_CTRL_REG1);
+ mag->ctl_reg1 = mag3110_read_reg(client, MAG3110_CTRL_REG1);
ret = mag3110_write_reg(client, MAG3110_CTRL_REG1,
- data->ctl_reg1 & ~MAG3110_AC_MASK);
-
- free_irq(client->irq, data);
- input_unregister_polled_device(data->poll_dev);
- input_free_polled_device(data->poll_dev);
- hwmon_device_unregister(data->hwmon_dev);
+ mag->ctl_reg1 & ~MAG3110_AC_MASK);
+ free_irq(client->irq, mag);
+ input_unregister_polled_device(mag->poll_dev);
+ input_free_polled_device(mag->poll_dev);
sysfs_remove_group(&client->dev.kobj, &mag3110_attr_group);
- kfree(data);
- mag3110_pdata = NULL;
+ mag3110_unreigister_caldata_input(mag);
+ kfree(mag);
+ mag = NULL;
return ret;
}
@@ -513,12 +565,13 @@ static int __devexit mag3110_remove(struct i2c_client *client)
#ifdef CONFIG_PM
static int mag3110_suspend(struct i2c_client *client, pm_message_t mesg)
{
+ struct mag3110_data *mag = i2c_get_clientdata(client);
int ret = 0;
- struct mag3110_data *data = i2c_get_clientdata(client);
- if (data->active == MAG_ACTIVED) {
- data->ctl_reg1 = mag3110_read_reg(client, MAG3110_CTRL_REG1);
+
+ if (mag->active == MAG_ACTIVED) {
+ mag->ctl_reg1 = mag3110_read_reg(client, MAG3110_CTRL_REG1);
ret = mag3110_write_reg(client, MAG3110_CTRL_REG1,
- data->ctl_reg1 & ~MAG3110_AC_MASK);
+ mag->ctl_reg1 & ~MAG3110_AC_MASK);
}
return ret;
}
@@ -527,15 +580,17 @@ static int mag3110_resume(struct i2c_client *client)
{
int ret = 0;
u8 tmp_data[MAG3110_XYZ_DATA_LEN];
- struct mag3110_data *data = i2c_get_clientdata(client);
- if (data->active == MAG_ACTIVED) {
+ struct mag3110_data *mag = i2c_get_clientdata(client);
+
+ if (mag->active == MAG_ACTIVED) {
ret = mag3110_write_reg(client, MAG3110_CTRL_REG1,
- data->ctl_reg1);
+ mag->ctl_reg1);
- if (data->ctl_reg1 & MAG3110_AC_MASK) {
- /* Read out MSB data to clear interrupt automatically*/
+ if (mag->ctl_reg1 & MAG3110_AC_MASK) {
+ /* Read out MSB data to clear */
+ /* interrupt flag automatically */
mag3110_read_block_data(client, MAG3110_OUT_X_MSB,
- MAG3110_XYZ_DATA_LEN, tmp_data);
+ MAG3110_XYZ_DATA_LEN, tmp_data);
}
}
return ret;
@@ -544,22 +599,22 @@ static int mag3110_resume(struct i2c_client *client)
#else
#define mag3110_suspend NULL
#define mag3110_resume NULL
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM */
static const struct i2c_device_id mag3110_id[] = {
- {MAG3110_DRV_NAME, 0},
+ { MAG3110_DRV_NAME, 0 },
{}
};
MODULE_DEVICE_TABLE(i2c, mag3110_id);
static struct i2c_driver mag3110_driver = {
- .driver = {.name = MAG3110_DRV_NAME,
- .owner = THIS_MODULE,},
- .suspend = mag3110_suspend,
- .resume = mag3110_resume,
- .probe = mag3110_probe,
- .remove = __devexit_p(mag3110_remove),
- .id_table = mag3110_id,
+ .driver = { .name = MAG3110_DRV_NAME,
+ .owner = THIS_MODULE, },
+ .suspend = mag3110_suspend,
+ .resume = mag3110_resume,
+ .probe = mag3110_probe,
+ .remove = __devexit_p(mag3110_remove),
+ .id_table = mag3110_id,
};
static int __init mag3110_init(void)
diff --git a/drivers/hwmon/mma8x5x.c b/drivers/hwmon/mma8x5x.c
new file mode 100644
index 000000000000..ba00053ac447
--- /dev/null
+++ b/drivers/hwmon/mma8x5x.c
@@ -0,0 +1,561 @@
+/*
+ * mma8x5x.c - Linux kernel modules for 3-Axis Orientation/Motion
+ * Detection Sensor MMA8451/MMA8452/MMA8453/MMA8652/MMA8653
+ *
+ * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/pm.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/input-polldev.h>
+
+
+#define MMA8X5X_I2C_ADDR 0x1D
+#define MMA8451_ID 0x1A
+#define MMA8452_ID 0x2A
+#define MMA8453_ID 0x3A
+#define MMA8652_ID 0x4A
+#define MMA8653_ID 0x5A
+
+
+#define POLL_INTERVAL_MIN 1
+#define POLL_INTERVAL_MAX 500
+#define POLL_INTERVAL 100 /* msecs */
+
+/* if sensor is standby ,set POLL_STOP_TIME to slow down the poll */
+#define POLL_STOP_TIME 200
+#define INPUT_FUZZ 32
+#define INPUT_FLAT 32
+#define MODE_CHANGE_DELAY_MS 100
+
+#define MMA8X5X_STATUS_ZYXDR 0x08
+#define MMA8X5X_BUF_SIZE 6
+
+/* register enum for mma8x5x registers */
+enum {
+ MMA8X5X_STATUS = 0x00,
+ MMA8X5X_OUT_X_MSB,
+ MMA8X5X_OUT_X_LSB,
+ MMA8X5X_OUT_Y_MSB,
+ MMA8X5X_OUT_Y_LSB,
+ MMA8X5X_OUT_Z_MSB,
+ MMA8X5X_OUT_Z_LSB,
+
+ MMA8X5X_F_SETUP = 0x09,
+ MMA8X5X_TRIG_CFG,
+ MMA8X5X_SYSMOD,
+ MMA8X5X_INT_SOURCE,
+ MMA8X5X_WHO_AM_I,
+ MMA8X5X_XYZ_DATA_CFG,
+ MMA8X5X_HP_FILTER_CUTOFF,
+
+ MMA8X5X_PL_STATUS,
+ MMA8X5X_PL_CFG,
+ MMA8X5X_PL_COUNT,
+ MMA8X5X_PL_BF_ZCOMP,
+ MMA8X5X_P_L_THS_REG,
+
+ MMA8X5X_FF_MT_CFG,
+ MMA8X5X_FF_MT_SRC,
+ MMA8X5X_FF_MT_THS,
+ MMA8X5X_FF_MT_COUNT,
+
+ MMA8X5X_TRANSIENT_CFG = 0x1D,
+ MMA8X5X_TRANSIENT_SRC,
+ MMA8X5X_TRANSIENT_THS,
+ MMA8X5X_TRANSIENT_COUNT,
+
+ MMA8X5X_PULSE_CFG,
+ MMA8X5X_PULSE_SRC,
+ MMA8X5X_PULSE_THSX,
+ MMA8X5X_PULSE_THSY,
+ MMA8X5X_PULSE_THSZ,
+ MMA8X5X_PULSE_TMLT,
+ MMA8X5X_PULSE_LTCY,
+ MMA8X5X_PULSE_WIND,
+
+ MMA8X5X_ASLP_COUNT,
+ MMA8X5X_CTRL_REG1,
+ MMA8X5X_CTRL_REG2,
+ MMA8X5X_CTRL_REG3,
+ MMA8X5X_CTRL_REG4,
+ MMA8X5X_CTRL_REG5,
+
+ MMA8X5X_OFF_X,
+ MMA8X5X_OFF_Y,
+ MMA8X5X_OFF_Z,
+
+ MMA8X5X_REG_END,
+};
+
+/* The sensitivity is represented in counts/g. In 2g mode the
+ sensitivity is 1024 counts/g. In 4g mode the sensitivity is 512
+ counts/g and in 8g mode the sensitivity is 256 counts/g.
+ */
+enum {
+ MODE_2G = 0,
+ MODE_4G,
+ MODE_8G,
+};
+
+enum {
+ MMA_STANDBY = 0,
+ MMA_ACTIVED,
+};
+struct mma8x5x_data_axis {
+ short x;
+ short y;
+ short z;
+};
+struct mma8x5x_data {
+ struct i2c_client *client;
+ struct input_polled_dev *poll_dev;
+ struct mutex data_lock;
+ int active;
+ int position;
+ u8 chip_id;
+ int mode;
+};
+/* Addresses scanned */
+static const unsigned short normal_i2c[] = { 0x1c, 0x1d, I2C_CLIENT_END };
+
+static int mma8x5x_chip_id[] = {
+ MMA8451_ID,
+ MMA8452_ID,
+ MMA8453_ID,
+ MMA8652_ID,
+ MMA8653_ID,
+};
+static char *mma8x5x_names[] = {
+ "mma8451",
+ "mma8452",
+ "mma8453",
+ "mma8652",
+ "mma8653",
+};
+static int mma8x5x_position_setting[8][3][3] = {
+ { { 0, -1, 0 }, { 1, 0, 0 }, { 0, 0, 1 } },
+ { { -1, 0, 0 }, { 0, -1, 0 }, { 0, 0, 1 } },
+ { { 0, 1, 0 }, { -1, 0, 0 }, { 0, 0, 1 } },
+ { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } },
+
+ { { 0, -1, 0 }, { -1, 0, 0 }, { 0, 0, -1 } },
+ { { -1, 0, 0 }, { 0, 1, 0 }, { 0, 0, -1 } },
+ { { 0, 1, 0 }, { 1, 0, 0 }, { 0, 0, -1 } },
+ { { 1, 0, 0 }, { 0, -1, 0 }, { 0, 0, -1 } },
+};
+
+static int mma8x5x_data_convert(struct mma8x5x_data *pdata,
+ struct mma8x5x_data_axis *axis_data)
+{
+ short rawdata[3], data[3];
+ int i, j;
+ int position = pdata->position;
+
+ if (position < 0 || position > 7)
+ position = 0;
+ rawdata[0] = axis_data->x;
+ rawdata[1] = axis_data->y;
+ rawdata[2] = axis_data->z;
+ 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];
+ }
+ axis_data->x = data[0];
+ axis_data->y = data[1];
+ axis_data->z = data[2];
+ return 0;
+}
+static int mma8x5x_check_id(int id)
+{
+ int i = 0;
+
+ for (i = 0; i < sizeof(mma8x5x_chip_id) / sizeof(mma8x5x_chip_id[0]); i++)
+ if (id == mma8x5x_chip_id[i])
+ return 1;
+ return 0;
+}
+static char *mma8x5x_id2name(u8 id)
+{
+ return mma8x5x_names[(id >> 4) - 1];
+}
+static int mma8x5x_device_init(struct i2c_client *client)
+{
+ int result;
+ struct mma8x5x_data *pdata = i2c_get_clientdata(client);
+
+ result = i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, 0);
+ if (result < 0)
+ goto out;
+
+ result = i2c_smbus_write_byte_data(client, MMA8X5X_XYZ_DATA_CFG,
+ pdata->mode);
+ if (result < 0)
+ goto out;
+ pdata->active = MMA_STANDBY;
+ msleep(MODE_CHANGE_DELAY_MS);
+ return 0;
+out:
+ dev_err(&client->dev, "error when init mma8x5x:(%d)", result);
+ return result;
+}
+static int mma8x5x_device_stop(struct i2c_client *client)
+{
+ u8 val;
+
+ val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
+ i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, val & 0xfe);
+ return 0;
+}
+
+static int mma8x5x_read_data(struct i2c_client *client,
+ struct mma8x5x_data_axis *data)
+{
+ u8 tmp_data[MMA8X5X_BUF_SIZE];
+ int ret;
+
+ ret = i2c_smbus_read_i2c_block_data(client,
+ MMA8X5X_OUT_X_MSB,
+ MMA8X5X_BUF_SIZE, tmp_data);
+ if (ret < MMA8X5X_BUF_SIZE) {
+ dev_err(&client->dev, "i2c block read failed\n");
+ return -EIO;
+ }
+ data->x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1];
+ data->y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3];
+ data->z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5];
+ return 0;
+}
+
+static void mma8x5x_report_data(struct mma8x5x_data *pdata)
+{
+ struct input_polled_dev *poll_dev = pdata->poll_dev;
+ struct mma8x5x_data_axis data;
+
+ mutex_lock(&pdata->data_lock);
+ if (pdata->active == MMA_STANDBY) {
+ /* if standby ,set as 10s to slow the poll */
+ poll_dev->poll_interval = POLL_STOP_TIME;
+ goto out;
+ } else if (poll_dev->poll_interval == POLL_STOP_TIME)
+ poll_dev->poll_interval = POLL_INTERVAL;
+ if (mma8x5x_read_data(pdata->client, &data) != 0)
+ goto out;
+ mma8x5x_data_convert(pdata, &data);
+ input_report_abs(poll_dev->input, ABS_X, data.x);
+ input_report_abs(poll_dev->input, ABS_Y, data.y);
+ input_report_abs(poll_dev->input, ABS_Z, data.z);
+ input_sync(poll_dev->input);
+out:
+ mutex_unlock(&pdata->data_lock);
+}
+
+static void mma8x5x_dev_poll(struct input_polled_dev *dev)
+{
+ struct mma8x5x_data *pdata = (struct mma8x5x_data *)dev->private;
+
+ mma8x5x_report_data(pdata);
+}
+
+static ssize_t mma8x5x_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+ struct mma8x5x_data *pdata = (struct mma8x5x_data *)(poll_dev->private);
+ struct i2c_client *client = pdata->client;
+ u8 val;
+ int enable;
+
+ mutex_lock(&pdata->data_lock);
+ val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
+ if ((val & 0x01) && pdata->active == MMA_ACTIVED)
+ enable = 1;
+ else
+ enable = 0;
+ mutex_unlock(&pdata->data_lock);
+ return sprintf(buf, "%d\n", enable);
+}
+
+static ssize_t mma8x5x_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+ struct mma8x5x_data *pdata = (struct mma8x5x_data *)(poll_dev->private);
+ struct i2c_client *client = pdata->client;
+ int ret;
+ unsigned long enable;
+ u8 val = 0;
+
+ enable = simple_strtoul(buf, NULL, 10);
+ 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);
+ if (!ret) {
+ pdata->active = MMA_ACTIVED;
+ printk(KERN_INFO"mma enable setting active \n");
+ }
+ } 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);
+ if (!ret) {
+ pdata->active = MMA_STANDBY;
+ printk(KERN_INFO"mma enable setting inactive \n");
+ }
+ }
+ mutex_unlock(&pdata->data_lock);
+ return count;
+}
+static ssize_t mma8x5x_position_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+ struct mma8x5x_data *pdata = (struct mma8x5x_data *)(poll_dev->private);
+ int position = 0;
+
+ mutex_lock(&pdata->data_lock);
+ position = pdata->position;
+ mutex_unlock(&pdata->data_lock);
+ return sprintf(buf, "%d\n", position);
+}
+
+static ssize_t mma8x5x_position_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+ struct mma8x5x_data *pdata = (struct mma8x5x_data *)(poll_dev->private);
+ int position;
+
+ position = simple_strtoul(buf, NULL, 10);
+ mutex_lock(&pdata->data_lock);
+ pdata->position = position;
+ mutex_unlock(&pdata->data_lock);
+ return count;
+}
+
+static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
+ mma8x5x_enable_show, mma8x5x_enable_store);
+static DEVICE_ATTR(position, S_IWUSR | S_IRUGO,
+ mma8x5x_position_show, mma8x5x_position_store);
+
+static struct attribute *mma8x5x_attributes[] = {
+ &dev_attr_enable.attr,
+ &dev_attr_position.attr,
+ NULL
+};
+
+static const struct attribute_group mma8x5x_attr_group = {
+ .attrs = mma8x5x_attributes,
+};
+static int mma8x5x_detect(struct i2c_client *client,
+ struct i2c_board_info *info)
+{
+ struct i2c_adapter *adapter = client->adapter;
+ int chip_id;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA))
+ return -ENODEV;
+ 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",
+ mma8x5x_id2name(chip_id), client->addr);
+ strlcpy(info->type, "mma8x5x", I2C_NAME_SIZE);
+ return 0;
+}
+static int __devinit mma8x5x_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int result, chip_id;
+ struct input_dev *idev;
+ struct mma8x5x_data *pdata;
+ struct i2c_adapter *adapter;
+ struct input_polled_dev *poll_dev;
+
+ adapter = to_i2c_adapter(client->dev.parent);
+ result = i2c_check_functionality(adapter,
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA);
+ if (!result)
+ goto err_out;
+
+ chip_id = i2c_smbus_read_byte_data(client, MMA8X5X_WHO_AM_I);
+
+ if (!mma8x5x_check_id(chip_id)) {
+ dev_err(&client->dev,
+ "read chip ID 0x%x is not equal to 0x%x,0x%x,0x%x,0x%x,0x%x!\n",
+ chip_id, MMA8451_ID, MMA8452_ID,
+ MMA8453_ID, MMA8652_ID, MMA8653_ID);
+ result = -EINVAL;
+ goto err_out;
+ }
+ pdata = kzalloc(sizeof(struct mma8x5x_data), GFP_KERNEL);
+ if (!pdata) {
+ result = -ENOMEM;
+ dev_err(&client->dev, "alloc data memory error!\n");
+ goto err_out;
+ }
+ /* Initialize the MMA8X5X chip */
+ pdata->client = client;
+ pdata->chip_id = chip_id;
+ pdata->mode = MODE_2G;
+ pdata->position = *(int *)client->dev.platform_data;
+ mutex_init(&pdata->data_lock);
+ i2c_set_clientdata(client, pdata);
+ mma8x5x_device_init(client);
+ poll_dev = input_allocate_polled_device();
+ if (!poll_dev) {
+ result = -ENOMEM;
+ dev_err(&client->dev, "alloc poll device failed!\n");
+ goto err_alloc_poll_device;
+ }
+ poll_dev->poll = mma8x5x_dev_poll;
+ poll_dev->poll_interval = POLL_STOP_TIME;
+ poll_dev->poll_interval_min = POLL_INTERVAL_MIN;
+ poll_dev->poll_interval_max = POLL_INTERVAL_MAX;
+ poll_dev->private = pdata;
+ idev = poll_dev->input;
+ idev->name = "FreescaleAccelerometer";
+ idev->uniq = mma8x5x_id2name(pdata->chip_id);
+ idev->id.bustype = BUS_I2C;
+ idev->evbit[0] = BIT_MASK(EV_ABS);
+ 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);
+ pdata->poll_dev = poll_dev;
+ result = input_register_polled_device(pdata->poll_dev);
+ if (result) {
+ dev_err(&client->dev, "register poll device failed!\n");
+ goto err_register_polled_device;
+ }
+ result = sysfs_create_group(&idev->dev.kobj, &mma8x5x_attr_group);
+ if (result) {
+ dev_err(&client->dev, "create device file failed!\n");
+ result = -EINVAL;
+ goto err_create_sysfs;
+ }
+ printk(KERN_INFO"mma8x5x device driver probe successfully\n");
+ return 0;
+err_create_sysfs:
+ input_unregister_polled_device(pdata->poll_dev);
+err_register_polled_device:
+ input_free_polled_device(poll_dev);
+err_alloc_poll_device:
+ kfree(pdata);
+err_out:
+ return result;
+}
+static int __devexit mma8x5x_remove(struct i2c_client *client)
+{
+ struct mma8x5x_data *pdata = i2c_get_clientdata(client);
+ struct input_polled_dev *poll_dev = pdata->poll_dev;
+
+ mma8x5x_device_stop(client);
+ if (pdata) {
+ input_unregister_polled_device(poll_dev);
+ input_free_polled_device(poll_dev);
+ kfree(pdata);
+ }
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+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->active == MMA_ACTIVED)
+ mma8x5x_device_stop(client);
+ return 0;
+}
+
+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->active == MMA_ACTIVED) {
+ val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
+ i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, val | 0x01);
+ }
+ return 0;
+
+}
+#endif
+
+static const struct i2c_device_id mma8x5x_id[] = {
+ { "mma8x5x", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, mma8x5x_id);
+
+static SIMPLE_DEV_PM_OPS(mma8x5x_pm_ops, mma8x5x_suspend, mma8x5x_resume);
+static struct i2c_driver mma8x5x_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "mma8x5x",
+ .owner = THIS_MODULE,
+ .pm = &mma8x5x_pm_ops,
+ },
+ .probe = mma8x5x_probe,
+ .remove = __devexit_p(mma8x5x_remove),
+ .id_table = mma8x5x_id,
+ .detect = mma8x5x_detect,
+ .address_list = normal_i2c,
+};
+
+static int __init mma8x5x_init(void)
+{
+ /* register driver */
+ int res;
+
+ res = i2c_add_driver(&mma8x5x_driver);
+ if (res < 0) {
+ printk(KERN_INFO "add mma8x5x i2c driver failed\n");
+ return -ENODEV;
+ }
+ return res;
+}
+
+static void __exit mma8x5x_exit(void)
+{
+ i2c_del_driver(&mma8x5x_driver);
+}
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MMA8X5X 3-Axis Orientation/Motion Detection Sensor driver");
+MODULE_LICENSE("GPL");
+
+module_init(mma8x5x_init);
+module_exit(mma8x5x_exit);
diff --git a/drivers/hwmon/mxc_mma8450.c b/drivers/hwmon/mxc_mma8450.c
deleted file mode 100644
index 214df139a866..000000000000
--- a/drivers/hwmon/mxc_mma8450.c
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * mma8450.c - Linux kernel modules for 3-Axis Orientation/Motion
- * Detection Sensor
- *
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/hwmon-sysfs.h>
-#include <linux/err.h>
-#include <linux/hwmon.h>
-#include <linux/input-polldev.h>
-
-/*
- * Defines
- */
-#define assert(expr)\
- if (!(expr)) {\
- printk(KERN_ERR "Assertion failed! %s,%d,%s,%s\n",\
- __FILE__, __LINE__, __func__, #expr);\
- }
-
-#define MMA8450_DRV_NAME "mma8450"
-#define MMA8450_I2C_ADDR 0x1C
-#define MMA8450_ID 0xC6
-#define MMA8450_STATUS 0x00
-
-#define MODE_CHANGE_DELAY_MS 100
-#define POLL_INTERVAL_MAX 500
-#define POLL_INTERVAL 100
-#define INPUT_FUZZ 32
-#define INPUT_FLAT 32
-
-/* register enum for mma8450 registers */
-enum {
- MMA8450_STATUS1 = 0x00,
- MMA8450_OUT_X8,
- MMA8450_OUT_Y8,
- MMA8450_OUT_Z8,
-
- MMA8450_STATUS2,
- MMA8450_OUT_X_LSB,
- MMA8450_OUT_X_MSB,
- MMA8450_OUT_Y_LSB,
- MMA8450_OUT_Y_MSB,
- MMA8450_OUT_Z_LSB,
- MMA8450_OUT_Z_MSB,
-
- MMA8450_STATUS3,
- MMA8450_OUT_X_DELTA,
- MMA8450_OUT_Y_DELTA,
- MMA8450_OUT_Z_DELTA,
-
- MMA8450_WHO_AM_I,
-
- MMA8450_F_STATUS,
- MMA8450_F_8DATA,
- MMA8450_F_12DATA,
- MMA8450_F_SETUP,
-
- MMA8450_SYSMOD,
- MMA8450_INT_SOURCE,
- MMA8450_XYZ_DATA_CFG,
- MMA8450_HP_FILTER_CUTOFF,
-
- MMA8450_PL_STATUS,
- MMA8450_PL_PRE_STATUS,
- MMA8450_PL_CFG,
- MMA8450_PL_COUNT,
- MMA8450_PL_BF_ZCOMP,
- MMA8450_PL_P_L_THS_REG1,
- MMA8450_PL_P_L_THS_REG2,
- MMA8450_PL_P_L_THS_REG3,
- MMA8450_PL_L_P_THS_REG1,
- MMA8450_PL_L_P_THS_REG2,
- MMA8450_PL_L_P_THS_REG3,
-
- MMA8450_FF_MT_CFG_1,
- MMA8450_FF_MT_SRC_1,
- MMA8450_FF_MT_THS_1,
- MMA8450_FF_MT_COUNT_1,
- MMA8450_FF_MT_CFG_2,
- MMA8450_FF_MT_SRC_2,
- MMA8450_FF_MT_THS_2,
- MMA8450_FF_MT_COUNT_2,
-
- MMA8450_TRANSIENT_CFG,
- MMA8450_TRANSIENT_SRC,
- MMA8450_TRANSIENT_THS,
- MMA8450_TRANSIENT_COUNT,
-
- MMA8450_PULSE_CFG,
- MMA8450_PULSE_SRC,
- MMA8450_PULSE_THSX,
- MMA8450_PULSE_THSY,
- MMA8450_PULSE_THSZ,
- MMA8450_PULSE_TMLT,
- MMA8450_PULSE_LTCY,
- MMA8450_PULSE_WIND,
-
- MMA8450_ASLP_COUNT,
- MMA8450_CTRL_REG1,
- MMA8450_CTRL_REG2,
- MMA8450_CTRL_REG3,
- MMA8450_CTRL_REG4,
- MMA8450_CTRL_REG5,
-
- MMA8450_OFF_X,
- MMA8450_OFF_Y,
- MMA8450_OFF_Z,
-
- MMA8450_REG_END,
-};
-
-enum {
- MODE_STANDBY,
- MODE_2G,
- MODE_4G,
- MODE_8G,
-};
-
-/* mma8450 status */
-struct mma8450_status {
- u8 mode;
- u8 ctl_reg2;
- u8 ctl_reg1;
-};
-
-static struct mma8450_status mma_status = {
- .mode = 0,
- .ctl_reg2 = 0,
- .ctl_reg1 = 0
-};
-
-static struct device *hwmon_dev;
-static struct i2c_client *mma8450_i2c_client;
-static struct input_polled_dev *mma8450_idev;
-
-/*
- * Initialization function
- */
-static int mma8450_init_client(struct i2c_client *client)
-{
- int result;
-
- mma_status.mode = MODE_2G;
-
- result = i2c_smbus_write_byte_data(client, MMA8450_XYZ_DATA_CFG, 0x07);
- assert(result == 0);
-
- result =
- i2c_smbus_write_byte_data(client, MMA8450_CTRL_REG1,
- mma_status.mode);
- assert(result == 0);
-
- mdelay(MODE_CHANGE_DELAY_MS);
-
- return result;
-}
-
-/*
- * read sensor data from mma8450
- */
-static int mma8450_read_data(short *x, short *y, short *z)
-{
- u8 tmp_data[7];
-
- if (i2c_smbus_read_i2c_block_data
- (mma8450_i2c_client, MMA8450_OUT_X_LSB, 7, tmp_data) < 7) {
- dev_err(&mma8450_i2c_client->dev, "i2c block read failed\n");
- return -3;
- }
-
- *x = ((tmp_data[1] << 8) & 0xff00) | ((tmp_data[0] << 4) & 0x00f0);
- *y = ((tmp_data[3] << 8) & 0xff00) | ((tmp_data[2] << 4) & 0x00f0);
- *z = ((tmp_data[5] << 8) & 0xff00) | ((tmp_data[4] << 4) & 0x00f0);
-
- *x = (short)(*x) >> 4;
- *y = (short)(*y) >> 4;
- *z = (short)(*z) >> 4;
-
- if (mma_status.mode == MODE_4G) {
- (*x) = (*x) << 1;
- (*y) = (*y) << 1;
- (*z) = (*z) << 1;
- } else if (mma_status.mode == MODE_8G) {
- (*x) = (*x) << 2;
- (*y) = (*y) << 2;
- (*z) = (*z) << 2;
- }
-
- return 0;
-}
-
-static void report_abs(void)
-{
- short x, y, z;
- int result;
-
- do {
- result =
- i2c_smbus_read_byte_data(mma8450_i2c_client,
- MMA8450_STATUS3);
- } while (!(result & 0x08)); /* wait for new data */
-
- if (mma8450_read_data(&x, &y, &z) != 0)
- return;
-
- input_report_abs(mma8450_idev->input, ABS_X, x);
- input_report_abs(mma8450_idev->input, ABS_Y, y);
- input_report_abs(mma8450_idev->input, ABS_Z, z);
- input_sync(mma8450_idev->input);
-}
-
-static void mma8450_dev_poll(struct input_polled_dev *dev)
-{
- report_abs();
-}
-
-/*
- * I2C init/probing/exit functions
- */
-static int __devinit mma8450_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- int result;
- struct i2c_adapter *adapter;
- struct input_dev *idev;
-
- mma8450_i2c_client = client;
- adapter = to_i2c_adapter(client->dev.parent);
-
- result = i2c_check_functionality(adapter,
- I2C_FUNC_SMBUS_BYTE |
- I2C_FUNC_SMBUS_BYTE_DATA);
- assert(result);
-
- printk(KERN_INFO "check mma8450 chip ID\n");
- result = i2c_smbus_read_byte_data(client, MMA8450_WHO_AM_I);
-
- if (MMA8450_ID != (result)) {
- dev_err(&client->dev,
- "read chip ID 0x%x is not equal to 0x%x!\n", result,
- MMA8450_ID);
- printk(KERN_INFO "read chip ID failed\n");
- result = -EINVAL;
- goto err_detach_client;
- }
-
- /* Initialize the MMA8450 chip */
- result = mma8450_init_client(client);
- assert(result == 0);
-
- hwmon_dev = hwmon_device_register(&client->dev);
- assert(!(IS_ERR(hwmon_dev)));
-
- dev_info(&client->dev, "build time %s %s\n", __DATE__, __TIME__);
-
- /*input poll device register */
- mma8450_idev = input_allocate_polled_device();
- if (!mma8450_idev) {
- dev_err(&client->dev, "alloc poll device failed!\n");
- result = -ENOMEM;
- return result;
- }
- mma8450_idev->poll = mma8450_dev_poll;
- mma8450_idev->poll_interval = POLL_INTERVAL;
- mma8450_idev->poll_interval_max = POLL_INTERVAL_MAX;
- idev = mma8450_idev->input;
- idev->name = MMA8450_DRV_NAME;
- idev->id.bustype = BUS_I2C;
- idev->evbit[0] = BIT_MASK(EV_ABS);
-
- input_set_abs_params(idev, ABS_X, -8192, 8191, INPUT_FUZZ, INPUT_FLAT);
- input_set_abs_params(idev, ABS_Y, -8192, 8191, INPUT_FUZZ, INPUT_FLAT);
- input_set_abs_params(idev, ABS_Z, -8192, 8191, INPUT_FUZZ, INPUT_FLAT);
- result = input_register_polled_device(mma8450_idev);
- if (result) {
- dev_err(&client->dev, "register poll device failed!\n");
- return result;
- }
-
- return result;
-
-err_detach_client:
- return result;
-}
-
-static int __devexit mma8450_remove(struct i2c_client *client)
-{
- int result;
- mma_status.ctl_reg1 =
- i2c_smbus_read_byte_data(client, MMA8450_CTRL_REG1);
- result =
- i2c_smbus_write_byte_data(client, MMA8450_CTRL_REG1,
- mma_status.ctl_reg1 & 0xFC);
- assert(result == 0);
-
- hwmon_device_unregister(hwmon_dev);
-
- return result;
-}
-
-static int mma8450_suspend(struct i2c_client *client, pm_message_t mesg)
-{
- int result;
- mma_status.ctl_reg1 =
- i2c_smbus_read_byte_data(client, MMA8450_CTRL_REG1);
- result =
- i2c_smbus_write_byte_data(client, MMA8450_CTRL_REG1,
- mma_status.ctl_reg1 & 0xFC);
- assert(result == 0);
- return result;
-}
-
-static int mma8450_resume(struct i2c_client *client)
-{
- int result;
- result =
- i2c_smbus_write_byte_data(client, MMA8450_CTRL_REG1,
- mma_status.mode);
- assert(result == 0);
- return result;
-}
-
-static const struct i2c_device_id mma8450_id[] = {
- {MMA8450_DRV_NAME, 0},
- {},
-};
-
-MODULE_DEVICE_TABLE(i2c, mma8450_id);
-
-static struct i2c_driver mma8450_driver = {
- .driver = {
- .name = MMA8450_DRV_NAME,
- .owner = THIS_MODULE,
- },
- .suspend = mma8450_suspend,
- .resume = mma8450_resume,
- .probe = mma8450_probe,
- .remove = __devexit_p(mma8450_remove),
- .id_table = mma8450_id,
-};
-
-static int __init mma8450_init(void)
-{
- /* register driver */
- int res;
-
- res = i2c_add_driver(&mma8450_driver);
- if (res < 0) {
- printk(KERN_INFO "add mma8450 i2c driver failed\n");
- return -ENODEV;
- }
- printk(KERN_INFO "add mma8450 i2c driver\n");
-
- return res;
-}
-
-static void __exit mma8450_exit(void)
-{
- printk(KERN_INFO "remove mma8450 i2c driver.\n");
- i2c_del_driver(&mma8450_driver);
-}
-
-MODULE_AUTHOR("Freescale Semiconductor, Inc.");
-MODULE_DESCRIPTION("MMA8450 3-Axis Orientation/Motion Detection Sensor driver");
-MODULE_LICENSE("GPL");
-
-module_init(mma8450_init);
-module_exit(mma8450_exit);
diff --git a/drivers/hwmon/mxc_mma8451.c b/drivers/hwmon/mxc_mma8451.c
deleted file mode 100644
index d144cbcbacdb..000000000000
--- a/drivers/hwmon/mxc_mma8451.c
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * mma8451.c - Linux kernel modules for 3-Axis Orientation/Motion
- * Detection Sensor
- *
- * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/pm.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/hwmon-sysfs.h>
-#include <linux/err.h>
-#include <linux/hwmon.h>
-#include <linux/input-polldev.h>
-
-#define MMA8451_DRV_NAME "mma8451"
-#define MMA8451_I2C_ADDR 0x1C
-#define MMA8451_ID 0x1A
-#define MMA8452_ID 0x2A
-#define MMA8453_ID 0x3A
-
-#define POLL_INTERVAL_MIN 20
-#define POLL_INTERVAL_MAX 1000
-#define POLL_INTERVAL 500
-#define INPUT_FUZZ 128
-#define INPUT_FLAT 128
-#define MODE_CHANGE_DELAY_MS 100
-
-#define MMA8451_STATUS_ZYXDR 0x08
-#define MMA8451_BUF_SIZE 6
-
-#define DR_1_25MS 0
-#define DR_2_5MS 1
-#define DR_5_0MS 2
-#define DR_10_0MS 3
-#define DR_20_0MS 4
-#define DR_80_0MS 5
-#define DR_160_0MS 6
-#define DR_640_0MS 7
-
-/* register enum for mma8451 registers */
-enum {
- MMA8451_STATUS = 0x00,
- MMA8451_OUT_X_MSB,
- MMA8451_OUT_X_LSB,
- MMA8451_OUT_Y_MSB,
- MMA8451_OUT_Y_LSB,
- MMA8451_OUT_Z_MSB,
- MMA8451_OUT_Z_LSB,
-
- MMA8451_F_SETUP = 0x09,
- MMA8451_TRIG_CFG,
- MMA8451_SYSMOD,
- MMA8451_INT_SOURCE,
- MMA8451_WHO_AM_I,
- MMA8451_XYZ_DATA_CFG,
- MMA8451_HP_FILTER_CUTOFF,
-
- MMA8451_PL_STATUS,
- MMA8451_PL_CFG,
- MMA8451_PL_COUNT,
- MMA8451_PL_BF_ZCOMP,
- MMA8451_P_L_THS_REG,
-
- MMA8451_FF_MT_CFG,
- MMA8451_FF_MT_SRC,
- MMA8451_FF_MT_THS,
- MMA8451_FF_MT_COUNT,
-
- MMA8451_TRANSIENT_CFG = 0x1D,
- MMA8451_TRANSIENT_SRC,
- MMA8451_TRANSIENT_THS,
- MMA8451_TRANSIENT_COUNT,
-
- MMA8451_PULSE_CFG,
- MMA8451_PULSE_SRC,
- MMA8451_PULSE_THSX,
- MMA8451_PULSE_THSY,
- MMA8451_PULSE_THSZ,
- MMA8451_PULSE_TMLT,
- MMA8451_PULSE_LTCY,
- MMA8451_PULSE_WIND,
-
- MMA8451_ASLP_COUNT,
- MMA8451_CTRL_REG1,
- MMA8451_CTRL_REG2,
- MMA8451_CTRL_REG3,
- MMA8451_CTRL_REG4,
- MMA8451_CTRL_REG5,
-
- MMA8451_OFF_X,
- MMA8451_OFF_Y,
- MMA8451_OFF_Z,
-
- MMA8451_REG_END,
-};
-
-/* The sensitivity is represented in counts/g. In 2g mode the
- sensitivity is 1024 counts/g. In 4g mode the sensitivity is 512
- counts/g and in 8g mode the sensitivity is 256 counts/g.
- */
-enum {
- MODE_2G = 0,
- MODE_4G,
- MODE_8G,
-};
-
-enum {
- MMA_STANDBY = 0,
- MMA_ACTIVED,
-};
-
-/* mma8451 status */
-struct mma8451_status {
- u8 mode;
- u8 ctl_reg1;
- int active;
- int position;
-};
-
-static struct mma8451_status mma_status;
-static struct input_polled_dev *mma8451_idev;
-static struct device *hwmon_dev;
-static struct i2c_client *mma8451_i2c_client;
-
-static int senstive_mode = MODE_2G;
-static int ACCHAL[8][3][3] = {
- {{ 0, -1, 0}, { 1, 0, 0}, {0, 0, 1} },
- {{-1, 0, 0}, { 0, -1, 0}, {0, 0, 1} },
- {{ 0, 1, 0}, {-1, 0, 0}, {0, 0, 1} },
- {{ 1, 0, 0}, { 0, 1, 0}, {0, 0, 1} },
-
- {{ 0, -1, 0}, {-1, 0, 0}, {0, 0, -1} },
- {{-1, 0, 0}, { 0, 1, 0}, {0, 0, -1} },
- {{ 0, 1, 0}, { 1, 0, 0}, {0, 0, -1} },
- {{ 1, 0, 0}, { 0, -1, 0}, {0, 0, -1} },
-};
-
-static DEFINE_MUTEX(mma8451_lock);
-static int mma8451_adjust_position(short *x, short *y, short *z)
-{
- short rawdata[3], data[3];
- int i, j;
- int position = mma_status.position;
- if (position < 0 || position > 7)
- position = 0;
-
- rawdata[0] = *x;
- rawdata[1] = *y;
- rawdata[2] = *z;
-
- for (i = 0; i < 3 ; i++) {
- data[i] = 0;
- for (j = 0; j < 3; j++)
- data[i] += rawdata[j] * ACCHAL[position][i][j];
- }
- *x = data[0];
- *y = data[1];
- *z = data[2];
- return 0;
-}
-
-static int mma8451_change_mode(struct i2c_client *client, int mode)
-{
- int result;
-
- /* Put sensor into Standby Mode by clearing the Active bit */
- mma_status.ctl_reg1 = 0x00;
- result = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1,
- mma_status.ctl_reg1);
- if (result < 0)
- goto out;
-
- /* Write the 2g dynamic range value */
- mma_status.mode = mode;
- result = i2c_smbus_write_byte_data(client, MMA8451_XYZ_DATA_CFG,
- mma_status.mode);
- if (result < 0)
- goto out;
-
- /* Set the Active bit and Data rate in CTRL Reg 1 */
- mma_status.active = MMA_STANDBY;
-
- mdelay(MODE_CHANGE_DELAY_MS);
-
- return 0;
-out:
- dev_err(&client->dev, "error when init mma8451:(%d)", result);
- return result;
-}
-
-static int mma8451_read_data(short *x, short *y, short *z)
-{
- u8 tmp_data[MMA8451_BUF_SIZE];
- int ret;
-
- /* Read 14-bit XYZ results using 6 byte */
- ret = i2c_smbus_read_i2c_block_data(mma8451_i2c_client,
- MMA8451_OUT_X_MSB, MMA8451_BUF_SIZE, tmp_data);
- if (ret < MMA8451_BUF_SIZE) {
- dev_err(&mma8451_i2c_client->dev, "i2c block read failed\n");
- return -EIO;
- }
-
- /* Concatenate the MSB and LSB */
- *x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1];
- *y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3];
- *z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5];
- return 0;
-}
-
-static void report_abs(void)
-{
- short x, y, z;
- int result;
-
- mutex_lock(&mma8451_lock);
- if (mma_status.active == MMA_STANDBY)
- goto out;
- /* Read Status register */
- result = i2c_smbus_read_byte_data(mma8451_i2c_client, MMA8451_STATUS);
-
- /* Check ZYXDR status bit for data available */
- if (!(result & MMA8451_STATUS_ZYXDR)) {
- /* Data not ready */
- goto out;
- }
-
- /* Read XYZ data */
- if (mma8451_read_data(&x, &y, &z) != 0)
- goto out;
- mma8451_adjust_position(&x, &y, &z);
- /* Report XYZ data */
- input_report_abs(mma8451_idev->input, ABS_X, x);
- input_report_abs(mma8451_idev->input, ABS_Y, y);
- input_report_abs(mma8451_idev->input, ABS_Z, z);
- input_sync(mma8451_idev->input);
-out:
- mutex_unlock(&mma8451_lock);
-}
-
-static void mma8451_dev_poll(struct input_polled_dev *dev)
-{
- report_abs();
-}
-
-static ssize_t mma8451_enable_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct i2c_client *client;
- u8 val;
- int enable;
-
- mutex_lock(&mma8451_lock);
- client = mma8451_i2c_client;
- val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1);
- if ((val & 0x01) && mma_status.active == MMA_ACTIVED)
- enable = 1;
- else
- enable = 0;
- mutex_unlock(&mma8451_lock);
- return sprintf(buf, "%d\n", enable);
-}
-
-static ssize_t mma8451_enable_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct i2c_client *client;
- int ret;
- unsigned long enable;
- u8 val = 0;
- enable = simple_strtoul(buf, NULL, 10);
- mutex_lock(&mma8451_lock);
- client = mma8451_i2c_client;
- enable = (enable > 0) ? 1 : 0;
-
- if (enable && mma_status.active == MMA_STANDBY) {
- val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1);
- /* Set the Active bit and Data rate in CTRL Reg 1 */
- val |= (DR_20_0MS<<3);
- val |= 1;
- ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1,
- val);
- if (!ret) {
- mma_status.active = MMA_ACTIVED;
- printk(KERN_DEBUG "mma enable setting active\n");
- }
- } else if (enable == 0 && mma_status.active == MMA_ACTIVED) {
- val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1);
- ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1,
- val & 0xFE);
- if (!ret) {
- mma_status.active = MMA_STANDBY;
- printk(KERN_DEBUG "mma enable setting inactive\n");
- }
- }
- mutex_unlock(&mma8451_lock);
- return count;
-}
-static ssize_t mma8451_position_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- int position = 0;
- mutex_lock(&mma8451_lock);
- position = mma_status.position ;
- mutex_unlock(&mma8451_lock);
- return sprintf(buf, "%d\n", position);
-}
-
-static ssize_t mma8451_position_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- int position;
- position = simple_strtoul(buf, NULL, 10);
- mutex_lock(&mma8451_lock);
- mma_status.position = position;
- mutex_unlock(&mma8451_lock);
- return count;
-}
-
-static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
- mma8451_enable_show, mma8451_enable_store);
-static DEVICE_ATTR(position, S_IWUSR | S_IRUGO,
- mma8451_position_show, mma8451_position_store);
-
-static struct attribute *mma8451_attributes[] = {
- &dev_attr_enable.attr,
- &dev_attr_position.attr,
- NULL
-};
-
-static const struct attribute_group mma8451_attr_group = {
- .attrs = mma8451_attributes,
-};
-
-static int __devinit mma8451_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- int result, client_id;
- struct input_dev *idev;
- struct i2c_adapter *adapter;
-
- mma8451_i2c_client = client;
- adapter = to_i2c_adapter(client->dev.parent);
- result = i2c_check_functionality(adapter,
- I2C_FUNC_SMBUS_BYTE |
- I2C_FUNC_SMBUS_BYTE_DATA);
- if (!result)
- goto err_out;
-
- client_id = i2c_smbus_read_byte_data(client, MMA8451_WHO_AM_I);
-
- if (client_id != MMA8451_ID && client_id != MMA8452_ID &&
- client_id != MMA8453_ID) {
- dev_err(&client->dev,
- "read chip ID 0x%x is not equal to 0x%x \
- or 0x%x!\n", result, MMA8451_ID, MMA8452_ID);
- result = -EINVAL;
- goto err_out;
- }
-
- /* Initialize the MMA8451 chip */
- result = mma8451_change_mode(client, senstive_mode);
- if (result) {
- dev_err(&client->dev,
- "error when init mma8451 chip:(%d)\n", result);
- goto err_out;
- }
-
- hwmon_dev = hwmon_device_register(&client->dev);
- if (!hwmon_dev) {
- result = -ENOMEM;
- dev_err(&client->dev,
- "error when register hwmon device\n");
- goto err_out;
- }
-
- mma8451_idev = input_allocate_polled_device();
- if (!mma8451_idev) {
- result = -ENOMEM;
- dev_err(&client->dev, "alloc poll device failed!\n");
- goto err_alloc_poll_device;
- }
- mma8451_idev->poll = mma8451_dev_poll;
- mma8451_idev->poll_interval = POLL_INTERVAL;
- mma8451_idev->poll_interval_min = POLL_INTERVAL_MIN;
- mma8451_idev->poll_interval_max = POLL_INTERVAL_MAX;
- idev = mma8451_idev->input;
- idev->name = "mma845x";
- idev->id.bustype = BUS_I2C;
- idev->evbit[0] = BIT_MASK(EV_ABS);
-
- input_set_abs_params(idev, ABS_X, -8192, 8191, INPUT_FUZZ, INPUT_FLAT);
- input_set_abs_params(idev, ABS_Y, -8192, 8191, INPUT_FUZZ, INPUT_FLAT);
- input_set_abs_params(idev, ABS_Z, -8192, 8191, INPUT_FUZZ, INPUT_FLAT);
-
- result = input_register_polled_device(mma8451_idev);
- if (result) {
- dev_err(&client->dev, "register poll device failed!\n");
- goto err_register_polled_device;
- }
- result = sysfs_create_group(&idev->dev.kobj, &mma8451_attr_group);
- if (result) {
- dev_err(&client->dev, "create device file failed!\n");
- result = -EINVAL;
- goto err_register_polled_device;
- }
- mma_status.position = *(int *)client->dev.platform_data;
- return 0;
-err_register_polled_device:
- input_free_polled_device(mma8451_idev);
-err_alloc_poll_device:
- hwmon_device_unregister(&client->dev);
-err_out:
- return result;
-}
-
-static int mma8451_stop_chip(struct i2c_client *client)
-{
- int ret = 0;
- if (mma_status.active == MMA_ACTIVED) {
- mma_status.ctl_reg1 = i2c_smbus_read_byte_data(client,
- MMA8451_CTRL_REG1);
- ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1,
- mma_status.ctl_reg1 & 0xFE);
- }
- return ret;
-}
-
-static int __devexit mma8451_remove(struct i2c_client *client)
-{
- int ret;
- ret = mma8451_stop_chip(client);
- hwmon_device_unregister(hwmon_dev);
-
- return ret;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int mma8451_suspend(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
-
- return mma8451_stop_chip(client);
-}
-
-static int mma8451_resume(struct device *dev)
-{
- int ret = 0;
- struct i2c_client *client = to_i2c_client(dev);
- if (mma_status.active == MMA_ACTIVED)
- ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1,
- mma_status.ctl_reg1);
- return ret;
-
-}
-#endif
-
-static const struct i2c_device_id mma8451_id[] = {
- {MMA8451_DRV_NAME, 0},
-};
-MODULE_DEVICE_TABLE(i2c, mma8451_id);
-
-static SIMPLE_DEV_PM_OPS(mma8451_pm_ops, mma8451_suspend, mma8451_resume);
-static struct i2c_driver mma8451_driver = {
- .driver = {
- .name = MMA8451_DRV_NAME,
- .owner = THIS_MODULE,
- .pm = &mma8451_pm_ops,
- },
- .probe = mma8451_probe,
- .remove = __devexit_p(mma8451_remove),
- .id_table = mma8451_id,
-};
-
-static int __init mma8451_init(void)
-{
- /* register driver */
- int res;
-
- res = i2c_add_driver(&mma8451_driver);
- if (res < 0) {
- printk(KERN_INFO "add mma8451 i2c driver failed\n");
- return -ENODEV;
- }
- return res;
-}
-
-static void __exit mma8451_exit(void)
-{
- i2c_del_driver(&mma8451_driver);
-}
-
-MODULE_AUTHOR("Freescale Semiconductor, Inc.");
-MODULE_DESCRIPTION("MMA8451 3-Axis Orientation/Motion Detection Sensor driver");
-MODULE_LICENSE("GPL");
-
-module_init(mma8451_init);
-module_exit(mma8451_exit);