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