光感传感器 芯片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 buffer[2] = {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");

相关推荐
softbangong几秒前
816-批量将图片分别转为pdf,文件夹下所有图片转为一个pdf
java·服务器·pdf·图片处理·图片转pdf·pdf工具·批量转换
C^h1 分钟前
RTthread中的内存池理解
linux·数据库·c++·算法·嵌入式
司南-70493 分钟前
claude初探- 国内镜像安装linux版claude
linux·运维·服务器·人工智能·后端
为美好的生活献上中指6 分钟前
*Java 沉淀重走长征路*之——《Linux 从入门到企业实战:一套六步法,带你打通运维与开发的任督二脉》
java·linux·运维·开发语言·阿里云·华为云·linux命令
何妨呀~8 分钟前
Docker部署与配置全攻略
运维·docker·容器
the sun3411 分钟前
从Ubuntu迁移到QEMU驱动开发
linux·驱动开发·ubuntu
犽戾武16 分钟前
机械臂 VR 遥操作调试日志记录
linux·服务器·网络
路由侠内网穿透19 分钟前
本地部署开源 LLM 应用观测与调试平台 Langfuse 并实现外部访问
运维·服务器·数据库·物联网·开源
SPC的存折19 分钟前
1、Ansible之Ansible安装与入门
linux·数据库·ansible
liulilittle26 分钟前
eBPF tc prog
服务器·网络·c++·网络协议·tcp/ip·性能·perf