summaryrefslogtreecommitdiff
path: root/drivers/hwmon/mag3110.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/mag3110.c')
-rwxr-xr-xdrivers/hwmon/mag3110.c538
1 files changed, 282 insertions, 256 deletions
diff --git a/drivers/hwmon/mag3110.c b/drivers/hwmon/mag3110.c
index a8d80fa46dfe..a976ab2569c9 100755
--- a/drivers/hwmon/mag3110.c
+++ b/drivers/hwmon/mag3110.c
@@ -31,22 +31,29 @@
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <linux/of.h>
+#include <linux/pm.h>
#include <linux/regulator/consumer.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_IRQ_USED 1
+#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 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_MAX 500
-#define POLL_INTERVAL 100
#define INT_TIMEOUT 1000
-#define DEFAULT_POSITION 2
/* register enum for mag3110 registers */
enum {
MAG3110_DR_STATUS = 0x00,
@@ -74,54 +81,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} },
-
- { {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 } },
+
};
-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,7 +160,8 @@ static int mag3110_write_reg(struct i2c_client *client, u8 reg, char value)
static int mag3110_read_block_data(struct i2c_client *client, u8 reg,
int count, u8 *addr)
{
- if (i2c_smbus_read_i2c_block_data(client, reg, count, addr) < count) {
+ if (i2c_smbus_read_i2c_block_data
+ (client, reg, count, addr) < count) {
dev_err(&client->dev, "i2c block read failed\n");
return -1;
}
@@ -178,113 +193,127 @@ 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)
+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)
- return -EINVAL;
- data = mag3110_pdata;
+ if (!mag || mag->active == MAG_STANDBY)
+ return -EINVAL;
#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)
- return -EINVAL;
#endif
-
- data->data_ready = 0;
-
- while (i2c_smbus_read_byte_data(data->client, MAG3110_DR_STATUS)) {
- if (mag3110_read_block_data(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];
+ mag->data_ready = 0;
+ if (mag3110_read_block_data(client,
+ MAG3110_OUT_X_MSB,
+ MAG3110_XYZ_DATA_LEN, tmp_data) < 0)
+ return -1;
+ 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)
{
- int result;
- u8 tmp_data[MAG3110_XYZ_DATA_LEN];
- result = i2c_smbus_read_byte_data(mag3110_pdata->client,
- MAG3110_DR_STATUS);
- if (!(result & MAG3110_STATUS_ZYXDR))
- return IRQ_NONE;
-
- mag3110_pdata->data_ready = 1;
-
- if (mag3110_pdata->active == MAG_STANDBY)
- /*
- * Since the mode will be changed, sometimes irq will
- * be handled in StandBy mode because of interrupt latency.
- * So just clear the interrutp flag via reading block data.
- */
- mag3110_read_block_data(mag3110_pdata->client,
- MAG3110_OUT_X_MSB,
- MAG3110_XYZ_DATA_LEN, tmp_data);
- else
- 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 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);
}
@@ -292,38 +321,38 @@ static ssize_t mag3110_enable_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client;
- int reg, ret;
- long enable;
+ 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];
- ret = strict_strtol(buf, 10, &enable);
- if (ret) {
- dev_err(dev, "string to long error\n");
- return ret;
- }
-
- mutex_lock(&mag3110_lock);
- client = mag3110_pdata->client;
-
+ enable = simple_strtoul(buf, NULL, 10);
+ 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");
+
}
- /* Read out MSB data to clear interrupt flag */
- msleep(100);
- mag3110_read_block_data(mag3110_pdata->client, MAG3110_OUT_X_MSB,
+ 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);
- mutex_unlock(&mag3110_lock);
+ }
+ mutex_unlock(&mag->data_lock);
return count;
}
@@ -333,10 +362,12 @@ static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
static ssize_t mag3110_dr_mode_show(struct device *dev,
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;
@@ -347,7 +378,9 @@ static ssize_t mag3110_dr_mode_store(struct device *dev,
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;
@@ -355,9 +388,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);
@@ -373,31 +406,29 @@ static DEVICE_ATTR(dr_mode, S_IWUSR | S_IRUGO,
static ssize_t mag3110_position_show(struct device *dev,
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)
{
- long position;
- int ret;
- ret = strict_strtol(buf, 10, &position);
- if (ret) {
- dev_err(dev, "string to long error\n");
- return ret;
- }
+ struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+ struct mag3110_data *mag = (struct mag3110_data *)(poll_dev->private);
+ int position;
- mutex_lock(&mag3110_lock);
- mag3110_pdata->position = (int)position;
- mutex_unlock(&mag3110_lock);
+ position = simple_strtoul(buf, NULL, 10);
+ 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);
@@ -409,7 +440,7 @@ static struct attribute *mag3110_attributes[] = {
};
static const struct attribute_group mag3110_attr_group = {
- .attrs = mag3110_attributes,
+ .attrs = mag3110_attributes,
};
static int mag3110_probe(struct i2c_client *client,
@@ -417,22 +448,17 @@ static int mag3110_probe(struct i2c_client *client,
{
struct i2c_adapter *adapter;
struct input_dev *idev;
- struct mag3110_data *data;
- int ret = 0;
+ struct mag3110_data *mag;
struct regulator *vdd, *vdd_io;
- u32 pos = 0;
- struct device_node *of_node = client->dev.of_node;
-#if MAG3110_IRQ_USED
- struct irq_data *irq_data = irq_get_irq_data(client->irq);
u32 irq_flag;
- bool shared_irq = of_property_read_bool(of_node, "shared-interrupt");
-#endif
- vdd = NULL;
- vdd_io = NULL;
-
+ struct irq_data *irq_data;
+ struct device_node *of_node = client->dev.of_node;
+ bool shared_irq;
+ int ret = 0;
+ u32 pos;
vdd = devm_regulator_get(&client->dev, "vdd");
if (!IS_ERR(vdd)) {
- ret = regulator_enable(vdd);
+ ret = regulator_enable(vdd);
if (ret) {
dev_err(&client->dev, "vdd set voltage error\n");
return ret;
@@ -447,7 +473,6 @@ static int mag3110_probe(struct i2c_client *client,
return ret;
}
}
-
adapter = to_i2c_adapter(client->dev.parent);
if (!i2c_check_functionality(adapter,
I2C_FUNC_SMBUS_BYTE |
@@ -464,137 +489,144 @@ static int mag3110_probe(struct i2c_client *client,
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;
+ ret = of_property_read_u32(of_node, "position", &pos);
+ if (ret)
+ pos = 2;
+ mag->position = (int)pos;
+ 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_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
- irq_flag = irqd_get_trigger_type(irq_data);
- irq_flag |= IRQF_ONESHOT;
- if (shared_irq)
- irq_flag |= IRQF_SHARED;
- ret = request_threaded_irq(client->irq, NULL, mag3110_irq_handler,
- irq_flag, client->dev.driver->name, idev);
- if (ret < 0) {
- dev_err(&client->dev, "failed to register irq %d!\n",
- client->irq);
- goto error_rm_dev_sysfs;
+ shared_irq = of_property_read_bool(of_node, "shared-interrupt");
+ if (client->irq) {
+ irq_data = irq_get_irq_data(client->irq);
+ irq_flag = irqd_get_trigger_type(irq_data);
+ irq_flag |= IRQF_ONESHOT;
+ if (shared_irq)
+ irq_flag |= IRQF_SHARED;
+ ret = request_irq(client->irq, mag3110_irq_handler,
+ irq_flag, client->dev.driver->name, mag);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed to register irq %d!\n",
+ client->irq);
+ goto error_reg_irq;
+ }
}
#endif
/* Initialize mag3110 chip */
+
mag3110_init_client(client);
- mag3110_pdata = data;
- mag3110_pdata->active = MAG_STANDBY;
- ret = of_property_read_u32(of_node, "position", &pos);
- if (ret)
- pos = DEFAULT_POSITION;
- mag3110_pdata->position = (int)pos;
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 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;
}
#ifdef CONFIG_PM
-static int mag3110_suspend(struct i2c_client *client, pm_message_t mesg)
+static int mag3110_suspend(struct device *dev)
{
+ struct i2c_client *client = to_i2c_client(dev);
+ 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;
}
-static int mag3110_resume(struct i2c_client *client)
+static int mag3110_resume(struct device *dev)
{
int ret = 0;
u8 tmp_data[MAG3110_XYZ_DATA_LEN];
- struct mag3110_data *data = i2c_get_clientdata(client);
- if (data->active == MAG_ACTIVED) {
+ struct i2c_client *client = to_i2c_client(dev);
+ 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
- flag 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);
}
@@ -605,36 +637,30 @@ 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 SIMPLE_DEV_PM_OPS(mag3110_pm_ops, mag3110_suspend, mag3110_resume);
static struct i2c_driver mag3110_driver = {
- .driver = {.name = MAG3110_DRV_NAME,
- .owner = THIS_MODULE,},
- .suspend = mag3110_suspend,
- .resume = mag3110_resume,
- .probe = mag3110_probe,
- .remove = mag3110_remove,
- .id_table = mag3110_id,
+ .driver = {
+ .name = MAG3110_DRV_NAME,
+ .owner = THIS_MODULE,
+ .pm = &mag3110_pm_ops,
+ },
+ .probe = mag3110_probe,
+ .remove = mag3110_remove,
+ .id_table = mag3110_id,
};
-static int __init mag3110_init(void)
-{
- return i2c_add_driver(&mag3110_driver);
-}
-static void __exit mag3110_exit(void)
-{
- i2c_del_driver(&mag3110_driver);
-}
+module_i2c_driver(mag3110_driver);
-module_init(mag3110_init);
-module_exit(mag3110_exit);
MODULE_AUTHOR("Freescale Semiconductor, Inc.");
MODULE_DESCRIPTION("Freescale mag3110 3-axis magnetometer driver");
MODULE_LICENSE("GPL");