android_kernel_modules_leno.../drivers/hwmon/sensor_general.c

2560 lines
59 KiB
C

/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Date: May 2013
* Authors: PSI IO & Sensor Team
* qipeng.zha@intel.com
*/
#include <linux/module.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/sysfs.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/acpi_gpio.h>
#include <linux/delay.h>
#include <linux/firmware.h>
#include <asm/div64.h>
#include "sensor_driver_config.h"
#include "sensor_general.h"
#ifdef CONFIG_GENERAL_SENSOR_DEBUG
/*debug switch*/
unsigned int sensor_general_debug_sensors;
unsigned int sensor_general_debug_level;
EXPORT_SYMBOL(sensor_general_debug_sensors);
EXPORT_SYMBOL(sensor_general_debug_level);
char *action_debug[] = {
"OP_ACCESS",
"OP_MIN", "OP_MAX",
"OP_LOGIC_EQ", "OP_LOGIC_NEQ", "OP_LOGIC_GREATER", "OP_LOGIC_LESS",
"OP_LOGIC_GE", "OP_LOGIC_LE", "OP_LOGIC_AND", "OP_LOGIC_OR",
"OP_ARI_ADD", "OP_ARI_SUB", "OP_ARI_MUL", "OP_ARI_DIV", "OP_ARI_MOD",
"OP_BIT_OR", "OP_BIT_AND", "OP_BIT_LSL", "OP_BIT_LSR", "OP_BIT_NOR",
"OP_ENDIAN_BE16", "OP_ENDIAN_BE16_UN", "OP_ENDIAN_BE24",
"OP_ENDIAN_BE32", "OP_ENDIAN_LE16", "OP_ENDIAN_LE16_UN",
"OP_ENDIAN_LE24", "OP_ENDIAN_LE32",
"OP_RESERVE",
};
/*performance switch*/
static unsigned int sensor_general_time;
static struct {
int times;
ktime_t time;
} sensor_time[MAX_SENSOR_DRIVERS];
static inline void sensor_time_start(struct sensor_data *data, ktime_t *start)
{
/*preempt_disable();*/
if (data->dbg_on & sensor_general_time)
*start = ktime_get();
}
static inline void sensor_time_end(struct sensor_data *data, ktime_t *start)
{
int sensor_num;
ktime_t end;
ktime_t duration;
sensor_num = data->dbg_on & sensor_general_time;
if (sensor_num) {
end = ktime_get();
duration = sensor_time[ffs(sensor_num) - 1].time;
duration = ktime_add(duration, ktime_sub(end, *start));
sensor_time[ffs(sensor_num) - 1].time = duration;
sensor_time[ffs(sensor_num) - 1].times++;
}
/*preempt_enable();*/
}
#else
#define sensor_time_start(a, b)
#define sensor_time_end(a, b)
#endif
static p_extern_c extern_c_array[MAX_EXTERN_C];
static DEFINE_MUTEX(sensor_externc_lock);
static long extern_c_ref_cnt = 0;
static void sensor_launch_work(struct sensor_data *data);
static void unregister_failed_devices(void);
static inline void stack_init(struct sensor_data_stack *stack)
{
stack->top = -1;
}
static inline int stack_empty(struct sensor_data_stack *stack)
{
if (stack->top == -1)
return 1;
else
return 0;
}
static inline int pop(struct sensor_data *data)
{
int ret;
struct sensor_data_stack *stack = &data->stack;
if (stack->top < 0 || stack->top > DATA_STACK_MAX_SIZE - 1) {
dump_stack();
printk(KERN_ERR "Corrupted stack in sensor drver %d\n",
stack->top);
return -EFAULT;
}
ret = stack->data_stack[stack->top--];
SENSOR_DBG(DBG_LEVEL5, data->dbg_on, "%d val:0x%x %s",
stack->top, ret, data->config->input_name);
return ret;
}
static inline void push(struct sensor_data *data, int val)
{
struct sensor_data_stack *stack = &data->stack;
if (stack->top >= DATA_STACK_MAX_SIZE - 1 || stack->top < -1) {
dump_stack();
printk(KERN_ERR "Corrupted stack in sensor drver %d\n",
stack->top);
return;
}
SENSOR_DBG(DBG_LEVEL5, data->dbg_on, "%d val:0x%x %s",
stack->top, val,
data->config->input_name);
stack->data_stack[++stack->top] = val;
}
static inline int data_operand(struct sensor_data *data,
struct operand *oper)
{
int index;
int len;
int addr;
int op;
switch (oper->type) {
case OPT_BEFORE:
op = pop(data);
break;
case OPT_IMM:
op = oper->data.immediate;
break;
case OPT_REG_BUF:
addr = oper->data.reg.addr;
len = oper->data.reg.len;
op = 0;
while (--len >= 0) {
/*assume little endian, if not,
use additional endian action*/
op <<= 8;
op += data->regbuf[addr + len];
}
break;
case OPT_INDEX:
index = oper->data.index;
op = data->private[index];
break;
default:
dev_err(&data->client->dev, "Nonsupport operand1\n");
return -EINVAL;
}
return op;
}
/*
* access of global variable and i2c registers
* i2c reg = reg buf, immediate, before data , global variable
* reg bufs = i2c regs, immediate, before data, global variable
* global variable = reg buf, immeidate, before data
*/
static int data_op_access(struct sensor_data *data, struct data_action *action)
{
u8 addr;
u8 flag;
int len;
int val;
int ret = 0;
SENSOR_DBG(DBG_LEVEL4, data->dbg_on, "%p", action);
switch (action->operand1.type) {
case OPT_REG_BUF:
addr = action->operand1.data.reg.addr;
switch (action->operand2.type) {
case OPT_REG:
/*read i2c register, assume two addr are same*/
len = action->operand2.data.reg.len;
flag = action->operand2.data.reg.flag;
SENSOR_DBG(DBG_LEVEL3, data->dbg_on,
"readreg:(0x%x %d)=",
(unsigned int)addr|flag, (unsigned int)len);
if (len > 1) {
ret = i2c_smbus_read_i2c_block_data(
data->client, addr | flag,
len, &data->regbuf[addr]);
if (ret < 0) {
dev_err(&data->client->dev,
"i2c read error\n");
ret = -EIO;
} else {
int i = 0;
for (; i < len; i++)
SENSOR_DBG(DBG_LEVEL3,
data->dbg_on,
"0x%x",
data->regbuf[addr + i]);
ret = 0;
}
} else {
ret = i2c_smbus_read_byte_data(data->client,
addr | flag);
if (ret < 0) {
dev_err(&data->client->dev,
"i2c read error\n");
ret = -EIO;
} else {
SENSOR_DBG(DBG_LEVEL3,
data->dbg_on, "%x", ret);
data->regbuf[addr] = ret;
ret = 0;
}
}
break;
/*only support len=1 currently*/
case OPT_IMM:
data->regbuf[addr] = action->operand2.data.immediate;
break;
case OPT_BEFORE:
val = pop(data);
data->regbuf[addr] = val;
SENSOR_DBG(DBG_LEVEL3, data->dbg_on,
"set reg buf:%x=%x", addr, val);
break;
case OPT_INDEX:
val = data->private[action->operand2.data.index];
data->regbuf[addr] = val;
SENSOR_DBG(DBG_LEVEL3, data->dbg_on,
"set reg buf:%x = %x", addr, val);
break;
default:
dev_err(&data->client->dev, "Nonsupport operand2\n");
return -EINVAL;
}
break;
case OPT_INDEX:
val = data_operand(data, &action->operand2);
data->private[action->operand1.data.index] = val;
SENSOR_DBG(DBG_LEVEL3, data->dbg_on,
"set privated data:pri[%d]=%x",
action->operand1.data.index, val);
break;
case OPT_REG:
addr = action->operand1.data.reg.addr;
flag = action->operand1.data.reg.flag;
len = action->operand1.data.reg.len;
val = data_operand(data, &action->operand2);
SENSOR_DBG(DBG_LEVEL3, data->dbg_on, "write %s reg: %x=%x",
len > 1 ? "word" : "byte",
(unsigned int)addr|flag, val);
/*only support byte/word write currently*/
if (len == 2) {
/*always update reg buf when write*/
*(u16 *)&data->regbuf[addr] = val;
ret = i2c_smbus_write_word_data(data->client,
addr | flag, val);
} else {
data->regbuf[addr] = val;
ret = i2c_smbus_write_byte_data(data->client,
addr | flag, val);
}
break;
default:
dev_err(&data->client->dev, "Nonsupport operand1\n");
return -EINVAL;
}
return ret;
}
/*data operations*/
int (*data_op_array[OP_RESERVE])(int, int);
#define __BUILD_DATA_BASIC_OP(op, operation) \
static inline int data_op_##op(int op1, int op2) \
{ \
return operation; \
}
#define __BUILD_DATA_ENDIAN_OP(op, operator, sign) \
static inline int data_op_##op(int op1, int op2) \
{ \
return (sign)operator(op1); \
}
__BUILD_DATA_BASIC_OP(logic_eq, op1 == op2)
__BUILD_DATA_BASIC_OP(logic_neq, op1 != op2)
__BUILD_DATA_BASIC_OP(logic_greater, op1 > op2)
__BUILD_DATA_BASIC_OP(logic_less, op1 < op2)
__BUILD_DATA_BASIC_OP(logic_ge, op1 >= op2)
__BUILD_DATA_BASIC_OP(logic_le, op1 <= op2)
__BUILD_DATA_BASIC_OP(logic_and, op1 && op2)
__BUILD_DATA_BASIC_OP(logic_or, op1 || op2)
__BUILD_DATA_BASIC_OP(ari_add, op1 + op2)
__BUILD_DATA_BASIC_OP(ari_sub, op1 - op2)
__BUILD_DATA_BASIC_OP(ari_mul, op1 * op2)
__BUILD_DATA_BASIC_OP(ari_div, op1 / op2)
__BUILD_DATA_BASIC_OP(ari_mod, op1 % op2)
__BUILD_DATA_BASIC_OP(bit_or, op1 | op2)
__BUILD_DATA_BASIC_OP(bit_and, op1 & op2)
__BUILD_DATA_BASIC_OP(bit_lsl, op1 << op2)
__BUILD_DATA_BASIC_OP(bit_lsr, op1 >> op2)
__BUILD_DATA_ENDIAN_OP(be16, be16_to_cpu, s16)
__BUILD_DATA_ENDIAN_OP(be16u, be16_to_cpu, u16)
__BUILD_DATA_ENDIAN_OP(le16, le16_to_cpu, s16)
__BUILD_DATA_ENDIAN_OP(le16u, le16_to_cpu, u16)
__BUILD_DATA_ENDIAN_OP(be32, be32_to_cpu, s32)
__BUILD_DATA_ENDIAN_OP(le32, le32_to_cpu, s32)
__BUILD_DATA_ENDIAN_OP(be24, be24_to_cpu, s32)
__BUILD_DATA_ENDIAN_OP(le24, le24_to_cpu, s32)
static inline int data_op_bit_nor(int op1, int op2)
{
return ~op1;
}
static inline int data_op_min(int op1, int op2)
{
return min(op1, op2);
}
static inline int data_op_max(int op1, int op2)
{
return max(op1, op2);
}
static inline int data_op_comm(int op1, int op2)
{
return op1 > op2 ? 1 : 0;
}
static int sensor_exec_data_action(struct sensor_data *data,
struct data_action *action)
{
int op1, op2 = 0;
int result;
SENSOR_DBG(DBG_LEVEL4, data->dbg_on, "actions:%p", action);
if (action->op == OP_ACCESS)
return data_op_access(data, action);
else if (action->op > OP_ACCESS && action->op < OP_RESERVE) {
/*other data operations*/
op1 = data_operand(data, &action->operand1);
if (action->op < OP_BIT_NOR)
op2 = data_operand(data, &action->operand2);
result = data_op_array[action->op](op1, op2);
push(data, result);
SENSOR_DBG(DBG_LEVEL3, data->dbg_on, "0x%x %s 0x%x = 0x%x",
op1, action_debug[action->op], op2, result);
return 0;
} else
return -EINVAL;
}
#define RET_RETURN 2
static int sensor_exec_actions(struct sensor_data *data,
int num, struct lowlevel_action *actions)
{
int ret = 0;
int num_con;
int num_if;
int num_else;
int inx;
p_extern_c p = NULL;
while (num > 0) {
SENSOR_DBG(DBG_LEVEL4, data->dbg_on,
"%s %p actions:%p num:%d",
data->config->input_name, data,
actions, (int)num);
switch (actions->type) {
case DATA:
ret = sensor_exec_data_action(data,
&actions->action.data);
if (ret) {
dev_err(&data->client->dev,
"[%d]%s\n", __LINE__, __func__);
return ret;
}
actions++;
num--;
break;
case IFELSE:
num_con = actions->action.ifelse.num_con;
num_if = actions->action.ifelse.num_if;
num_else = actions->action.ifelse.num_else;
/*skip ifelse action itself*/
actions++;
num--;
ret = sensor_exec_actions(data, num_con, actions);
if (ret) {
if (ret != RET_RETURN)
dev_err(&data->client->dev,
"[%d]%s\n", __LINE__, __func__);
return ret;
}
actions += num_con;
num -= num_con;
if (pop(data)) {
SENSOR_DBG(DBG_LEVEL3, data->dbg_on,
"true of if action:%p", actions);
ret = sensor_exec_actions(data,
num_if, actions);
if (ret) {
if (ret != RET_RETURN)
dev_err(&data->client->dev,
"[%d]%s\n", __LINE__, __func__);
return ret;
}
} else {
SENSOR_DBG(DBG_LEVEL3, data->dbg_on,
"false of if action:%p",
actions);
ret = sensor_exec_actions(data,
num_else, actions + num_if);
if (ret) {
if (ret != RET_RETURN)
dev_err(&data->client->dev,
"[%d]%s\n", __LINE__, __func__);
return ret;
}
}
actions += (num_if + num_else);
num -= (num_if + num_else);
break;
case SLEEP:
msleep(actions->action.sleep.ms);
actions++;
num--;
break;
case RETURN:
return RET_RETURN;
case EXTERNC:
SENSOR_DBG(DBG_LEVEL3, data->dbg_on,
"extern c action:%p", actions);
inx = actions->action.externc.index;
/*Don't use sensor_externc_lock directly for sake of performance
use a reference count to aovid unregister extern_c here*/
mutex_lock(&sensor_externc_lock);
extern_c_ref_cnt++;
mutex_unlock(&sensor_externc_lock);
if (inx < MAX_EXTERN_C && (p = extern_c_array[inx])) {
ret = (*p)(data);
if (ret) {
dev_err(&data->client->dev,
"[%d]%s exec extern c %p\n",
__LINE__, __func__, p);
}
} else {
dev_err(&data->client->dev,
"[%d]%s\n", __LINE__, __func__);
ret = -EINVAL;
}
mutex_lock(&sensor_externc_lock);
extern_c_ref_cnt--;
mutex_unlock(&sensor_externc_lock);
if (ret)
return ret;
actions++;
num--;
break;
default:
dev_err(&data->client->dev,
"[%d]%s\n", __LINE__, __func__);
return -EINVAL;
}
}
return ret;
}
/*
* num: how many valid actions to exec
* actions: lowlevel actions table
*/
static int sensor_exec_lowlevel_actions(struct sensor_data *data,
int num, struct lowlevel_action *actions)
{
int ret;
ret = sensor_exec_actions(data, num, actions);
if (ret == RET_RETURN) {
SENSOR_DBG(DBG_LEVEL3, data->dbg_on, "return action");
return 0;
}
return ret;
}
/*
* exec of user defined sensor action
*/
static int sensor_exec_sensor_action(struct sensor_data *data,
enum sensor_action type)
{
int ret = 0;
int num = data->config->indexs[type].num;
if (num) {
int index = data->config->indexs[type].index;
struct lowlevel_action *action_table =
(struct lowlevel_action *)&data->config->actions;
struct lowlevel_action *actions = &action_table[index];
ret = sensor_exec_lowlevel_actions(data, num, actions);
}
return ret;
}
/*
* interval: poll interal in ms
*/
static int sensor_update_odr(struct sensor_data *data, int interval)
{
int ret = 0;
int entry;
int hz_interval;
int index;
int num;
struct lowlevel_action *action_table =
(struct lowlevel_action *)&data->config->actions;
SENSOR_DBG(DBG_LEVEL1, data->dbg_on, "%s", data->config->input_name);
if (!data->config->odr_entries)
return ret;
/*search odr table to get the nearest lower than requested interval*/
/*fix me: follow lis3dhl acc driver*/
if (!interval)
interval = data->config->report_interval;
if (!interval)
hz_interval = 1000;
else
hz_interval = 1000/interval;
for (entry = 0; entry < data->config->odr_entries; entry++) {
if (data->config->odr_table[entry].hz >= hz_interval)
break;
}
if (entry >= data->config->odr_entries) {
dev_err(&data->client->dev, "Nonsupport interval\n");
return -EINVAL;
}
index = data->config->odr_table[entry].index.index;
num = data->config->odr_table[entry].index.num;
ret = sensor_exec_lowlevel_actions(data, num, &action_table[index]);
return ret;
}
static int sensor_update_range(struct sensor_data *data, int range)
{
int ret = 0;
int entry;
int index;
int num;
struct lowlevel_action *action_table =
(struct lowlevel_action *)&data->config->actions;
SENSOR_DBG(DBG_LEVEL1, data->dbg_on, "%s", data->config->input_name);
if (!data->config->range_entries)
return ret;
/*search range table*/
for (entry = 0; entry < data->config->range_entries; entry++) {
if (data->config->range_table[entry].range == range)
break;
}
if (entry >= data->config->range_entries) {
dev_err(&data->client->dev, "Nonsupport range\n");
return -EINVAL;
}
index = data->config->range_table[entry].index.index;
num = data->config->range_table[entry].index.num;
return sensor_exec_lowlevel_actions(data, num, &action_table[index]);
}
/*
* Only be called in probe
*/
static int sensor_init(struct sensor_data *data)
{
int ret = 0;
int id;
SENSOR_DBG(DBG_LEVEL1, data->dbg_on, "%s", data->config->input_name);
/*common ID check*/
if (data->config->id_reg_addr != SENSOR_INVALID_REG) {
ret = i2c_smbus_read_byte_data(data->client,
data->config->id_reg_addr | data->config->id_reg_flag);
if (ret < 0) {
dev_err(&data->client->dev, "Sensor get ID error\n");
return ret;
}
for (id = 0; id < MAX_DEV_IDS; id++) {
if (data->config->id[id] == ret)
break;
}
if (id >= MAX_DEV_IDS) {
dev_err(&data->client->dev, "No matched ID %d\n", ret);
return -ENODEV;
}
}
return sensor_exec_sensor_action(data, INIT);
}
static int sensor_deinit(struct sensor_data *data)
{
SENSOR_DBG(DBG_LEVEL1, data->dbg_on, "%s", data->config->input_name);
return sensor_exec_sensor_action(data, DEINIT);
}
static int sensor_enable(struct sensor_data *data)
{
int ret = 0;
SENSOR_DBG(DBG_LEVEL1, data->dbg_on, "%s", data->config->input_name);
if (data->state != STATE_EN) {
ret = sensor_exec_sensor_action(data, ENABLE);
data->state = STATE_EN;
sensor_launch_work(data);
}
return ret;
}
static int sensor_disable(struct sensor_data *data)
{
int ret = 0;
SENSOR_DBG(DBG_LEVEL1, data->dbg_on, "%s", data->config->input_name);
if (data->state == STATE_EN) {
if (INT != data->config->method) {
cancel_delayed_work(&data->input_work);
data->launched = 0;
}
ret = sensor_exec_sensor_action(data, DISABLE);
data->state = STATE_DIS;
}
return ret;
}
static int sensor_suspend(struct device *dev)
{
int i;
struct i2c_client *client = to_i2c_client(dev);
struct sensor_data *data = i2c_get_clientdata(client);
struct mutex *lock = data->lock;
int num = data->config->shared_nums;
SENSOR_DBG(DBG_LEVEL1, data->dbg_on, "%s", data->config->input_name);
if (INT == data->config->method) {
int irq = gpio_to_irq(data->gpio);
disable_irq(irq);
}
mutex_lock(lock);
for (i = 0; i < num; i++, data++) {
data->state_suspend = data->state;
sensor_disable(data);
data->state = STATE_SUS;
}
mutex_unlock(lock);
return 0;
}
static int sensor_resume(struct device *dev)
{
int i;
struct i2c_client *client = to_i2c_client(dev);
struct sensor_data *data = i2c_get_clientdata(client);
struct mutex *lock = data->lock;
int num = data->config->shared_nums;
SENSOR_DBG(DBG_LEVEL1, data->dbg_on, "%s", data->config->input_name);
if (INT == data->config->method) {
int irq = gpio_to_irq(data->gpio);
enable_irq(irq);
}
mutex_lock(lock);
for (i = 0; i < num; i++, data++) {
if (data->state_suspend == STATE_EN)
sensor_enable(data);
}
mutex_unlock(lock);
return 0;
}
/*Fix me, only support up to 32 sensor drivers*/
static int general_sensor_nums;
/*sync access of below*/
static DEFINE_MUTEX(sensor_proc_lock);
static struct sensor_data *sensor_data_tbl[MAX_SENSOR_DRIVERS] = {NULL};
static struct sensor_rawdata_proc *rawdata_proc_tbl[MAX_SENSOR_DRIVERS] = {NULL};
static inline int sensor_add_data(struct sensor_data *data_new)
{
int i;
int ret = 0;
mutex_lock(&sensor_proc_lock);
for (i = 0; i < MAX_SENSOR_DRIVERS; i++) {
struct sensor_data *data = sensor_data_tbl[i];
if (!data) {
sensor_data_tbl[i] = data_new;
break;
}
}
if (i >= MAX_SENSOR_DRIVERS) {
ret = -EINVAL;
}
mutex_unlock(&sensor_proc_lock);
return ret;
}
static inline int sensor_remove_data(struct sensor_data *data_new)
{
int i;
int ret = 0;
mutex_lock(&sensor_proc_lock);
for (i = 0; i < MAX_SENSOR_DRIVERS; i++) {
struct sensor_data *data = sensor_data_tbl[i];
if (data == data_new) {
sensor_data_tbl[i] = NULL;
break;
}
}
if (i >= MAX_SENSOR_DRIVERS) {
ret = -EINVAL;
}
mutex_unlock(&sensor_proc_lock);
return ret;
}
int sensor_register_rawdata_proc(struct sensor_rawdata_proc *proc_new)
{
int i;
int ret = 0;
SENSOR_DBG(DBG_LEVEL3, DBG_ALL_SENSORS, "%s", proc_new->name);
mutex_lock(&sensor_proc_lock);
for (i = 0; i < MAX_SENSOR_DRIVERS; i++) {
struct sensor_rawdata_proc *proc = rawdata_proc_tbl[i];
if (!proc) {
rawdata_proc_tbl[i] = proc_new;
break;
}
}
if (i >= MAX_SENSOR_DRIVERS) {
ret = -EINVAL;
goto out;
}
for (i = 0; i < MAX_SENSOR_DRIVERS; i++) {
struct sensor_data *data = sensor_data_tbl[i];
if (data && !strncmp(proc_new->name,
data->config->name, strlen(proc_new->name))) {
if (data->rawdata_proc)
printk(KERN_WARNING
"Override new raw data proc for %s\n",
data->config->input_name);
data->rawdata_proc = proc_new;
break;
}
}
out:
mutex_unlock(&sensor_proc_lock);
return ret;
}
EXPORT_SYMBOL(sensor_register_rawdata_proc);
int sensor_unregister_rawdata_proc(struct sensor_rawdata_proc *proc_new)
{
int i;
int ret = 0;
SENSOR_DBG(DBG_LEVEL3, DBG_ALL_SENSORS, "%s", proc_new->name);
mutex_lock(&sensor_proc_lock);
for (i = 0; i < MAX_SENSOR_DRIVERS; i++) {
struct sensor_rawdata_proc *proc = rawdata_proc_tbl[i];
if (proc == proc_new) {
rawdata_proc_tbl[i] = NULL;
break;
}
}
if (i >= MAX_SENSOR_DRIVERS) {
ret = -EINVAL;
goto out;
}
for (i = 0; i < MAX_SENSOR_DRIVERS; i++) {
struct sensor_data *data = sensor_data_tbl[i];
if (data && data->rawdata_proc == proc_new) {
data->rawdata_proc = NULL;
break;
}
}
out:
mutex_unlock(&sensor_proc_lock);
return ret;
}
EXPORT_SYMBOL(sensor_unregister_rawdata_proc);
int sensor_register_extern_c(p_extern_c p)
{
int i;
int ret = 0;
SENSOR_DBG(DBG_LEVEL3, DBG_ALL_SENSORS, "%p", p);
mutex_lock(&sensor_externc_lock);
for (i = 0; i < MAX_EXTERN_C; i++) {
if (!extern_c_array[i]) {
extern_c_array[i] = p;
break;
}
}
if (i >= MAX_EXTERN_C)
ret = -EINVAL;
mutex_unlock(&sensor_externc_lock);
return ret;
}
EXPORT_SYMBOL(sensor_register_extern_c);
int sensor_unregister_extern_c(p_extern_c p)
{
int i;
int ret = 0;
SENSOR_DBG(DBG_LEVEL3, DBG_ALL_SENSORS, "%p", p);
mutex_lock(&sensor_externc_lock);
if (extern_c_ref_cnt > 0) {
printk(KERN_ERR "Err: can't unregister externc %d",
extern_c_ref_cnt);
ret = -EBUSY;
goto out;
}
for (i = 0; i < MAX_EXTERN_C; i++) {
if (extern_c_array[i] == p) {
extern_c_array[i] = NULL;
break;
}
}
if (i >= MAX_EXTERN_C)
ret = -EINVAL;
out:
mutex_unlock(&sensor_externc_lock);
return ret;
}
EXPORT_SYMBOL(sensor_unregister_extern_c);
static int sensor_get_report_data(struct sensor_data *data)
{
int ret = 0;
int val;
int (*proc)(struct sensor_data *, int);
#ifdef CONFIG_GENERAL_SENSOR_DEBUG
ktime_t start;
#endif
SENSOR_DBG(DBG_LEVEL3, data->dbg_on, "%s", data->config->input_name);
sensor_time_start(data, &start);
/*AXIS X*/
if (data->config->indexs[GET_DATA_X].num) {
ret = sensor_exec_sensor_action(data, GET_DATA_X);
if (!ret) {
if (stack_empty(&data->stack)) {
SENSOR_DBG(DBG_LEVEL2, data->dbg_on,
"%s no data", data->config->input_name);
return ret; /*no valid data*/
}
val = pop(data);
if (data->rawdata_proc &&
(proc = data->rawdata_proc->proc_x))
val = (*proc)(data, val);
SENSOR_DBG(DBG_LEVEL2, data->dbg_on, "%s X:%d",
data->config->input_name, val);
/*Fix me: REL_X/Y/Z == ABS_X/Y/Z*/
input_event(data->input_dev,
data->config->event_type, REL_X, val);
}
}
/*AXIS Y*/
if (data->config->indexs[GET_DATA_Y].num) {
ret = sensor_exec_sensor_action(data, GET_DATA_Y);
if (!ret) {
if (stack_empty(&data->stack))
return ret;
val = pop(data);
if (data->rawdata_proc &&
(proc = data->rawdata_proc->proc_y))
val = (*proc)(data, val);
SENSOR_DBG(DBG_LEVEL2, data->dbg_on, "%s Y:%d",
data->config->input_name, val);
input_event(data->input_dev,
data->config->event_type, REL_Y, val);
}
}
/*AXIS Z*/
if (data->config->indexs[GET_DATA_Z].num) {
ret = sensor_exec_sensor_action(data, GET_DATA_Z);
if (!ret) {
if (stack_empty(&data->stack))
return ret;
val = pop(data);
if (data->rawdata_proc &&
(proc = data->rawdata_proc->proc_z))
val = (*proc)(data, val);
SENSOR_DBG(DBG_LEVEL2, data->dbg_on, "%s Z:%d",
data->config->input_name, val);
input_event(data->input_dev,
data->config->event_type, REL_Z, val);
}
}
input_sync(data->input_dev);
sensor_time_end(data, &start);
return ret;
}
static ssize_t sensor_range_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct sensor_data *data = i2c_get_clientdata(client);
int range;
mutex_lock(data->lock);
range = data->range;
mutex_unlock(data->lock);
return sprintf(buf, "%d\n", range);
}
static ssize_t sensor_range_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int ret;
unsigned long range;
struct i2c_client *client = to_i2c_client(dev);
struct sensor_data *data = i2c_get_clientdata(client);
if (kstrtoul(buf, 0, &range))
return -EINVAL;
mutex_lock(data->lock);
ret = sensor_update_range(data, range);
if (ret < 0)
goto err;
data->range = range;
ret = count;
err:
mutex_unlock(data->lock);
return ret;
}
static ssize_t attr_get_selftest(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct sensor_data *data = i2c_get_clientdata(client);
int val;
int ret;
SENSOR_DBG(DBG_LEVEL3, data->dbg_on, "%s", data->config->input_name);
mutex_lock(data->lock);
ret = sensor_exec_sensor_action(data, GET_SELFTEST);
if (ret) {
dev_err(dev, "%s\n", __func__);
mutex_unlock(data->lock);
return -EIO;
}
val = pop(data);
mutex_unlock(data->lock);
return sprintf(buf, "%d\n", val);
}
static ssize_t attr_set_selftest(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct i2c_client *client = to_i2c_client(dev);
struct sensor_data *data = i2c_get_clientdata(client);
int ret;
unsigned long val;
SENSOR_DBG(DBG_LEVEL3, data->dbg_on, "%s", data->config->input_name);
if (kstrtoul(buf, 0, &val))
return -EINVAL;
mutex_lock(data->lock);
/*make sure the data action will pop this data*/
push(data, val);
ret = sensor_exec_sensor_action(data, SET_SELFTEST);
if (ret)
dev_err(dev, "%s\n", __func__);
mutex_unlock(data->lock);
return size;
}
/*show routine for data action */
static ssize_t sensor_sysfs_data_acton_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
struct i2c_client *client = to_i2c_client(dev);
struct sensor_data *data = i2c_get_clientdata(client);
struct sysfs_entry *entry = data->config->sysfs_table;
unsigned long val;
int index;
int num;
int i;
struct lowlevel_action *action_table =
(struct lowlevel_action *)&data->config->actions;
SENSOR_DBG(DBG_LEVEL3, data->dbg_on, "%s", data->config->input_name);
for (i = 0; i < data->config->sysfs_entries; i++, entry++) {
if (!strcmp(attr->attr.name, entry->name))
break;
}
if (i >= data->config->sysfs_entries) {
dev_err(&client->dev, "[%d]%s\n", __LINE__, __func__);
return -EIO;
}
mutex_lock(data->lock);
index = data->config->sysfs_table[i].action.data.index_show.index;
num = data->config->sysfs_table[i].action.data.index_show.num;
ret = sensor_exec_lowlevel_actions(data, num, &action_table[index]);
if (ret) {
dev_err(&client->dev, "[%d]%s\n", __LINE__, __func__);
mutex_unlock(data->lock);
return -EIO;
}
val = pop(data);
mutex_unlock(data->lock);
SENSOR_DBG(DBG_LEVEL3, data->dbg_on, "%x", (int)val);
return sprintf(buf, "%d\n", (int)val);
}
/* store routine for data action
* series data actions, make sure the last action
* is OP_ACCESS when prepare config
*/
static ssize_t sensor_sysfs_data_acton_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int ret;
unsigned long val;
struct i2c_client *client = to_i2c_client(dev);
struct sensor_data *data = i2c_get_clientdata(client);
struct sysfs_entry *entry = data->config->sysfs_table;
int index;
int num;
int i;
struct lowlevel_action *action_table =
(struct lowlevel_action *)&data->config->actions;
SENSOR_DBG(DBG_LEVEL3, data->dbg_on, "%s", data->config->input_name);
if (kstrtoul(buf, 0, &val))
return -EINVAL;
for (i = 0; i < data->config->sysfs_entries; i++, entry++) {
if (!strcmp(attr->attr.name, entry->name))
break;
}
if (i >= data->config->sysfs_entries) {
dev_err(&client->dev, "[%d]%s\n", __LINE__, __func__);
return -EIO;
}
mutex_lock(data->lock);
push(data, val);
SENSOR_DBG(DBG_LEVEL3, data->dbg_on, "%x", (int)val);
index = data->config->sysfs_table[i].action.data.index_store.index;
num = data->config->sysfs_table[i].action.data.index_store.num;
ret = sensor_exec_lowlevel_actions(data, num, &action_table[index]);
if (ret) {
dev_err(&client->dev, "[%d]%s\n", __LINE__, __func__);
mutex_unlock(data->lock);
return -EIO;
}
mutex_unlock(data->lock);
return count;
}
/*
* for Poll and Mix method, need to lauch delayed work when enable/resume
* while for Int, no sw need to launch except enable hw
* mutex lock must be held when calling this function
*/
static void sensor_launch_work(struct sensor_data *data)
{
SENSOR_DBG(DBG_LEVEL1, data->dbg_on, "%s", data->config->input_name);
if (INT == data->config->method) {
SENSOR_DBG(DBG_LEVEL1, data->dbg_on, "%s skip int",
data->config->input_name);
return;
}
if (data->launched) {
SENSOR_DBG(DBG_LEVEL1, data->dbg_on, "%s already launch",
data->config->input_name);
return;
}
if (data->poll_interval > 0) {
/*Poll method*/
schedule_delayed_work(&data->input_work,
msecs_to_jiffies(data->poll_interval));
} else {
/*MIX method*/
data->report_cnt = data->config->report_cnt;
schedule_delayed_work(&data->input_work,
msecs_to_jiffies(data->config->report_interval));
}
data->launched = 1;
}
/*
* general delayed work func
* create a seperate work queue for all sensor drivers ?
*/
static void sensor_poll_work(struct work_struct *work)
{
int delay;
struct sensor_data *data = container_of(to_delayed_work(work),
struct sensor_data, input_work);
SENSOR_DBG(DBG_LEVEL3, data->dbg_on, "%s", data->config->input_name);
mutex_lock(data->lock);
/*especially for the first time : INIT_DELAYED_WORK*/
if (data->state != STATE_EN) {
data->launched = 0;
goto poll_out;
}
/*nothing input if error*/
sensor_get_report_data(data);
/*Poll or Mix method*/
if (data->poll_interval > 0) {
delay = msecs_to_jiffies(data->poll_interval);
schedule_delayed_work(&data->input_work, delay);
} else {
if (data->report_cnt-- > 0) {
delay = msecs_to_jiffies(data->config->report_interval);
schedule_delayed_work(&data->input_work, delay);
} else {
data->launched = 0;
}
}
poll_out:
mutex_unlock(data->lock);
}
/*
* this is somewhat hardcode for special sensors
* which ack is not common and performance critical
* although these action can be integrate in get_data action
*/
static int fixup_accel(struct sensor_data *data)
{
return 0;
}
static int fixup_apds990x(struct sensor_data *data)
{
return 0;
}
struct sensor_ack_fixup {
char *name;
int (*fn)(struct sensor_data *);
};
static struct sensor_ack_fixup fixup_table[] = {
{"accel", fixup_accel},
{"apds990x", fixup_apds990x},
{NULL, NULL}
};
static int sensor_ack_int_fixup(struct sensor_data *data)
__attribute__((unused));
static int sensor_ack_int_fixup(struct sensor_data *data)
{
struct sensor_ack_fixup *fixup = fixup_table;
while (fixup->name) {
if (!strcmp(fixup->name, data->config->name))
return fixup->fn(data);
fixup++;
}
return 0;
}
/*
* general irq thread handler
*/
static irqreturn_t sensor_interrupt_handler(int irq, void *pri)
{
struct sensor_data *data = (struct sensor_data *)pri;
enum method_get_data method = data->config->method;
int ret;
retry_int:
mutex_lock(data->lock);
if (data->config->irq_serialize) {
if (data->multi_index != *data->share_irq_seq) {
mutex_unlock(data->lock);
cond_resched();
goto retry_int;
} else {
(*data->share_irq_seq)++;
if (*data->share_irq_seq >= data->config->shared_nums)
*data->share_irq_seq = 0;
}
}
SENSOR_DBG(DBG_LEVEL3, data->dbg_on, "%s", data->config->input_name);
ret = sensor_exec_sensor_action(data, INT_ACK);
if (ret) {
printk(KERN_ERR "[%d]%s exec INT action error\n",
__LINE__, __func__);
ret = IRQ_HANDLED;
goto irq_out;
} else {
ret = pop(data);
if (ret == IRQ_NONE) {
SENSOR_DBG(DBG_LEVEL3, data->dbg_on,
"unexpected irq");
goto irq_out;
}
}
/*especially for the first time, similar with work func */
if (data->state != STATE_EN) {
ret = IRQ_HANDLED;
goto irq_out;
}
if (method == INT) {
ret = sensor_get_report_data(data);
if (ret) {
printk(KERN_ERR "[%d]%s get data error\n",
__LINE__, __func__);
ret = IRQ_HANDLED;
goto irq_out;
}
} else if (method == MIX)
sensor_launch_work(data);
else
printk(KERN_ERR "Wrong method in sensor irq\n");
ret = IRQ_HANDLED;
irq_out:
mutex_unlock(data->lock);
return ret;
}
/*
* poll: delayed work
* int: thread irq func
* mix: thread irq func and delayed work, irq triger delayed work
*/
static int sensor_get_data_init(struct sensor_data *data)
{
int ret = 0;
enum method_get_data method = data->config->method;
SENSOR_DBG(DBG_LEVEL3, data->dbg_on, "%s", data->config->input_name);
/*init delayed work or irq routine*/
if (method == POLL || method == MIX)
INIT_DELAYED_WORK(&data->input_work, sensor_poll_work);
/*init irq*/
if (method == INT || method == MIX) {
int irq;
unsigned long flags;
/*only the fisrt one request gpio*/
if (data->multi_index == 0) {
gpio_request(data->gpio, data->config->name);
gpio_direction_input(data->gpio);
}
flags = data->config->irq_flag;
if (data->config->shared_nums > 1)
flags |= IRQF_SHARED;
irq = gpio_to_irq(data->gpio);
ret = request_threaded_irq(irq, NULL, sensor_interrupt_handler,
flags, data->config->input_name, data);
if (ret < 0) {
if (data->multi_index == 0)
gpio_free(data->gpio);
dev_err(&data->client->dev,
"Fail to request irq:%d ret=%d\n", irq, ret);
return ret;
}
}
return ret;
}
static int sensor_input_init(struct sensor_data *data)
{
int ret;
struct input_dev *input;
SENSOR_DBG(DBG_LEVEL3, data->dbg_on, "%s", data->config->input_name);
input = input_allocate_device();
if (!input) {
dev_err(&data->client->dev, "input device allocate failed\n");
return -ENOMEM;
}
input->name = data->config->input_name;
input->id.bustype = BUS_I2C;
input->dev.parent = &data->client->dev;
set_bit(data->config->event_type, input->evbit);
if (data->config->indexs[GET_DATA_X].num) {
if (data->config->event_type == EV_REL)
set_bit(REL_X, input->relbit);
else if (data->config->event_type == EV_ABS)
set_bit(ABS_X, input->absbit);
}
if (data->config->indexs[GET_DATA_Y].num) {
if (data->config->event_type == EV_REL)
set_bit(REL_Y, input->relbit);
else if (data->config->event_type == EV_ABS)
set_bit(ABS_Y, input->absbit);
}
if (data->config->indexs[GET_DATA_Z].num) {
if (data->config->event_type == EV_REL)
set_bit(REL_Z, input->relbit);
else if (data->config->event_type == EV_ABS)
set_bit(ABS_Z, input->absbit);
}
ret = input_register_device(input);
if (ret) {
dev_err(&data->client->dev,
"unable to register input device %s:%d\n",
input->name, ret);
goto err;
}
data->input_dev = input;
return 0;
err:
input_free_device(input);
return ret;
}
static ssize_t sensor_interval_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct sensor_data *data = i2c_get_clientdata(client);
int interval;
SENSOR_DBG(DBG_LEVEL3, data->dbg_on, "%s", data->config->input_name);
mutex_lock(data->lock);
interval = data->poll_interval;
mutex_unlock(data->lock);
return sprintf(buf, "%d\n", interval);
}
static ssize_t sensor_interval_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
unsigned long interval;
struct i2c_client *client = to_i2c_client(dev);
struct sensor_data *data = i2c_get_clientdata(client);
SENSOR_DBG(DBG_LEVEL1, data->dbg_on, "%s", data->config->input_name);
if (kstrtoul(buf, 0, &interval))
return -EINVAL;
SENSOR_DBG(DBG_LEVEL1, data->dbg_on, "%d-->%d",
data->poll_interval, (int)interval);
/*check whether interval is belong to [min, max]*/
if (data->config->min_poll_interval != SENSOR_INVALID_INTERVAL &&
interval < data->config->min_poll_interval) {
interval = data->config->min_poll_interval;
}
if (data->config->max_poll_interval != SENSOR_INVALID_INTERVAL &&
interval > data->config->max_poll_interval) {
interval = data->config->max_poll_interval;
}
mutex_lock(data->lock);
/*enable, then set poll*/
if (data->poll_interval == interval)
goto out;
sensor_update_odr(data, interval);
data->poll_interval = interval;
sensor_launch_work(data);
out:
mutex_unlock(data->lock);
return count;
}
static ssize_t sensor_enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct sensor_data *data = i2c_get_clientdata(client);
int enabled;
SENSOR_DBG(DBG_LEVEL1, data->dbg_on, "%s", data->config->input_name);
mutex_lock(data->lock);
enabled = (data->state == STATE_EN);
mutex_unlock(data->lock);
return sprintf(buf, "%d\n", enabled);
}
#define SENSOR_SYSFS_POWERON 1
#define SENSOR_SYSFS_POWERDOWN 0
static ssize_t sensor_enable_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct sensor_data *data = i2c_get_clientdata(client);
unsigned long val;
SENSOR_DBG(DBG_LEVEL1, data->dbg_on, "%s", data->config->input_name);
if (kstrtoul(buf, 0, &val))
return -EINVAL;
SENSOR_DBG(DBG_LEVEL1, data->dbg_on, " %x", (int)val);
if (val != SENSOR_SYSFS_POWERON && val != SENSOR_SYSFS_POWERDOWN)
return -EINVAL;
mutex_lock(data->lock);
/*both STATE_DIS and SATE_SUS -> STATE_EN*/
if (val)
sensor_enable(data);
else
sensor_disable(data);
mutex_unlock(data->lock);
return count;
}
static DEVICE_ATTR(poll, S_IRUGO|S_IWUSR,
sensor_interval_show, sensor_interval_store);
static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR,
sensor_enable_show, sensor_enable_store);
static struct attribute *sensor_default_attributes[] = {
&dev_attr_poll.attr,
&dev_attr_enable.attr,
NULL
};
static struct attribute_group sensor_default_attribute_group = {
.attrs = sensor_default_attributes
};
union sysfsapi_action {
void (*invalid)(void);
ssize_t (*show)(struct device *, struct device_attribute *, char *);
ssize_t (*store)(struct device *,
struct device_attribute *, const char *, size_t);
};
union sysfsapi_action sysfsapi_table[SENSOR_ACTION_RESERVE] = {
/*INIT*/
{ .invalid = NULL },
{ .invalid = NULL },
/*ENABLE*/
{ .invalid = NULL },
{ .invalid = NULL },
/*INT_ACK*/
{ .invalid = NULL },
/*GET_DATE_X*/
{ .invalid = NULL },
{ .invalid = NULL },
{ .invalid = NULL },
{ .show = sensor_range_show },
{ .store = sensor_range_store },
{ .show = attr_get_selftest },
{ .store = attr_set_selftest },
};
static struct device general_sensor_device;
static void sysfs_interfaces_link(struct device *dev)
{
static int general_sensor_num = 0;
int ret = 0;
char name[32] = {0};
sprintf(name, "sensor%d", general_sensor_num++);
ret = sysfs_create_link(&general_sensor_device.kobj, &dev->kobj, name);
if (ret) {
dev_warn(dev, "Fail to link %s\n", dev_name(dev));
}
}
static int create_sysfs_interfaces(struct sensor_data *data)
{
int ret = 0;
struct device_attribute *dev_attr;
int i;
int sub = 0;
SENSOR_DBG(DBG_LEVEL3, data->dbg_on, "%s", data->client->name);
/*default poll and enable sysfs device files*/
/*fix me: in remove. this will be obsolete after sync with user xml*/
if (strlen(data->config->attr_name)) {
sensor_default_attribute_group.name = data->config->attr_name;
sub = 1;
} else {
sensor_default_attribute_group.name = NULL;
}
ret = sysfs_create_group(&data->attr_dev->kobj,
&sensor_default_attribute_group);
if (ret) {
dev_err(data->attr_dev, "sysfs can not create group\n");
return ret;
}
sysfs_interfaces_link(data->attr_dev);
/*developer defined */
if (!data->config->sysfs_entries)
return ret;
dev_attr = kzalloc(data->config->sysfs_entries *
sizeof(struct device_attribute),
GFP_KERNEL);
if (!dev_attr) {
dev_err(data->attr_dev, "Fail to alloc memory\n");
return -ENOMEM;
} else
data->dev_attr = dev_attr;
for (i = 0; i < data->config->sysfs_entries; i++, dev_attr++) {
dev_attr->attr.name = data->config->sysfs_table[i].name;
dev_attr->attr.mode = S_IRUGO|S_IWUSR;
if (data->config->sysfs_table[i].type == DATA_ACTION) {
dev_attr->show = sensor_sysfs_data_acton_show;
dev_attr->store = sensor_sysfs_data_acton_store;
} else if (data->config->sysfs_table[i].type == SENSOR_ACTION) {
enum sensor_action action =
data->config->sysfs_table[i].action.sensor.show;
dev_attr->show = sysfsapi_table[action].show;
action =
data->config->sysfs_table[i].action.sensor.store;
dev_attr->store = sysfsapi_table[action].store;
if (!dev_attr->store || !dev_attr->show) {
dev_err(data->attr_dev, "Wrong sys action\n");
goto err;
}
} else {
dev_err(data->attr_dev, "Nonsupported action\n");
goto err;
}
if (!sub) {
if (device_create_file(data->attr_dev, dev_attr))
goto err;
} else {
/*fix me. some are subdir*/
if (device_create_file(data->attr_dev, dev_attr))
goto err;
}
}
return ret;
err:
for (i = i - 1, dev_attr--; i >= 0; i--, dev_attr--)
device_remove_file(data->attr_dev, dev_attr);
kfree(data->dev_attr);
data->dev_attr = NULL;
return ret;
}
static void remove_sysfs_interfaces(struct sensor_data *data)
{
int i;
struct device_attribute *dev_attr = data->dev_attr;
/*remove default */
sysfs_remove_group(&data->attr_dev->kobj,
&sensor_default_attribute_group);
/*remove others*/
for (i = 0; i < data->config->sysfs_entries; i++, dev_attr++)
device_remove_file(data->attr_dev, dev_attr);
kfree(data->dev_attr);
data->dev_attr = NULL;
/*release kobj for multi device*/
if (data->config->shared_nums > 1) {
device_del(data->attr_dev);
data->attr_dev = NULL;
}
}
static int sensor_rawdata_proc_init(struct sensor_data *data)
{
int i;
mutex_lock(&sensor_proc_lock);
for (i = 0; i < MAX_SENSOR_DRIVERS; i++) {
struct sensor_rawdata_proc *proc = rawdata_proc_tbl[i];
if (proc && !strncmp(proc->name,
data->config->name, strlen(proc->name))) {
data->rawdata_proc = proc;
goto out;
}
}
data->rawdata_proc = NULL;
out:
mutex_unlock(&sensor_proc_lock);
return 0;
}
/*
* sensor private data init
*/
static int sensor_data_init(struct i2c_client *client,
struct sensor_data *data,
struct sensor_config *config)
{
int ret = 0;
int i;
int nums = config->shared_nums;
u8 *regbuf = (u8 *)&data[nums];
/*share lock with the first one*/
struct mutex *lock = (struct mutex *)&data->real_lock;
SENSOR_DBG(DBG_LEVEL3, DBG_ALL_SENSORS, "shared nums:%d", nums);
/*hook first private data for multi devices*/
i2c_set_clientdata(client, data);
mutex_init(lock);
for (i = 0; i < nums; i++, data++) {
/*init*/
data->config = config;
stack_init(&data->stack);
data->lock = lock;
data->regbuf = regbuf;
data->client = client;
data->state = STATE_DIS;
data->state_suspend = STATE_DIS;
data->launched = 0;
data->poll_interval = data->config->default_poll_interval;
data->range = data->config->default_range;
if (config->method != POLL) {
data->gpio =
acpi_get_gpio_by_index(&client->dev, 0, NULL);
if (data->gpio < 0) {
dev_warn(&client->dev,
"Fail to get gpio pin by ACPI\n");
data->gpio = config->gpio_num;
}
if (data->gpio < 0) {
dev_err(&client->dev, "Need to specify gpio\n");
goto err;
}
}
sensor_rawdata_proc_init(data);
data->multi_index = i;
data->share_irq_seq = regbuf + config->sensor_regs;
/*init data->attr_dev*/
if (nums == 1) {
/*single device*/
data->attr_dev = &client->dev;
} else {
/*multi device*/
struct device *dev;
dev = kzalloc(sizeof(struct device), GFP_KERNEL);
if (!dev) {
ret = -ENOMEM;
goto err;
}
device_initialize(dev);
dev->parent = &client->dev;
dev_set_name(dev, config->input_name);
ret = device_add(dev);
if (ret) {
dev_err(&client->dev,
"Fail to register device\n");
kfree(dev);
goto err;
}
data->attr_dev = dev;
dev_set_drvdata(dev, data);
}
config = (struct sensor_config *)((char *)config + config->size);
}
return 0;
err:
for (i = i - 1, data--; i >= 0; i--, data--) {
device_del(data->attr_dev);
kfree(data->attr_dev);
data->attr_dev = NULL;
}
return ret;
}
/*
* record registered driver for remove
*/
static int registered_drivers;
static int registered_devices;
static struct i2c_driver *i2c_sensor_drivers[MAX_SENSOR_DRIVERS] = { NULL };
static struct i2c_client *i2c_sensor_devices[MAX_SENSOR_DRIVERS] = { NULL };
static int failed_drivers;
static int failed_devices;
static char *i2c_failed_driver[MAX_SENSOR_DRIVERS] = { NULL };
static struct i2c_client *i2c_failed_device[MAX_SENSOR_DRIVERS] = { NULL };
static int sensor_probe(struct i2c_client *client,
const struct i2c_device_id *devid)
{
int ret = 0;
struct sensor_config *config;
struct sensor_data *data = NULL;
int i;
SENSOR_DBG(DBG_LEVEL3, DBG_ALL_SENSORS, "i2c device:%s", devid->name);
config = (struct sensor_config *)devid->driver_data;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_I2C | I2C_FUNC_SMBUS_I2C_BLOCK)) {
dev_err(&client->dev, "client not i2c capable\n");
return -ENODEV;
}
data = kzalloc(config->shared_nums * sizeof(struct sensor_data) +
config->sensor_regs + 1/*share irq sequence*/,
GFP_KERNEL);
if (!data) {
return -ENOMEM;
dev_err(&client->dev, "Fail to alloc memory\n");
}
ret = sensor_data_init(client, data, config);
if (ret) {
dev_err(&client->dev, "sensor_data_init\n");
kfree(data);
return ret;
}
for (i = 0; i < config->shared_nums; i++) {
/*don't power on device*/
ret = sensor_init(data + i);
if (ret) {
dev_err(&client->dev, "sensor_init\n");
i2c_failed_driver[failed_drivers++] = config->name;
i2c_failed_device[failed_devices++] = client;
goto err;
}
ret = sensor_input_init(data + i);
if (ret) {
dev_err(&client->dev, "sensor_input_init\n");
goto err;
}
ret = sensor_get_data_init(data + i);
if (ret) {
dev_err(&client->dev, "sensor_get_data_init\n");
goto err;
}
ret = create_sysfs_interfaces(data + i);
if (ret) {
dev_err(&client->dev, "create_sysfs_interfaces\n");
goto err;
}
if (general_sensor_nums <= MAX_SENSOR_DRIVERS - 1) {
(data + i)->dbg_on = (1 << general_sensor_nums);
general_sensor_nums++;
} else {
dev_err(&client->dev, "Too many sensor drivers\n");
goto err;
}
sensor_add_data(data + i);
}
return ret;
err:
if (0 == i)
kfree(data);
return ret;
}
/*
* disable sensor device
* remove all info related to this sensor device which add in probe
*/
static int sensor_remove(struct i2c_client *client)
{
struct sensor_data *data = i2c_get_clientdata(client);
int num = data->config->shared_nums - 1;
for (data += num; num >= 0; num--, data--) {
remove_sysfs_interfaces(data);
if (data->config->method == INT ||
data->config->method == MIX) {
free_irq(gpio_to_irq(data->gpio), data);
if (num == 0)
gpio_free(data->gpio);
}
input_unregister_device(data->input_dev);
sensor_disable(data);
sensor_deinit(data);
sensor_remove_data(data);
}
data++;
kfree(data);
return 0;
}
static const struct dev_pm_ops sensor_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(sensor_suspend, sensor_resume)
};
static int register_sensor_driver(struct sensor_config *config)
{
struct i2c_device_id *i2c_ids;
struct i2c_driver *sensor_driver;
int ret;
sensor_driver = kzalloc(sizeof(struct i2c_driver) +
MAX_DEV_IDS * sizeof(struct i2c_device_id),
GFP_KERNEL);
if (!sensor_driver) {
ret = -ENOMEM;
printk(KERN_ERR "Fail to alloc memory in %s\n", __func__);
return ret;
}
sensor_driver->driver.name = config->name;
sensor_driver->driver.owner = THIS_MODULE;
#ifdef CONFIG_PM_SLEEP
sensor_driver->driver.pm = &sensor_pm_ops;
#endif
sensor_driver->probe = sensor_probe;
sensor_driver->remove = sensor_remove;
/*set name and private config for this sensor*/
i2c_ids = (struct i2c_device_id *)&sensor_driver[1];
sensor_driver->id_table = i2c_ids;
i2c_ids->driver_data = (unsigned long)config;
strlcpy(i2c_ids->name, config->name, I2C_NAME_SIZE);
SENSOR_DBG(DBG_LEVEL3, DBG_ALL_SENSORS,
"register i2c driver:%s", i2c_ids->name);
ret = i2c_add_driver(sensor_driver);
if (ret) {
kfree(sensor_driver);
printk(KERN_ERR "Fail to register i2c driver\n");
} else
i2c_sensor_drivers[registered_drivers++] = sensor_driver;
return ret;
}
static int register_sensor_device(struct sensor_config *config)
{
int ret = 0;
struct i2c_adapter *adapter;
struct i2c_client *client;
struct i2c_board_info info;
memset(&info, 0, sizeof(info));
strlcpy(info.type, config->name, I2C_NAME_SIZE);
adapter = i2c_get_adapter(config->i2c_bus);
if (!adapter)
return -ENODEV;
else {
int addr;
int valid_dev = 0;
for (addr = 0; addr < MAX_I2C_ADDRS &&
config->i2c_addrs[addr] != INVALID_I2C_ADDR; addr++) {
info.addr = config->i2c_addrs[addr];
client = i2c_new_device(adapter, &info);
if (!client) {
printk(KERN_ERR "Fail to add i2c device%d:%d\n",
config->i2c_bus, info.addr);
continue;
}
/*more than one addr, check whether
this is valid device for current addr*/
if (config->i2c_addrs[1] != INVALID_I2C_ADDR) {
ret = i2c_smbus_read_byte_data(client,
config->test_reg_addr);
if (ret < 0) {
i2c_unregister_device(client);
continue;
}
}
i2c_sensor_devices[registered_devices++] = client;
valid_dev = 1;
break;
}
if (!valid_dev)
return -EINVAL;
else
return 0;
}
}
static void unregister_sensor_drivers(void)
{
int num = registered_drivers - 1;
while (num >= 0) {
if (i2c_sensor_drivers[num]) {
i2c_del_driver(i2c_sensor_drivers[num]);
kfree(i2c_sensor_drivers[num]);
i2c_sensor_drivers[num] = NULL;
}
num--;
}
registered_drivers = 0;
}
static void unregister_failed_driver(char *name) __attribute__((unused));
static void unregister_failed_driver(char *name)
{
int failed_num = failed_drivers - 1;
while (failed_num >= 0) {
char *failed_name = i2c_failed_driver[failed_num];
if (failed_name && !strcmp(failed_name, name)) {
int num = registered_drivers - 1;
while (num >= 0) {
struct i2c_driver *drv = i2c_sensor_drivers[num];
if (drv && !strcmp(drv->driver.name, name)) {
i2c_del_driver(drv);
kfree(i2c_sensor_drivers[num]);
i2c_sensor_drivers[num] = NULL;
i2c_failed_driver[failed_num] = NULL;
return;
}
num--;
}
}
failed_num--;
}
}
static void unregister_sensor_devices(void)
{
int num = registered_devices - 1;
while (num >= 0) {
if (i2c_sensor_devices[num]) {
/*fix me*/
i2c_unregister_device(i2c_sensor_devices[num]);
i2c_sensor_devices[num] = NULL;
}
num--;
}
}
static void unregister_failed_devices(void)
{
int failed_num = failed_devices - 1;
while (failed_num >= 0) {
struct i2c_client *fail_cli = i2c_failed_device[failed_num];
int num = registered_devices - 1;
while (num >= 0) {
struct i2c_client *reg_cli = i2c_sensor_devices[num];
if (reg_cli && reg_cli == fail_cli){
i2c_unregister_device(fail_cli);
i2c_failed_device[failed_num] = NULL;
i2c_sensor_devices[num] = NULL;
}
num--;
}
failed_num--;
}
failed_devices = 0;
}
/*
* register one i2c driver and i2c device for each config(maybe multi)
* num: how many sensor config
*/
static int sensor_parse_config(int num, struct sensor_config *configs)
{
int ret = 0;
int shared_nums;
general_sensor_nums = 0;
while (num > 0) {
/*two methods to support multi drivers for one i2c slave*/
unregister_failed_devices();
//unregister_failed_driver(configs->name);
ret = register_sensor_driver(configs);
if (ret) {
printk(KERN_ERR "Fail to register sensor driver\n");
}
if (configs->i2c_bus != INVALID_I2C_BUS) {
ret = register_sensor_device(configs);
/*skip this error in case of multi register*/
if (ret) {
printk(KERN_WARNING
"Fail to register sensor device\n");
}
}
shared_nums = configs->shared_nums;
num -= shared_nums;
while (shared_nums > 0) {
shared_nums--;
configs = (struct sensor_config *)
((char *)configs + configs->size);
}
}
return 0;
}
static struct sensor_config_image *sensor_image;
static int sensor_general_attached;
static int start_method;
static void sensor_firmware_cb(const struct firmware *fw_entry, void *ctx)
{
int ret;
if (!fw_entry) {
printk(KERN_ERR "Fail to request sensor firmware\n");
return;
}
sensor_image = (struct sensor_config_image *)fw_entry->data;
if (start_method != SG_FORCE_START &&
(sensor_image->flags & SG_FLAGS_BOOT_DISABLE)) {
ret = -EINVAL;
goto out;
}
sensor_image = kmalloc(fw_entry->size, GFP_KERNEL);
if (!sensor_image) {
printk(KERN_ERR "Fail to alloc mem\n");
ret = -ENOMEM;
goto out;
}
memcpy((void *)sensor_image, fw_entry->data, fw_entry->size);
#ifdef CONFIG_GENERAL_SENSOR_DEBUG
/*set default debug switch*/
sensor_general_debug_sensors = sensor_image->dbg_sensors;
sensor_general_debug_level = sensor_image->dbg_level;
#endif
ret = sensor_parse_config(sensor_image->num,
(struct sensor_config *)&sensor_image->configs);
if (ret) {
printk(KERN_ERR "Fail to parse config image\n");
kfree(sensor_image);
sensor_image = NULL;
} else
sensor_general_attached = 1;
out:
release_firmware(fw_entry);
return;
}
static int sensor_general_start(int start)
{
start_method = start;
return request_firmware_nowait(THIS_MODULE, true,
GENERAL_SENSOR_FIRMWARE,
&general_sensor_device, GFP_KERNEL, NULL,
sensor_firmware_cb);
}
static ssize_t sensor_general_start_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int ret;
unsigned long val;
if (kstrtoul(buf, 0, &val))
return -EINVAL;
if (!sensor_general_attached && val) {
ret = sensor_general_start(val);
if (ret)
printk(KERN_ERR "Fail to start general sensor\n");
} else if (sensor_general_attached && !val) {
printk(KERN_DEBUG "[%d]%s, unattach general sensor driver\n",
__LINE__, __func__);
unregister_sensor_drivers();
unregister_sensor_devices();
kfree(sensor_image);
sensor_image = NULL;
sensor_general_attached = 0;
}
return count;
}
static DEVICE_ATTR(start, S_IRUGO|S_IWUSR,
NULL, sensor_general_start_store);
#ifdef CONFIG_GENERAL_SENSOR_DEBUG
static ssize_t sensor_general_debug_sensors_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
ret = sprintf(buf, "%08x\n", sensor_general_debug_sensors);
return ret;
}
static ssize_t sensor_general_debug_sensors_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
unsigned long val;
if (kstrtoul(buf, 0, &val))
return -EINVAL;
sensor_general_debug_sensors = val;
return count;
}
static DEVICE_ATTR(dbgsensors, S_IRUGO|S_IWUSR,
sensor_general_debug_sensors_show,
sensor_general_debug_sensors_store);
static ssize_t sensor_general_debug_level_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
ret = sprintf(buf, "%d\n", sensor_general_debug_level);
return ret;
}
static ssize_t sensor_general_debug_level_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
unsigned long val;
if (kstrtoul(buf, 0, &val))
return -EINVAL;
sensor_general_debug_level = val;
return count;
}
static DEVICE_ATTR(dbglevel, S_IRUGO|S_IWUSR,
sensor_general_debug_level_show,
sensor_general_debug_level_store);
static ssize_t sensor_general_time_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret = 0;
int i;
for (i = 0; i < general_sensor_nums; i++) {
if (sensor_general_time & (1 << i)) {
s64 ns = ktime_to_ns(sensor_time[i].time);
int times = sensor_time[i].times;
s64 onetime = ns;
if (times)
do_div(onetime, times);
else
onetime = 0;
ret += sprintf(buf + ret,
"Sensor %d times:%10d time:%20lld ns %10d ns/times\n",
i, times, ns, (int)onetime);
} else {
sensor_time[i].times = 0;
sensor_time[i].time.tv64 = 0;
}
}
return ret;
}
static ssize_t sensor_general_time_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
unsigned long val;
if (kstrtoul(buf, 0, &val))
return -EINVAL;
sensor_general_time = val;
return count;
}
static DEVICE_ATTR(time, S_IRUGO|S_IWUSR,
sensor_general_time_show,
sensor_general_time_store);
static struct attribute *sensor_general_attributes[] = {
&dev_attr_start.attr,
&dev_attr_dbgsensors.attr,
&dev_attr_dbglevel.attr,
&dev_attr_time.attr,
NULL
};
#else
static struct attribute *sensor_general_attributes[] = {
&dev_attr_start.attr,
NULL
};
#endif
static struct attribute_group sensor_general_attribute_group = {
.attrs = sensor_general_attributes
};
static void sensor_data_op_init(void)
{
data_op_array[OP_LOGIC_EQ] = data_op_logic_eq;
data_op_array[OP_LOGIC_NEQ] = data_op_logic_neq;
data_op_array[OP_LOGIC_GREATER] = data_op_logic_greater;
data_op_array[OP_LOGIC_LESS] = data_op_logic_less;
data_op_array[OP_LOGIC_GE] = data_op_logic_ge;
data_op_array[OP_LOGIC_LE] = data_op_logic_le;
data_op_array[OP_LOGIC_AND] = data_op_logic_and;
data_op_array[OP_LOGIC_OR] = data_op_logic_or;
data_op_array[OP_ARI_ADD] = data_op_ari_add;
data_op_array[OP_ARI_SUB] = data_op_ari_sub;
data_op_array[OP_ARI_MUL] = data_op_ari_mul;
data_op_array[OP_ARI_DIV] = data_op_ari_div;
data_op_array[OP_ARI_MOD] = data_op_ari_mod;
data_op_array[OP_BIT_OR] = data_op_bit_or;
data_op_array[OP_BIT_AND] = data_op_bit_and;
data_op_array[OP_BIT_LSL] = data_op_bit_lsl;
data_op_array[OP_BIT_LSR] = data_op_bit_lsr;
data_op_array[OP_BIT_NOR] = data_op_bit_nor;
data_op_array[OP_ENDIAN_BE16] = data_op_be16;
data_op_array[OP_ENDIAN_BE16_UN] = data_op_be16u;
data_op_array[OP_ENDIAN_BE24] = data_op_be24;
data_op_array[OP_ENDIAN_BE32] = data_op_be32;
data_op_array[OP_ENDIAN_LE16] = data_op_le16;
data_op_array[OP_ENDIAN_LE16_UN] = data_op_le16u;
data_op_array[OP_ENDIAN_LE24] = data_op_le24;
data_op_array[OP_ENDIAN_LE32] = data_op_le32;
data_op_array[OP_MIN] = data_op_min;
data_op_array[OP_MAX] = data_op_max;
}
static int __init sensor_general_init(void)
{
int ret;
device_initialize(&general_sensor_device);
general_sensor_device.parent = NULL;
dev_set_name(&general_sensor_device, "generalsensor");
ret = device_add(&general_sensor_device);
if (ret) {
printk(KERN_ERR "Fail to register device\n");
return ret;
}
#ifdef CONFIG_GENERAL_SENSOR_DEBUG
sensor_general_time = 0;
#endif
sensor_image = NULL;
sensor_general_attached = 0;
registered_drivers = 0;
registered_devices = 0;
failed_drivers = 0;
failed_devices = 0;
/*init callback of data operations*/
sensor_data_op_init();
/*attributes*/
ret = sysfs_create_group(&general_sensor_device.kobj,
&sensor_general_attribute_group);
if (ret) {
dev_err(&general_sensor_device, "sysfs can not create group\n");
goto err;
}
/*trigger at kernel boot time*/
#ifdef CONFIG_GENERAL_SENSOR_BOOT
ret = sensor_general_start(SG_START);
if (ret) {
dev_err(&general_sensor_device, "error sensor general init\n");
sysfs_remove_group(&general_sensor_device.kobj,
&sensor_general_attribute_group);
goto err;
}
#endif
return 0;
err:
device_del(&general_sensor_device);
return ret;
}
static void __exit sensor_general_exit(void)
{
unregister_sensor_drivers();
unregister_sensor_devices();
kfree(sensor_image);
sensor_image = NULL;
sysfs_remove_group(&general_sensor_device.kobj,
&sensor_general_attribute_group);
device_del(&general_sensor_device);
}
module_init(sensor_general_init);
module_exit(sensor_general_exit);
MODULE_DESCRIPTION("General Sensor Driver");
MODULE_AUTHOR("PSI IO&Sensor Team");
MODULE_LICENSE("GPL");