[go: nahoru, domu]

1631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai/*
2631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai * MPU3050 Tri-axis gyroscope driver
3631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *
4631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai * Copyright (C) 2011 Wistron Co.Ltd
5631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai * Joseph Lai <joseph_lai@wistron.com>
6631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *
7631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai * Trimmed down by Alan Cox <alan@linux.intel.com> to produce this version
8631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *
9631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai * This is a 'lite' version of the driver, while we consider the right way
10631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai * to present the other features to user space. In particular it requires the
11631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai * device has an IRQ, and it only provides an input interface, so is not much
12631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai * use for device orientation. A fuller version is available from the Meego
13631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai * tree.
14631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *
15631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai * This program is based on bma023.c.
16631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *
17631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai * This program is free software; you can redistribute it and/or modify
18631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai * it under the terms of the GNU General Public License as published by
19631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai * the Free Software Foundation; version 2 of the License.
20631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *
21631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai * This program is distributed in the hope that it will be useful, but
22631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai * WITHOUT ANY WARRANTY; without even the implied warranty of
23631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai * General Public License for more details.
25631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *
26631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai * You should have received a copy of the GNU General Public License along
27631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai * with this program; if not, write to the Free Software Foundation, Inc.,
28631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
29631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *
30631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai */
31631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
32631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai#include <linux/module.h>
33631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai#include <linux/interrupt.h>
34631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai#include <linux/platform_device.h>
35631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai#include <linux/mutex.h>
36631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai#include <linux/err.h>
37631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai#include <linux/i2c.h>
38631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai#include <linux/input.h>
39631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai#include <linux/delay.h>
40631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai#include <linux/slab.h>
41631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai#include <linux/pm_runtime.h>
42631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
43631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai#define MPU3050_CHIP_ID		0x69
44631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
45631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai#define MPU3050_AUTO_DELAY	1000
46631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
47631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai#define MPU3050_MIN_VALUE	-32768
48631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai#define MPU3050_MAX_VALUE	32767
49631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
50cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_DEFAULT_POLL_INTERVAL	200
51cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_DEFAULT_FS_RANGE	3
52cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus
53cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus/* Register map */
54cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_CHIP_ID_REG	0x00
55cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_SMPLRT_DIV	0x15
56cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_DLPF_FS_SYNC	0x16
57cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_INT_CFG		0x17
58cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_XOUT_H		0x1D
59cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_PWR_MGM		0x3E
60cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_PWR_MGM_POS	6
61cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus
62cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus/* Register bits */
63cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus
64cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus/* DLPF_FS_SYNC */
65cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_EXT_SYNC_NONE		0x00
66cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_EXT_SYNC_TEMP		0x20
67cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_EXT_SYNC_GYROX		0x40
68cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_EXT_SYNC_GYROY		0x60
69cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_EXT_SYNC_GYROZ		0x80
70cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_EXT_SYNC_ACCELX	0xA0
71cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_EXT_SYNC_ACCELY	0xC0
72cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_EXT_SYNC_ACCELZ	0xE0
73cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_EXT_SYNC_MASK		0xE0
74cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_FS_250DPS		0x00
75cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_FS_500DPS		0x08
76cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_FS_1000DPS		0x10
77cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_FS_2000DPS		0x18
78cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_FS_MASK		0x18
79cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_DLPF_CFG_256HZ_NOLPF2	0x00
80cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_DLPF_CFG_188HZ		0x01
81cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_DLPF_CFG_98HZ		0x02
82cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_DLPF_CFG_42HZ		0x03
83cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_DLPF_CFG_20HZ		0x04
84cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_DLPF_CFG_10HZ		0x05
85cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_DLPF_CFG_5HZ		0x06
86cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_DLPF_CFG_2100HZ_NOLPF	0x07
87cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_DLPF_CFG_MASK		0x07
88cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus/* INT_CFG */
89cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_RAW_RDY_EN		0x01
90cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_MPU_RDY_EN		0x02
91cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_LATCH_INT_EN		0x04
92cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus/* PWR_MGM */
93cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_PWR_MGM_PLL_X		0x01
94cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_PWR_MGM_PLL_Y		0x02
95cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_PWR_MGM_PLL_Z		0x03
96cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_PWR_MGM_CLKSEL		0x07
97cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_PWR_MGM_STBY_ZG	0x08
98cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_PWR_MGM_STBY_YG	0x10
99cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_PWR_MGM_STBY_XG	0x20
100cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_PWR_MGM_SLEEP		0x40
101cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_PWR_MGM_RESET		0x80
102cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus#define MPU3050_PWR_MGM_MASK		0x40
103cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus
104631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Laistruct axis_data {
105631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	s16 x;
106631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	s16 y;
107631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	s16 z;
108631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai};
109631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
110631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Laistruct mpu3050_sensor {
111631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	struct i2c_client *client;
112631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	struct device *dev;
113631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	struct input_dev *idev;
114631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai};
115631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
116631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai/**
117631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	mpu3050_xyz_read_reg	-	read the axes values
118631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	@buffer: provide register addr and get register
119631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	@length: length of register
120631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *
121631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	Reads the register values in one transaction or returns a negative
122631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	error code on failure.
123631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai */
124631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Laistatic int mpu3050_xyz_read_reg(struct i2c_client *client,
125631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai			       u8 *buffer, int length)
126631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai{
127631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	/*
128631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	 * Annoying we can't make this const because the i2c layer doesn't
129631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	 * declare input buffers const.
130631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	 */
131631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	char cmd = MPU3050_XOUT_H;
132631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	struct i2c_msg msg[] = {
133631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		{
134631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai			.addr = client->addr,
135631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai			.flags = 0,
136631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai			.len = 1,
137631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai			.buf = &cmd,
138631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		},
139631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		{
140631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai			.addr = client->addr,
141631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai			.flags = I2C_M_RD,
142631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai			.len = length,
143631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai			.buf = buffer,
144631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		},
145631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	};
146631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
147631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	return i2c_transfer(client->adapter, msg, 2);
148631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai}
149631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
150631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai/**
151631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	mpu3050_read_xyz	-	get co-ordinates from device
152631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	@client: i2c address of sensor
153631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	@coords: co-ordinates to update
154631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *
155631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	Return the converted X Y and Z co-ordinates from the sensor device
156631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai */
157631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Laistatic void mpu3050_read_xyz(struct i2c_client *client,
158631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai			     struct axis_data *coords)
159631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai{
160631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	u16 buffer[3];
161631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
162631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	mpu3050_xyz_read_reg(client, (u8 *)buffer, 6);
163631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	coords->x = be16_to_cpu(buffer[0]);
164631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	coords->y = be16_to_cpu(buffer[1]);
165631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	coords->z = be16_to_cpu(buffer[2]);
166631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	dev_dbg(&client->dev, "%s: x %d, y %d, z %d\n", __func__,
167631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai					coords->x, coords->y, coords->z);
168631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai}
169631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
170631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai/**
171631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	mpu3050_set_power_mode	-	set the power mode
172631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	@client: i2c client for the sensor
173631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	@val: value to switch on/off of power, 1: normal power, 0: low power
174631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *
175631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	Put device to normal-power mode or low-power mode.
176631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai */
177631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Laistatic void mpu3050_set_power_mode(struct i2c_client *client, u8 val)
178631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai{
179631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	u8 value;
180631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
181631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	value = i2c_smbus_read_byte_data(client, MPU3050_PWR_MGM);
182631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	value = (value & ~MPU3050_PWR_MGM_MASK) |
183631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		(((val << MPU3050_PWR_MGM_POS) & MPU3050_PWR_MGM_MASK) ^
184631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		 MPU3050_PWR_MGM_MASK);
185631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	i2c_smbus_write_byte_data(client, MPU3050_PWR_MGM, value);
186631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai}
187631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
188631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai/**
189631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	mpu3050_input_open	-	called on input event open
190631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	@input: input dev of opened device
191631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *
192631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	The input layer calls this function when input event is opened. The
193631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	function will push the device to resume. Then, the device is ready
194631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	to provide data.
195631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai */
196631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Laistatic int mpu3050_input_open(struct input_dev *input)
197631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai{
198631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	struct mpu3050_sensor *sensor = input_get_drvdata(input);
1993b5187248bd07e400af081ad777e9aa1e5519ad7Heikki Krogerus	int error;
200631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
201631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	pm_runtime_get(sensor->dev);
202631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
2033b5187248bd07e400af081ad777e9aa1e5519ad7Heikki Krogerus	/* Enable interrupts */
2043b5187248bd07e400af081ad777e9aa1e5519ad7Heikki Krogerus	error = i2c_smbus_write_byte_data(sensor->client, MPU3050_INT_CFG,
2053b5187248bd07e400af081ad777e9aa1e5519ad7Heikki Krogerus					  MPU3050_LATCH_INT_EN |
2063b5187248bd07e400af081ad777e9aa1e5519ad7Heikki Krogerus					  MPU3050_RAW_RDY_EN |
2073b5187248bd07e400af081ad777e9aa1e5519ad7Heikki Krogerus					  MPU3050_MPU_RDY_EN);
2083b5187248bd07e400af081ad777e9aa1e5519ad7Heikki Krogerus	if (error < 0) {
2093b5187248bd07e400af081ad777e9aa1e5519ad7Heikki Krogerus		pm_runtime_put(sensor->dev);
2103b5187248bd07e400af081ad777e9aa1e5519ad7Heikki Krogerus		return error;
2113b5187248bd07e400af081ad777e9aa1e5519ad7Heikki Krogerus	}
2123b5187248bd07e400af081ad777e9aa1e5519ad7Heikki Krogerus
213631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	return 0;
214631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai}
215631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
216631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai/**
217631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	mpu3050_input_close	-	called on input event close
218631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	@input: input dev of closed device
219631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *
220631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	The input layer calls this function when input event is closed. The
221631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	function will push the device to suspend.
222631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai */
223631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Laistatic void mpu3050_input_close(struct input_dev *input)
224631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai{
225631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	struct mpu3050_sensor *sensor = input_get_drvdata(input);
226631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
227631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	pm_runtime_put(sensor->dev);
228631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai}
229631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
230631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai/**
231631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	mpu3050_interrupt_thread	-	handle an IRQ
232631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	@irq: interrupt numner
233631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	@data: the sensor
234631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *
235631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	Called by the kernel single threaded after an interrupt occurs. Read
236631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	the sensor data and generate an input event for it.
237631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai */
238631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Laistatic irqreturn_t mpu3050_interrupt_thread(int irq, void *data)
239631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai{
240631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	struct mpu3050_sensor *sensor = data;
241631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	struct axis_data axis;
242631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
243631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	mpu3050_read_xyz(sensor->client, &axis);
244631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
245631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	input_report_abs(sensor->idev, ABS_X, axis.x);
246631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	input_report_abs(sensor->idev, ABS_Y, axis.y);
247631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	input_report_abs(sensor->idev, ABS_Z, axis.z);
248631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	input_sync(sensor->idev);
249631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
250631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	return IRQ_HANDLED;
251631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai}
252631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
253631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai/**
254cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus *	mpu3050_hw_init	-	initialize hardware
255cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus *	@sensor: the sensor
256cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus *
257cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus *	Called during device probe; configures the sampling method.
258cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus */
2595298cc4cc753bbe4c530b41341834f6ef3344d0dBill Pembertonstatic int mpu3050_hw_init(struct mpu3050_sensor *sensor)
260cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus{
261cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	struct i2c_client *client = sensor->client;
262cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	int ret;
263cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	u8 reg;
264cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus
265cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	/* Reset */
266cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	ret = i2c_smbus_write_byte_data(client, MPU3050_PWR_MGM,
267cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus					MPU3050_PWR_MGM_RESET);
268cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	if (ret < 0)
269cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus		return ret;
270cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus
271cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	ret = i2c_smbus_read_byte_data(client, MPU3050_PWR_MGM);
272cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	if (ret < 0)
273cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus		return ret;
274cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus
275cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	ret &= ~MPU3050_PWR_MGM_CLKSEL;
276cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	ret |= MPU3050_PWR_MGM_PLL_Z;
277cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	ret = i2c_smbus_write_byte_data(client, MPU3050_PWR_MGM, ret);
278cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	if (ret < 0)
279cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus		return ret;
280cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus
281cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	/* Output frequency divider. The poll interval */
282cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	ret = i2c_smbus_write_byte_data(client, MPU3050_SMPLRT_DIV,
283cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus					MPU3050_DEFAULT_POLL_INTERVAL - 1);
284cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	if (ret < 0)
285cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus		return ret;
286cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus
287cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	/* Set low pass filter and full scale */
288cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	reg = MPU3050_DEFAULT_FS_RANGE;
289cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	reg |= MPU3050_DLPF_CFG_42HZ << 3;
290cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	reg |= MPU3050_EXT_SYNC_NONE << 5;
291cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	ret = i2c_smbus_write_byte_data(client, MPU3050_DLPF_FS_SYNC, reg);
292cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	if (ret < 0)
293cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus		return ret;
294cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus
295cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	return 0;
296cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus}
297cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus
298cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus/**
299631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	mpu3050_probe	-	device detection callback
300631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	@client: i2c client of found device
301631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	@id: id match information
302631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *
303631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	The I2C layer calls us when it believes a sensor is present at this
304631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	address. Probe to see if this is correct and to validate the device.
305631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *
306631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	If present install the relevant sysfs interfaces and input device.
307631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai */
3085298cc4cc753bbe4c530b41341834f6ef3344d0dBill Pembertonstatic int mpu3050_probe(struct i2c_client *client,
309631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai				   const struct i2c_device_id *id)
310631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai{
311631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	struct mpu3050_sensor *sensor;
312631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	struct input_dev *idev;
313631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	int ret;
314631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	int error;
315631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
316631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	sensor = kzalloc(sizeof(struct mpu3050_sensor), GFP_KERNEL);
317631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	idev = input_allocate_device();
318631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	if (!sensor || !idev) {
319631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		dev_err(&client->dev, "failed to allocate driver data\n");
320631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		error = -ENOMEM;
321631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		goto err_free_mem;
322631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	}
323631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
324631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	sensor->client = client;
325631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	sensor->dev = &client->dev;
326631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	sensor->idev = idev;
327631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
328631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	mpu3050_set_power_mode(client, 1);
329631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	msleep(10);
330631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
331631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	ret = i2c_smbus_read_byte_data(client, MPU3050_CHIP_ID_REG);
332631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	if (ret < 0) {
333631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		dev_err(&client->dev, "failed to detect device\n");
334631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		error = -ENXIO;
335631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		goto err_free_mem;
336631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	}
337631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
338631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	if (ret != MPU3050_CHIP_ID) {
339631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		dev_err(&client->dev, "unsupported chip id\n");
340631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		error = -ENXIO;
341631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		goto err_free_mem;
342631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	}
343631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
344631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	idev->name = "MPU3050";
345631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	idev->id.bustype = BUS_I2C;
346631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	idev->dev.parent = &client->dev;
347631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
348631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	idev->open = mpu3050_input_open;
349631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	idev->close = mpu3050_input_close;
350631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
351631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	__set_bit(EV_ABS, idev->evbit);
352631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	input_set_abs_params(idev, ABS_X,
353631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai			     MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0);
354631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	input_set_abs_params(idev, ABS_Y,
355631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai			     MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0);
356631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	input_set_abs_params(idev, ABS_Z,
357631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai			     MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0);
358631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
359631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	input_set_drvdata(idev, sensor);
360631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
361631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	pm_runtime_set_active(&client->dev);
362631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
363cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	error = mpu3050_hw_init(sensor);
364cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus	if (error)
365cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus		goto err_pm_set_suspended;
366cd314fa6375b4de092a5b1de6aa194117523ecbbHeikki Krogerus
367631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	error = request_threaded_irq(client->irq,
368631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai				     NULL, mpu3050_interrupt_thread,
369f31ad406693f114e57ad4651eb17deb68419c7cbStephen Warren				     IRQF_TRIGGER_RISING | IRQF_ONESHOT,
3703b5187248bd07e400af081ad777e9aa1e5519ad7Heikki Krogerus				     "mpu3050", sensor);
371631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	if (error) {
372631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		dev_err(&client->dev,
373631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai			"can't get IRQ %d, error %d\n", client->irq, error);
374631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		goto err_pm_set_suspended;
375631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	}
376631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
377631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	error = input_register_device(idev);
378631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	if (error) {
379631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		dev_err(&client->dev, "failed to register input device\n");
380631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		goto err_free_irq;
381631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	}
382631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
383631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	pm_runtime_enable(&client->dev);
384631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	pm_runtime_set_autosuspend_delay(&client->dev, MPU3050_AUTO_DELAY);
385158baef35129e46e3eb15838092e91b94f0181e0Wei Yongjun	i2c_set_clientdata(client, sensor);
386631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
387631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	return 0;
388631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
389631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Laierr_free_irq:
390631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	free_irq(client->irq, sensor);
391631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Laierr_pm_set_suspended:
392631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	pm_runtime_set_suspended(&client->dev);
393631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Laierr_free_mem:
394d9b830fa444c1f4955d0ee88f5af2aa24d2c7837Axel Lin	input_free_device(idev);
395631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	kfree(sensor);
396631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	return error;
397631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai}
398631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
399631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai/**
400631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	mpu3050_remove	-	remove a sensor
401631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	@client: i2c client of sensor being removed
402631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *
403631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	Our sensor is going away, clean up the resources.
404631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai */
405e2619cf78e19476bfd7ceaefa9eff0847529346eBill Pembertonstatic int mpu3050_remove(struct i2c_client *client)
406631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai{
407631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	struct mpu3050_sensor *sensor = i2c_get_clientdata(client);
408631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
409631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	pm_runtime_disable(&client->dev);
410631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	pm_runtime_set_suspended(&client->dev);
411631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
412631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	free_irq(client->irq, sensor);
413631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	input_unregister_device(sensor->idev);
414631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	kfree(sensor);
415631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
416631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	return 0;
417631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai}
418631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
419631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai#ifdef CONFIG_PM
420631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai/**
421631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	mpu3050_suspend		-	called on device suspend
422631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	@dev: device being suspended
423631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *
424631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	Put the device into sleep mode before we suspend the machine.
425631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai */
426631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Laistatic int mpu3050_suspend(struct device *dev)
427631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai{
428631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	struct i2c_client *client = to_i2c_client(dev);
429631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
430631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	mpu3050_set_power_mode(client, 0);
431631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
432631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	return 0;
433631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai}
434631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
435631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai/**
436631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	mpu3050_resume		-	called on device resume
437631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	@dev: device being resumed
438631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *
439631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai *	Put the device into powered mode on resume.
440631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai */
441631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Laistatic int mpu3050_resume(struct device *dev)
442631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai{
443631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	struct i2c_client *client = to_i2c_client(dev);
444631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
445631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	mpu3050_set_power_mode(client, 1);
446631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	msleep(100);  /* wait for gyro chip resume */
447631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
448631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	return 0;
449631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai}
450631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai#endif
451631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
452631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Laistatic UNIVERSAL_DEV_PM_OPS(mpu3050_pm, mpu3050_suspend, mpu3050_resume, NULL);
453631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
454631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Laistatic const struct i2c_device_id mpu3050_ids[] = {
455631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	{ "mpu3050", 0 },
456631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	{ }
457631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai};
458631b16e81eab82e2894425a94c3fc14bf21adb26Joseph LaiMODULE_DEVICE_TABLE(i2c, mpu3050_ids);
459631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
460e948981aa0c97b6fcaa8626eeddb0340e175e9d7Olof Johanssonstatic const struct of_device_id mpu3050_of_match[] = {
461e948981aa0c97b6fcaa8626eeddb0340e175e9d7Olof Johansson	{ .compatible = "invn,mpu3050", },
462e948981aa0c97b6fcaa8626eeddb0340e175e9d7Olof Johansson	{ },
463e948981aa0c97b6fcaa8626eeddb0340e175e9d7Olof Johansson};
464e948981aa0c97b6fcaa8626eeddb0340e175e9d7Olof JohanssonMODULE_DEVICE_TABLE(of, mpu3050_of_match);
465e948981aa0c97b6fcaa8626eeddb0340e175e9d7Olof Johansson
466631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Laistatic struct i2c_driver mpu3050_i2c_driver = {
467631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	.driver	= {
468631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		.name	= "mpu3050",
469631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		.owner	= THIS_MODULE,
470631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai		.pm	= &mpu3050_pm,
471e948981aa0c97b6fcaa8626eeddb0340e175e9d7Olof Johansson		.of_match_table = mpu3050_of_match,
472631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	},
473631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	.probe		= mpu3050_probe,
4741cb0aa88179b7a71c240529e9d781d7bbb43d2e8Bill Pemberton	.remove		= mpu3050_remove,
475631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai	.id_table	= mpu3050_ids,
476631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai};
477631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
4781b92c1cf6b638e7cbe9fdaac3f6efb8874f5cc02Axel Linmodule_i2c_driver(mpu3050_i2c_driver);
479631b16e81eab82e2894425a94c3fc14bf21adb26Joseph Lai
480631b16e81eab82e2894425a94c3fc14bf21adb26Joseph LaiMODULE_AUTHOR("Wistron Corp.");
481631b16e81eab82e2894425a94c3fc14bf21adb26Joseph LaiMODULE_DESCRIPTION("MPU3050 Tri-axis gyroscope driver");
482631b16e81eab82e2894425a94c3fc14bf21adb26Joseph LaiMODULE_LICENSE("GPL");
483