光感传感器 芯片stk3171 linux驱动程序

/* drivers/input/sensors/access/kxtik.c

*

  • Copyright © 2012-2015 ROCKCHIP.
  • 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>

#define ALS_CMD 0x01

#define ALS_DT1 0x02

#define ALS_DT2 0X03

#define ALS_THDH1 0X04

#define ALS_THDH2 0X05

#define ALS_THDL1 0X06

#define ALS_THDL2 0X07

#define STA_TUS 0X08

#define PS_CMD 0X09

#define PS_DT 0X0A

#define PS_THDH 0X0B

#define PS_THDL 0X0C

#define SW_RESET 0X80

//ALS_CMD

#define ALS_SD_ENABLE (0<<0)

#define ALS_SD_DISABLE (1<<0)

#define ALS_INT_DISABLE (0<<1)

#define ALS_INT_ENABLE (1<<1)

#define ALS_1T_100MS (0<<2)

#define ALS_2T_200MS (1<<2)

#define ALS_4T_400MS (2<<2)

#define ALS_8T_800MS (3<<2)

#define ALS_RANGE_57671 (0<<6)

#define ALS_RANGE_28836 (1<<6)

//PS_CMD

#define PS_SD_ENABLE (0<<0)

#define PS_SD_DISABLE (1<<0)

#define PS_INT_DISABLE (0<<1)

#define PS_INT_ENABLE (1<<1)

#define PS_10T_2MS (0<<2)

#define PS_15T_3MS (1<<2)

#define PS_20T_4MS (2<<2)

#define PS_25T_5MS (3<<2)

#define PS_CUR_100MA (0<<4)

#define PS_CUR_200MA (1<<4)

#define PS_SLP_10MS (0<<5)

#define PS_SLP_30MS (1<<5)

#define PS_SLP_90MS (2<<5)

#define PS_SLP_270MS (3<<5)

#define TRIG_PS_OR_LS (0<<7)

#define TRIG_PS_AND_LS (1<<7)

//STA_TUS

#define STA_PS_INT (1<<5)

#define STA_ALS_INT (1<<4)

/****operate according to sensor chip:start/

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 result = 0;

int status = 0;

复制代码
sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);

//register setting according to chip datasheet
if(!enable)
{
	status = ALS_SD_DISABLE;
	sensor->ops->ctrl_data |= status;
}
else
{
	status = ~ALS_SD_DISABLE;
	sensor->ops->ctrl_data &= status;
}

DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);
result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
if(result)
	printk("%s:fail to active sensor\n",__func__);

if(enable)
sensor->ops->report(sensor->client);

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;

复制代码
result = sensor->ops->active(client,0,0);
if(result)
{
	printk("%s:line=%d,error\n",__func__,__LINE__);
	return result;
}

sensor->status_cur = SENSOR_OFF;

result = sensor_write_reg(client, SW_RESET, 0);
if(result)
{
	printk("%s:line=%d,error\n",__func__,__LINE__);
	return result;
}

result = sensor_write_reg(client, ALS_THDH1, 0);//it is important,if not then als can not trig intterupt
if(result)
{
	printk("%s:line=%d,error\n",__func__,__LINE__);
	return result;
}

result = sensor_write_reg(client, ALS_THDH2, 0);
if(result)
{
	printk("%s:line=%d,error\n",__func__,__LINE__);
	return result;
}

sensor->ops->ctrl_data |= ALS_1T_100MS;

if(sensor->pdata->irq_enable)
	sensor->ops->ctrl_data |= ALS_INT_ENABLE;
else
	sensor->ops->ctrl_data &= ~ALS_INT_ENABLE;

result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
if(result)
{
	printk("%s:line=%d,error\n",__func__,__LINE__);
	return result;
}

return result;

}

static int light_report_value(struct input_dev *input, int data)

{

unsigned char index = 0;

if(data <= 100){

index = 0;goto report;

}

else if(data <= 1600){

index = 1;goto report;

}

else if(data <= 2250){

index = 2;goto report;

}

else if(data <= 3200){

index = 3;goto report;

}

else if(data <= 6400){

index = 4;goto report;

}

else if(data <= 12800){

index = 5;goto report;

}

else if(data <= 26000){

index = 6;goto report;

}

else{

index = 7;goto report;

}

report:

input_report_abs(input, ABS_MISC, index);

input_sync(input);

复制代码
return index;

}

static int sensor_report_value(struct i2c_client *client)

{

struct sensor_private_data *sensor =

(struct sensor_private_data *) i2c_get_clientdata(client);

int result = 0;

int value = 0;

char buffer2 = {0};

char index = 0;

复制代码
if(sensor->ops->read_len < 2)	//sensor->ops->read_len = 2
{
	printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);
	return -1;
}

memset(buffer, 0, 2);

buffer[0] = sensor->ops->read_reg;
result = sensor_rx_data(client, buffer, sensor->ops->read_len);
if(result)
{
	printk("%s:line=%d,error\n",__func__,__LINE__);
	return result;
}

value = (buffer[0] << 8) | buffer[1];


index = light_report_value(sensor->input_dev, value);

DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, value,index);

if(sensor->pdata->irq_enable)
{
	if(sensor->ops->int_status_reg)
	{
		value = sensor_read_reg(client, sensor->ops->int_status_reg);
	}

	if(value & STA_ALS_INT)
	{
		value &= ~STA_ALS_INT;
		result = sensor_write_reg(client, sensor->ops->int_status_reg,value);	//clear int
		if(result)
		{
			printk("%s:line=%d,error\n",__func__,__LINE__);
			return result;
		}
	}
}


return result;

}

struct sensor_operate light_stk3171_ops = {

.name = "ls_stk3171",

.type = SENSOR_TYPE_LIGHT, //sensor type and it should be correct

.id_i2c = LIGHT_ID_STK3171, //i2c id number

.read_reg = ALS_DT1, //read data

.read_len = 2, //data length

.id_reg = SENSOR_UNKNOW_DATA, //read device id from this register

.id_data = SENSOR_UNKNOW_DATA, //device id

.precision = 16, //8 bits

.ctrl_reg = ALS_CMD, //enable or disable

.int_status_reg = STA_TUS, //intterupt status register

.range = {100,65535}, //range

.brightness ={10,255}, //brightness

.trig = IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,

.active = sensor_active,

.init = sensor_init,

.report = sensor_report_value,

};

/****operate according to sensor chip:end /

static int light_stk3171_probe(struct i2c_client *client,

const struct i2c_device_id *devid)

{

return sensor_register_device(client, NULL, devid, &light_stk3171_ops);

}

static int light_stk3171_remove(struct i2c_client *client)

{

return sensor_unregister_device(client, NULL, &light_stk3171_ops);

}

static const struct i2c_device_id light_stk3171_id\[\] = {

{"ls_stk3171", LIGHT_ID_STK3171},

{}

};

static struct i2c_driver light_stk3171_driver = {

.probe = light_stk3171_probe,

.remove = light_stk3171_remove,

.shutdown = sensor_shutdown,

.id_table = light_stk3171_id,

.driver = {

.name = "light_stk3171",

#ifdef CONFIG_PM

.pm = &sensor_pm_ops,

#endif

},

};

module_i2c_driver(light_stk3171_driver);

MODULE_AUTHOR("xxx");

MODULE_DESCRIPTION("stk3171 light driver");

MODULE_LICENSE("GPL");

相关推荐
NamoAmitabha1286 小时前
libpng12-0 1.2.54-1ubuntu1.1 (amd64 binary) in ubuntu xenial
linux·ubuntu20.4
Madison-No76 小时前
搭建项目测试环境
linux·运维·服务器·python
吴声子夜歌7 小时前
Shell编程实例——编写安全的shell脚本(二)
linux·运维·shell
悠悠121388 小时前
微服务通信别只看性能:REST 与 gRPC 的 6 个选型判断和一次 502 故障复盘
运维·服务器
xiaoye-duck9 小时前
《Linux 网络编程》深入理解 IP 协议(二):网段划分、私有 IP 与 NAT 地址转换
linux·网络·ip
云老大-阿里云国际站代理商9 小时前
华为云国际站服务代理商:NAT网关怎么配?多台ECS共用公网IP要注意什么
服务器·华为云·云计算
zx_7414848110 小时前
【Linux入门】Shell 函数、正则表达式与文本处理:cut 与 awk
linux·运维·正则表达式
Zenova EdgeOS10 小时前
Linux dmesg 工业边缘实战:内核日志过滤、持久化与故障定位
linux·运维·边缘计算·工业边缘·dmesg·内核日志
金士顿10 小时前
System.Text.Json Source Generator 深度解析:为什么 Native AOT 不喜欢反射
linux·asp.net core·arm64·net·native aot
wdfk_prog11 小时前
ROS教程08:从 TransportTCP::connect() 追到 TCPROS Connection Header、序列化与 Socket 数据传输
运维·缓存·docker·容器·ros