462 lines
12 KiB
C

/* drivers/input/sensors/gyro/Ewtsa.c
*
* Copyright (C) 2012-2015 Rockchip Electronics Co., Ltd.
* Author: zhangaihui <zah@rock-chips.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/irq.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <linux/uaccess.h>
#include <asm/atomic.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/workqueue.h>
#include <linux/freezer.h>
#include <linux/of_gpio.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif
#include <linux/sensor-dev.h>
/** This define controls compilation of the master device interface */
/*#define EWTSA_MASTER_DEVICE*/
/* configurable */
#define GYRO_MOUNT_SWAP_XY 0 /* swap X, Y */
#define GYRO_MOUNT_REVERSE_X 0 /* reverse X */
#define GYRO_MOUNT_REVERSE_Y 0 /* reverse Y */
#define GYRO_MOUNT_REVERSE_Z 0 /* reverse Z */
/* macro defines */
/*#define CHIP_ID 0x68*/
#define DEVICE_NAME "ewtsa"
#define EWTSA_ON 1
#define EWTSA_OFF 0
#define SLEEP_PIN 14
#define DRDY_PIN 12
#define DIAG_PIN 11
#define MAX_VALUE 32768
/* ewtsa_delay parameter */
#define DELAY_THRES_MIN 1
#define DELAY_THRES_1 4
#define DELAY_THRES_2 9 /* msec x 90% */
#define DELAY_THRES_3 18
#define DELAY_THRES_4 45
#define DELAY_THRES_5 90
#define DELAY_THRES_6 128
#define DELAY_THRES_MAX 255
#define DELAY_DLPF_2 2
#define DELAY_DLPF_3 3
#define DELAY_DLPF_4 4
#define DELAY_DLPF_5 5
#define DELAY_DLPF_6 6
#define DELAY_INTMIN_THRES 9
#define DATA_RATE_1 0x01
/* ewtsa_sleep parameter */
#define SLEEP_OFF 0
#define SLEEP_ON 1
/* event mode */
#define EWTSA_POLLING_MODE 0
#define EWTSA_INTERUPT_MODE 1
/* ewtsa register address */
#define REG_SMPL 0x15
#define REG_FS_DLPF 0x16
#define REG_INT_CFG 0x17
#define REG_INT_STATUS 0x1A
#define REG_SELF_O_C 0x29
#define REG_PWR_MGM 0x3E
#define REG_MBURST_ALL 0xFF
#define GYRO_DATA_REG 0x1D
/* ewtsa register param */
#define SELF_O_C_ENABLE 0x00
#define SELF_O_C_DISABLE 0x01
#define SLEEP_CTRL_ACTIVATE 0x40
#define SLEEP_CTRL_SLEEP 0x00
#define INT_CFG_INT_ENABLE 0x01
#define INT_CFG_INT_DISABLE 0x00
/* ewtsa interrupt control */
#define EWSTA_INT_CLEAR 0x00
#define EWSTA_INT_SKIP 0x01
/* wait time(ms)*/
#define EWTSA_BOOST_TIME_0 500
/* sleep setting range */
#define EWTSA_SLP_MIN 0
#define EWTSA_SLP_MAX 1
/* delay setting range */
#define EWTSA_DLY_MIN 1
#define EWTSA_DLY_MAX 255
/* range setting range */
#define EWTSA_RNG_MIN 0
#define EWTSA_RNG_MAX 3
/* soc setting range */
#define EWTSA_SOC_MIN 0
#define EWTSA_SOC_MAX 1
/* event setting range */
#define EWTSA_EVE_MIN 0
#define EWTSA_EVE_MAX 1
/* init param */
#define SLEEP_INIT_VAL (SLEEP_ON)
#define DELAY_INIT_VAL 10
#define RANGE_INIT_VAL 2 /*range 1000*/
#define DLPF_INIT_VAL (DELAY_DLPF_2)
#define CALIB_FUNC_INIT_VAL (EWTSA_ON)
/*config store counter num*/
#define CONFIG_COUNTER_MIN (6+9)
#define CONFIG_COUNTER_MAX (32+9)
/*command name */
#define COMMAND_NAME_SOC 0
#define COMMAND_NAME_DLY 1
#define COMMAND_NAME_RNG 2
#define COMMAND_NAME_EVE 3
#define COMMAND_NAME_SLP 4
#define COMMAND_NAME_NUM 5
#define EWTSA_delay DELAY_INIT_VAL
#define EWTSA_range RANGE_INIT_VAL
#define EWTSA_calib EWTSA_ON
/****************operate according to sensor chip:start************/
static int i2c_read_byte(struct i2c_client *thisClient, unsigned char regAddr, char *pReadData)
{
int ret = 0;
ret = i2c_master_send( thisClient, (char*)&regAddr, 1);
if(ret < 0)
{
printk("EWTSA send cAddress=0x%x error!\n", regAddr);
return ret;
}
ret = i2c_master_recv( thisClient, (char*)pReadData, 1);
if(ret < 0)
{
printk("EWTSAread *pReadData=0x%x error!\n", *pReadData);
return ret;
}
return 1;
}
static int i2c_write_byte(struct i2c_client *thisClient, unsigned char regAddr, unsigned char writeData)
{
char write_data[2] = {0};
int ret=0;
write_data[0] = regAddr;
write_data[1] = writeData;
ret = i2c_master_send(thisClient, write_data, 2);
if (ret < 0)
{
ret = i2c_master_send(thisClient, write_data, 2);
if (ret < 0)
{
printk("EWTSA send regAddr=0x%x error!\n", regAddr);
return ret;
}
return 1;
}
return 1;
}
static int ewtsa_system_restart(struct i2c_client *client)
{
int err;
char reg;
char smpl , dlpf;
err = i2c_write_byte(client, ( unsigned char)REG_SELF_O_C, ( unsigned char)SELF_O_C_DISABLE);
if (err < 0) {
return err;
}
///Set SMPL register
if (EWTSA_delay <= ( unsigned char)DELAY_THRES_2) {
smpl = ( unsigned char)DELAY_INTMIN_THRES;
}else{
smpl = ( unsigned char)(EWTSA_delay - ( unsigned char)1);
}
err = i2c_write_byte(client, ( unsigned char)REG_SMPL, ( unsigned char)smpl);
if (err < 0) {
return err;
}
///Set DLPF register
if (EWTSA_delay >= ( unsigned char)DELAY_THRES_6){
dlpf = ( unsigned char)DELAY_DLPF_6;
}else if (EWTSA_delay >= ( unsigned char)DELAY_THRES_5) {
dlpf = ( unsigned char)DELAY_DLPF_5;
}else if (EWTSA_delay >= ( unsigned char)DELAY_THRES_4){
dlpf = ( unsigned char)DELAY_DLPF_4;
}else if (EWTSA_delay >= ( unsigned char)DELAY_THRES_3) {
dlpf = ( unsigned char)DELAY_DLPF_3;
}else{
dlpf = ( unsigned char)DELAY_DLPF_2;
}
reg = ( unsigned char)(( unsigned char)(EWTSA_range << 3) | dlpf | ( unsigned char)0x80 ) ;
err = i2c_write_byte(client, REG_FS_DLPF, reg);
if (err < 0) {
return err;
}
if (EWTSA_calib== EWTSA_ON) {
printk("EWTSA_set_calibration() start \n");
err = i2c_write_byte(client,( unsigned char)REG_SELF_O_C, ( unsigned char)SELF_O_C_ENABLE);
if (err < 0) {
return err;
}
mdelay(500);
printk("EWTSA_set_calibration() end \n");
}
return 0;
}
static int ewtsa_disable(struct i2c_client *client)
{
struct sensor_private_data *sensor =
(struct sensor_private_data *) i2c_get_clientdata(client);
gpio_direction_output(sensor->pdata->standby_pin, GPIO_HIGH);
DBG("%s: end \n",__func__);
return 0;
}
static int ewtsa_enable(struct i2c_client *client)
{
int err;
struct sensor_private_data *sensor =
(struct sensor_private_data *) i2c_get_clientdata(client);
gpio_direction_output(sensor->pdata->standby_pin, GPIO_LOW);
err = i2c_write_byte(client, ( unsigned char)REG_PWR_MGM, ( unsigned char)SLEEP_CTRL_ACTIVATE);////0x44
if (err < 0){
//return err;
err = ewtsa_system_restart(client);///restart; only when i2c error
if (err < 0){
return err;
}
}
err = i2c_write_byte(client, ( unsigned char) REG_INT_CFG, ( unsigned char)INT_CFG_INT_ENABLE);
if (err < 0) {
return err;
}
DBG("%s: end \n",__func__);
return 0;
}
void gyro_dev_reset(struct i2c_client *client)
{
struct sensor_private_data *sensor =
(struct sensor_private_data *) i2c_get_clientdata(client);
DBG("%s\n",__func__);
gpio_direction_output(sensor->pdata->standby_pin, GPIO_HIGH);
msleep(100);
gpio_direction_output(sensor->pdata->standby_pin, GPIO_LOW);
msleep(100);
}
static int sensor_active(struct i2c_client *client, int enable, int rate)
{
/*
struct sensor_private_data *sensor =
(struct sensor_private_data *) i2c_get_clientdata(client);
int status = 0;
*/
int result = 0;
if(enable)
{
result=ewtsa_enable(client);
}
else
{
result=ewtsa_disable(client);
}
if(result)
printk("%s:fail to active sensor\n",__func__);
return result;
}
static int sensor_init(struct i2c_client *client)
{
struct sensor_private_data *sensor =
(struct sensor_private_data *) i2c_get_clientdata(client);
int result = 0;
/*
unsigned char buf[5];
unsigned char data = 0;
int i = 0;
char pReadData=0;
*/
sensor->status_cur = SENSOR_OFF;
gyro_dev_reset(client);
ewtsa_system_restart(client);
return result;
}
static int gyro_report_value(struct i2c_client *client, struct sensor_axis *axis)
{
struct sensor_private_data *sensor =
(struct sensor_private_data *) i2c_get_clientdata(client);
if (sensor->status_cur == SENSOR_ON) {
/* Report GYRO information */
input_report_rel(sensor->input_dev, ABS_RX, axis->x);
input_report_rel(sensor->input_dev, ABS_RY, axis->y);
input_report_rel(sensor->input_dev, ABS_RZ, axis->z);
input_sync(sensor->input_dev);
}
return 0;
}
static int sensor_report_value(struct i2c_client *client)
{
struct sensor_private_data *sensor =
(struct sensor_private_data *) i2c_get_clientdata(client);
struct sensor_platform_data *pdata = sensor->pdata;
int ret = 0;
int x = 0, y = 0, z = 0;
struct sensor_axis axis;
char buffer[6] = {0};
int i = 0;
/* int value = 0; */
memset(buffer, 0, 6);
#if 0
/* Data bytes from hardware xL, xH, yL, yH, zL, zH */
do {
buffer[0] = sensor->ops->read_reg;
ret = sensor_rx_data(client, buffer, sensor->ops->read_len);
if (ret < 0)
return ret;
} while (0);
#else
for(i=0; i<6; i++)
{
i2c_read_byte(client, sensor->ops->read_reg + i,&buffer[i]);
}
#endif
x = (short) (((buffer[0]) << 8) | buffer[1]);
y = (short) (((buffer[2]) << 8) | buffer[3]);
z = (short) (((buffer[4]) << 8) | buffer[5]);
//printk("%s: x=%d y=%d z=%d \n",__func__, x,y,z);
if (pdata)
{
axis.x = (pdata->orientation[0])*x + (pdata->orientation[1])*y + (pdata->orientation[2])*z;
axis.y = (pdata->orientation[3])*x + (pdata->orientation[4])*y + (pdata->orientation[5])*z;
axis.z = (pdata->orientation[6])*x + (pdata->orientation[7])*y + (pdata->orientation[8])*z;
}
else
{
axis.x = x;
axis.y = y;
axis.z = z;
}
gyro_report_value(client, &axis);
mutex_lock(&sensor->data_mutex);
sensor->axis = axis;
mutex_unlock(&sensor->data_mutex);
return ret;
}
static struct sensor_operate gyro_ewtsa_ops = {
.name = "ewtsa",
.type = SENSOR_TYPE_GYROSCOPE,
.id_i2c = GYRO_ID_EWTSA,
.read_reg = GYRO_DATA_REG,
.read_len = 6,
.id_reg = -1,
.id_data = -1,
.precision = 16,
.ctrl_reg = REG_PWR_MGM,
.int_status_reg = REG_INT_STATUS,
.range = {-32768, 32768},
.trig = IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
.active = sensor_active,
.init = sensor_init,
.report = sensor_report_value,
};
/****************operate according to sensor chip:end************/
static int gyro_ewtsa_probe(struct i2c_client *client,
const struct i2c_device_id *devid)
{
return sensor_register_device(client, NULL, devid, &gyro_ewtsa_ops);
}
static void gyro_ewtsa_remove(struct i2c_client *client)
{
sensor_unregister_device(client, NULL, &gyro_ewtsa_ops);
}
static const struct i2c_device_id gyro_ewtsa_id[] = {
{"ewtsa_gyro", GYRO_ID_EWTSA},
{}
};
static struct i2c_driver gyro_ewtsa_driver = {
.probe = gyro_ewtsa_probe,
.remove = (void *)gyro_ewtsa_remove,
.shutdown = sensor_shutdown,
.id_table = gyro_ewtsa_id,
.driver = {
.name = "gyro_ewtsa",
#ifdef CONFIG_PM
.pm = &sensor_pm_ops,
#endif
},
};
module_i2c_driver(gyro_ewtsa_driver);
MODULE_AUTHOR("zhangaihui <zah@rock-chips.com>");
MODULE_DESCRIPTION("ewtsa 3-Axis Gyroscope driver");
MODULE_LICENSE("GPL");