OrangePi3 LTS 驱动开发-i2c通信(二)

该文章详细介绍了在OrangePi3LTS平台上针对veml7700光感芯片的驱动开发过程,包括i2c_driver的注册、初始化、节点创建和input设备的注册。文中提供了i2c读写函数以及与veml7700交互的接口,同时展示了如何通过sysfs创建电源模式、光感值等属性的读写功能。
摘要由CSDN通过智能技术生成

OrangePi3 LTS 驱动开发-感光芯片veml7700

kernel版本:orange-pi-5.10-media
dts配置在上一章的基础上增加以下内容:

&i2c0 {
	clock-frequency = <100000>;
	status = "okay";
	// at24c02@50{
	// 	compatible = "atmel,24c02";
	// 	reg = <0x50>;
	// 	status = "okay";
	// };
	veml7700@10{
		compatible = "max,veml7700";
		reg = <0x10>;
		status = "okay";
	};
};

驱动主要有以下几个步骤:
1、i2c_driver的注册
2、veml7700的初始化
3、相关节点的创建
4、input设备的注册以及上报。(这一步可以省略,app直接轮询解析也可以,但是上报input子系统后,我们可以解析/dev/input/eventx节点得到我们想要的光感lux值)

相关节点的解析:
cat /sys/class/max_veml7700/veml7700/support 为1 ,表示有光感设备,0表示没有光感设备。
enable 为开关
delay 驱动中上报input的时间间隔
power_mode 表示工作模式
gain 增益调整
it 整合时间调整
lux当前寄存器中光感数值,需要计算得到真实光感值,在APP里处理计算。

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/workqueue.h>

#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_device.h>
#include <linux/err.h>
#include <linux/i2c.h>

#include <linux/leds.h>
#include <linux/printk.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/delay.h>

#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/input.h>
#include <linux/of_irq.h>
#include <linux/irq.h>
#include "veml7700.h"

static int max_i2c_read(struct i2c_adapter *i2c_adap,
			   unsigned char address, unsigned char *wdata,
			   unsigned int wlen, unsigned char *rdata,unsigned int rlen)
{
	struct i2c_msg msgs[2];
	int res;
	if (!rdata || !i2c_adap) 
    {
		printk("%s:line=%d,error\n",__func__,__LINE__);
		return -EINVAL;
	}

msgs[0].addr = address;
msgs[0].flags = 0;	/* write */
msgs[0].buf = wdata;
msgs[0].len = wlen;

msgs[1].addr = address;
msgs[1].flags = I2C_M_RD;
msgs[1].buf = rdata;
msgs[1].len = rlen;

res = i2c_transfer(i2c_adap, msgs, 2);
if (res == 2)
	return 0;
else if(res == 0)
	return -EBUSY;
else
	return res;

return res;
}

int max_i2c_rx_data(struct i2c_client *client, char * txData,int tlen,char *rxData, int rlen)
{
	int ret = 0;
	int i = 0;
	for (i = 0; i < 2; i++) 
    {
		ret = max_i2c_read(client->adapter, client->addr, txData,tlen,rxData,rlen);
		if (ret < 0)
        {
			printk("max_i2c_rx_data error\n");
		}
        else
        {
		    break;
		}
	}
	return ret;
}

static int max_i2c_veml7700_read(struct i2c_client *client,uint8_t addr,uint8_t *r_data)
{
	return max_i2c_rx_data(client,&addr,1,r_data,2);
}

static int max_i2c_write(struct i2c_adapter *i2c_adap,
			    unsigned char address,
			    unsigned int len, unsigned char const *data)
{
	struct i2c_msg msgs[1];
	int res;

if (!data || !i2c_adap) 
{
	printk("%s:line=%d,error\n",__func__,__LINE__);
	return -EINVAL;
}

msgs[0].addr = address;
msgs[0].flags = 0;
msgs[0].buf = (unsigned char *)data;
msgs[0].len = len;

res = i2c_transfer(i2c_adap, msgs, 1);
//printk("i2c_transfer res = %d\n",res);
if (res == 1)
	return 0;
else if(res == 0)
	return -EBUSY;
else
	return res;
}

int max_i2c_tx_data(struct i2c_client *client, char *txData, int length)
{
	int ret = 0;
	int i = 0;

for (i = 0; i < 3; i++) 
{
	ret = max_i2c_write(client->adapter, client->addr, length, txData);
	if (!ret)
		break;
}
return ret;
}

static int max_i2c_veml7700_write(struct i2c_client *client,uint8_t addr,uint8_t *w_data)
{
	uint8_t w_buff[3] = {0};
	w_buff[0] = addr;
	w_buff[1] = w_data[0];
	w_buff[2] = w_data[1];
	return max_i2c_tx_data(client,w_buff,3);
}

static int max_veml7700_get_value(struct i2c_client *client,int command,int mask,int shift,unsigned short *value)
{
	int ret = 0;
	unsigned short tmp_value = 0;
	unsigned char r_data[2] = {0};

ret = max_i2c_veml7700_read(client,command,r_data);

if (ret != 0 )
{
	printk("max_i2c_veml7700_read error\n");
}
else
{
	tmp_value = ((r_data[1] << 8) | r_data[0]);
	tmp_value  = (tmp_value & mask ) >> shift;
	*value = tmp_value;
}

return ret;
}

static int max_veml7700_set_value(struct i2c_client *client,int command,int mask,int shift,unsigned short value)
{
	int ret;
	unsigned short tmp_value = 0;
	unsigned short w_value = 0;
	unsigned char r_data[2] = {0};
	unsigned char w_data[2] = {0};

	ret = max_i2c_veml7700_read(client,command,r_data);
	tmp_value = ((r_data[1] << 8) | r_data[0]);

	w_value = (tmp_value & ~mask);
    w_value |= ((value << shift) & mask);

	w_data[0] = w_value & 0xFF;
	w_data[1] = w_value  >> 8; 

	ret = max_i2c_veml7700_write(client,command,w_data);

	return ret;
}

static int max_veml7700_get_power_mode(struct i2c_client *client,unsigned short *mode)
{
	return max_veml7700_get_value(client,COMMAND_ALS_SD,ALS_SD_MASK,ALS_SD_SHIFT,mode);
}

static int max_veml7700_set_power_mode(struct i2c_client *client,int mode)
{
	return max_veml7700_set_value(client,COMMAND_ALS_SD,ALS_SD_MASK,ALS_SD_SHIFT,mode);
}

static int max_veml7700_get_interrupt_mode(struct i2c_client *client,unsigned short *mode)
{
	return max_veml7700_get_value(client,COMMAND_ALS_INT_EN,ALS_INT_EN_MASK,ALS_INT_EN_SHIFT,mode);
}

static int max_veml7700_set_interrupt_mode(struct i2c_client *client,unsigned short mode)
{
	return max_veml7700_set_value(client,COMMAND_ALS_INT_EN,ALS_INT_EN_MASK,ALS_INT_EN_SHIFT,mode);
}

static int max_veml7700_get_gain(struct i2c_client *client,unsigned short *gain_value)
{
	return max_veml7700_get_value(client,COMMAND_ALS_GAIN,ALS_GAIN_MASK,ALS_GAIN_SHIFT,gain_value);
}

static int max_veml7700_set_gain(struct i2c_client *client,unsigned short gain_value)
{
	return max_veml7700_set_value(client,COMMAND_ALS_GAIN,ALS_GAIN_MASK,ALS_GAIN_SHIFT,gain_value);
}

static int max_veml7700_get_integration_time(struct i2c_client *client,unsigned short *time)
{
	return max_veml7700_get_value(client,COMMAND_ALS_IT,ALS_IT_MASK,ALS_IT_SHIFT,time);
}

static int max_veml7700_set_integration_time(struct i2c_client *client,unsigned short time)
{
	return max_veml7700_set_value(client,COMMAND_ALS_IT,ALS_IT_MASK,ALS_IT_SHIFT,time);
}

static int max_veml7700_get_power_saving_mode(struct i2c_client *client,unsigned short *mode)
{
	return max_veml7700_get_value(client,COMMAND_PSM,PSM_MASK,PSM_SHIFT,mode);
}

static int max_veml7700_set_power_saving_mode(struct i2c_client *client,unsigned short mode)
{
	return max_veml7700_set_value(client,COMMAND_PSM,PSM_MASK,PSM_SHIFT,mode);
}

static int max_veml7700_get_power_saving_enable(struct i2c_client *client,unsigned short *enable)
{
	return max_veml7700_get_value(client,COMMAND_PSM_EN,PSM_EN_MASK,PSM_EN_SHIFT,enable);
}

static int max_veml7700_set_power_saving_enable(struct i2c_client *client,unsigned short enable)
{
	return max_veml7700_set_value(client,COMMAND_PSM_EN,PSM_EN_MASK,PSM_EN_SHIFT,enable);
}

static int max_veml7700_get_lux(struct i2c_client *client ,unsigned short *lux_value)
{
	int ret = 0;
	unsigned char r_data[2] = {0};
	ret = max_i2c_veml7700_read(client,COMMAND_ALS_DATA,r_data);
	*lux_value = ((r_data[1] << 8) | r_data[0]);
	return ret;
}

static ssize_t name_show(struct device *dev, struct device_attribute *attr,
			char *buf)
{
	return sprintf(buf, "%s\n", DRIVER_NAME);
}

static DEVICE_ATTR(name, 0444, name_show,NULL);

static ssize_t power_mode_show(struct device *dev, struct device_attribute *attr,
			char *buf)
{
	unsigned short value = 0;
	struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);

if (!veml7700_driver)
{
	printk("get max_veml7700_driver error\n");
	return -ENODEV;
}
max_veml7700_get_power_mode(veml7700_driver->client,&value);

switch (value)
{
case 0/* constant-expression */:
	/* code */
	return sprintf(buf, "%s\n", "Power On");
	break;
case 1:
	return sprintf(buf, "%s\n", "Shut Down");
	break;
default:
	break;
}		

return sprintf(buf, "%s\n", "Error");
}

static ssize_t power_mode_store(struct device *dev,
                                            struct device_attribute *attr,
                                            const char *buf, size_t count)
{
	uint8_t value;
	int ret;

struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
if (!veml7700_driver)
{
	printk("get max_veml7700_driver error\n");
	return -ENODEV;
}
ret = kstrtou8(buf, 0, &value);// auto data format
if (ret)
{
	printk("kstrtou8 error\n");
	return -ENODEV;
}

if (value == 0x00 || value == 0x01)
{
	ret = max_veml7700_set_power_mode(veml7700_driver->client,value);
}
else
{
	printk("input value error,must only one in 0x00/0x01\n");
}
return count;
}

static DEVICE_ATTR(power_mode, 0664, power_mode_show,power_mode_store);

static ssize_t veml7700_lux_show(struct device *dev, struct device_attribute *attr,
			char *buf)
{
	unsigned short value = 0;
	struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);

if (!veml7700_driver)
{
	printk("get max_veml7700_driver error\n");
	return -ENODEV;
}

if (veml7700_driver->is_support)
{
	max_veml7700_get_lux(veml7700_driver->client,&value);
	return sprintf(buf, "%d\n", value);
}
else
{
	return sprintf(buf, "%s\n", "not support light sensor");
}
}

static DEVICE_ATTR(lux, 0444, veml7700_lux_show,NULL);

static ssize_t veml7700_enable_show(struct device *dev, struct device_attribute *attr,
			char *buf)
{
	struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
	if (!veml7700_driver)
	{
		printk("get max_veml7700_driver error\n");
		return -ENODEV;
	}
	
return sprintf(buf, "%d\n", veml7700_driver->enable);
}

static ssize_t veml7700_enable_store(struct device *dev,
                                            struct device_attribute *attr,
                                            const char *buf, size_t count)
{
	uint8_t value;
	int ret;

struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
if (!veml7700_driver)
{
	printk("get max_veml7700_driver error\n");
	return -ENODEV;
}
ret = kstrtou8(buf, 0, &value);// auto data format
if (ret)
{
	printk("kstrtou8 error\n");
	return -ENODEV;
}

if (value == 0x00 || value == 0x01)
{
	if (veml7700_driver->enable == 0 && value == 1)
	{
		schedule_delayed_work(&veml7700_driver->work, msecs_to_jiffies(veml7700_driver->delay));
	}
	veml7700_driver->enable = value;
}
else
{
	printk("input value error,must only one in 0x00/0x01\n");
}
return count;
}

static DEVICE_ATTR(enable, 0664, veml7700_enable_show,veml7700_enable_store);

static ssize_t veml7700_delay_show(struct device *dev, struct device_attribute *attr,
			char *buf)
{
	struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);

if (!veml7700_driver)
{
	printk("get max_veml7700_driver error\n");
	return -ENODEV;
}

return sprintf(buf, "%d\n", veml7700_driver->delay);
}

static ssize_t veml7700_delay_store(struct device *dev,
                                            struct device_attribute *attr,
                                            const char *buf, size_t count)
{
	int value;
	int ret;

struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
if (!veml7700_driver)
{
	printk("get max_veml7700_driver error\n");
	return -ENODEV;
}
ret = kstrtou32(buf, 0, &value);// auto data format
if (ret)
{
	printk("kstrtou8 error\n");
	return -ENODEV;
}

veml7700_driver->delay = value;
return count;
}

static DEVICE_ATTR(delay, 0664, veml7700_delay_show,veml7700_delay_store);

static ssize_t veml7700_support_show(struct device *dev, struct device_attribute *attr,
			char *buf)
{
	struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
	if (!veml7700_driver)
	{
		printk("get max_veml7700_driver error\n");
		return -ENODEV;
	}
	return sprintf(buf, "%d\n", veml7700_driver->is_support);
}

static DEVICE_ATTR(support, 0444, veml7700_support_show,NULL);

static ssize_t veml7700_gain_show(struct device *dev, struct device_attribute *attr,
			char *buf)
{
	struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
	unsigned short gain = 0;

if (!veml7700_driver)
{
	printk("get max_veml7700_driver error\n");
	return -ENODEV;
}
max_veml7700_get_gain(veml7700_driver->client,&gain);

return sprintf(buf, "%d\n", gain);
}

static ssize_t veml7700_gain_store(struct device *dev,
                                            struct device_attribute *attr,
                                            const char *buf, size_t count)
{
	int value;
	int ret;

struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
if (!veml7700_driver)
{
	printk("get max_veml7700_driver error\n");
	return -ENODEV;
}
ret = kstrtou32(buf, 0, &value);// auto data format
if (ret)
{
	printk("kstrtou8 error\n");
	return -ENODEV;
}
if (value == ALS_GAIN_X1 || value == ALS_GAIN_X2 || value == ALS_GAIN_d8 || value == ALS_GAIN_d4)
{
	max_veml7700_set_gain(veml7700_driver->client,value);
}
return count;
}

static DEVICE_ATTR(gain, 0664, veml7700_gain_show,veml7700_gain_store);


static ssize_t veml7700_it_show(struct device *dev, struct device_attribute *attr,
			char *buf)
{
	struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
	unsigned short it = 0;

if (!veml7700_driver)
{
	printk("get max_veml7700_driver error\n");
	return -ENODEV;
}
max_veml7700_get_integration_time(veml7700_driver->client,&it);

return sprintf(buf, "%d\n", it);
}

static ssize_t veml7700_it_store(struct device *dev,
                                            struct device_attribute *attr,
                                            const char *buf, size_t count)
{
	int value;
	int ret;

struct max_veml7700_driver *veml7700_driver = dev_get_drvdata(dev);
if (!veml7700_driver)
{
	printk("get max_veml7700_driver error\n");
	return -ENODEV;
}
ret = kstrtou32(buf, 0, &value);// auto data format
if (ret)
{
	printk("kstrtou8 error\n");
	return -ENODEV;
}
if (value == ALS_INTEGRATION_25ms  || value == ALS_INTEGRATION_50ms || value == ALS_INTEGRATION_100ms ||
		value == ALS_INTEGRATION_200ms || value == ALS_INTEGRATION_400ms|| value == ALS_INTEGRATION_800ms){
	max_veml7700_set_integration_time(veml7700_driver->client,value);
}
return count;
}
static DEVICE_ATTR(it, 0664, veml7700_it_show,veml7700_it_store);

static struct attribute *attrs[] = {
	&dev_attr_name.attr,
	&dev_attr_power_mode.attr,
	&dev_attr_lux.attr,
	&dev_attr_enable.attr,
	&dev_attr_delay.attr,
	&dev_attr_support.attr,
	&dev_attr_gain.attr,
	&dev_attr_it.attr,

NULL,	/* need to NULL terminate the list of attributes */
};

static struct attribute_group attr_group = {
	.attrs = attrs,
};

/**
 * @brief 获取dts注册的信息
 * 
 * @param client 
 * @return int 
 */
static int dts_parse(struct i2c_client *client)
{	
	//int ret = 0;
    struct device_node *node;
	//const char *str;
	//struct max_veml7700_driver *veml7700_driver = i2c_get_clientdata(client);

	node = client->dev.of_node;
    if (!node) 
    {
		printk("no node for %s\n",DEVICE_NAME);
        goto error;
    }

	if (!of_device_is_available(node))
    {
		printk("dts status is not okay \n");
		goto error;
	}
	return 0;
error:
	return -EINVAL;
}


static int veml7700_init(struct i2c_client *client)
{
	int ret = -1;
	unsigned short mode = -1;

	ret = max_veml7700_set_power_mode(client,ALS_POWER_SHUTDOWN);
	//printk("max_veml7700_set_power_mode ret == %d\n",ret);

	ret |= max_veml7700_set_interrupt_mode(client,ALS_INTERRUPT_DISABLE);
	//printk("max_veml7700_set_interrupt_mode ret == %d\n",ret);
	max_veml7700_get_interrupt_mode(client,&mode);
	printk("get interrupt mode == %s \n", mode == 0 ? "disable" : "enable");


	ret |= max_veml7700_set_gain(client,ALS_GAIN_X1);
	//printk("max_veml7700_set_gain ret == %d\n",ret);
	max_veml7700_get_gain(client,&mode);
	printk("get gain == %s \n", mode == 0x2 ? "ALS_GAIN_X1" : "other");

	ret |= max_veml7700_set_integration_time(client,ALS_INTEGRATION_100ms);
	//printk("max_veml7700_set_integration_time ret == %d\n",ret);
	max_veml7700_get_integration_time(client,&mode);
	printk("get integration time == %s \n", mode == ALS_INTEGRATION_100ms ? "100ms" : "other");

	ret |= max_veml7700_set_power_saving_mode(client,ALS_POWER_MODE_3);
	//printk("max_veml7700_set_power_saving_mode ret == %d\n",ret);
	max_veml7700_get_power_saving_mode(client,&mode);
	printk("get power save mode == %s \n", mode == ALS_POWER_MODE_3 ? "ALS_POWER_MODE_3" : "other");

	ret |= max_veml7700_set_power_saving_enable(client,ALS_POWER_MODE_DISABLE);
	//printk("max_veml7700_set_power_saving_enable ret == %d\n",ret);
	max_veml7700_get_power_saving_enable(client,&mode);
	printk("max_veml7700_get_power_saving_enable == %s \n", mode == ALS_POWER_MODE_DISABLE ? "ALS_POWER_MODE_DISABLE" : "other");

	ret |= max_veml7700_set_power_mode(client,ALS_POWER_ON);
	//printk("max_veml7700_set_power_mode ret == %d\n",ret);
	max_veml7700_get_power_mode(client,&mode);
	printk("max_veml7700_get_power_mode == %s \n", mode == ALS_POWER_ON ? "ALS_POWER_ON" : "other");

	return ret;
}

static void veml7700_schedele_work(struct work_struct *work)
{
	unsigned short lux_value = 0;
	struct max_veml7700_driver *veml7700_driver = container_of((struct delayed_work *)work,
							struct max_veml7700_driver, work);
	max_veml7700_get_lux(veml7700_driver->client,&lux_value);
	//printk("get current lux value == %d \n",lux_value);
	input_event(veml7700_driver->input_dev,EV_MSC,MSC_RAW,lux_value);
	input_sync(veml7700_driver->input_dev);

if (veml7700_driver->enable)
	schedule_delayed_work(&veml7700_driver->work, msecs_to_jiffies(veml7700_driver->delay));
}

static int max_veml7700_probe(struct i2c_client *client,
		     	 const struct i2c_device_id *id)
{
	int ret = 0;
	struct max_veml7700_driver *veml7700_driver = NULL;
	static struct class *veml7700_class;


printk("get client addr == 0x%2x\n",client->addr);

veml7700_driver = kzalloc(sizeof(struct max_veml7700_driver), GFP_KERNEL);
if (veml7700_driver == NULL) {
	printk("failed to create our veml7700_driver\n");
	return -ENOMEM;
}

veml7700_driver->client = client;
i2c_set_clientdata(client,veml7700_driver);

ret = dts_parse(client);
if (ret){
	printk("dts parse error\n");
	goto dts_error;
}

veml7700_class = class_create(THIS_MODULE, DRIVER_NAME);
if (IS_ERR(veml7700_class)) {
	ret= PTR_ERR(veml7700_class);
	printk("veml7700_class: class create failed\n");
	goto dts_error;
}

veml7700_driver->dev = device_create(veml7700_class,
		 &client->dev, 0, NULL, DEVICE_NAME);
if (unlikely(IS_ERR(veml7700_driver->dev))) {
	ret = PTR_ERR(veml7700_driver->dev);
	veml7700_driver->dev = NULL;
	goto destory_class;
}

ret = sysfs_create_group(&veml7700_driver->dev->kobj, &attr_group);
if(ret){
	printk("sysfs_create_group in msa311 driver\n");
	goto destory_device;
}

veml7700_driver->delay = 3000;
veml7700_driver->enable  = 0;

//申请注册input系统
veml7700_driver->input_dev = input_allocate_device();
if (!veml7700_driver->input_dev)
{
	printk("input_allocate_device error\n");
}
veml7700_driver->input_dev->name = DEVICE_NAME;
veml7700_driver->input_dev->id.bustype = BUS_I2C;
veml7700_driver->input_dev->dev.parent = veml7700_driver->dev;

// 设置所支持的事件类型
__set_bit(EV_MSC,veml7700_driver->input_dev->evbit);
__set_bit(MSC_RAW,veml7700_driver->input_dev->mscbit);

ret = input_register_device(veml7700_driver->input_dev);
if (ret < 0) {
	input_free_device(veml7700_driver->input_dev);
	goto destory_device;
}

ret = veml7700_init(veml7700_driver->client);
if (ret != 0)
{
	printk("veml7700_init error and maybe don't support light sensor\n");
	veml7700_driver->enable = 0;
	veml7700_driver->is_support = 0;
}
else
{
	printk("veml7700_init Success !\n");
	veml7700_driver->is_support = 1;
	veml7700_driver->enable  = 1;
}

INIT_DELAYED_WORK(&veml7700_driver->work, veml7700_schedele_work);
if (veml7700_driver->enable == 1 && veml7700_driver->is_support == 1)
	schedule_delayed_work(&veml7700_driver->work, msecs_to_jiffies(veml7700_driver->delay));

input_set_drvdata(veml7700_driver->input_dev,veml7700_driver);
dev_set_drvdata(veml7700_driver->dev, veml7700_driver);

printk("max_veml7700_probe Ok !\n ");
return 0;

destory_device:
	device_destroy(veml7700_class,0);
destory_class:
	class_destroy(veml7700_class);
dts_error:
	kfree(veml7700_driver);
	return -ENODEV;
}

/**
 * @brief 
 * 
 * @param client 
 * @return int 
 */
static int max_veml7700_remove(struct i2c_client *client)
{
	return 0;
}

static const struct of_device_id i2c_veml7700_of_match[] = {
	{ .compatible = "max,veml7700" },
	{ }
};

static const struct i2c_device_id veml_device_id[] = {
	{DEVICE_NAME, 0 },
	{ }
};

MODULE_DEVICE_TABLE(i2c, veml_device_id);

static struct i2c_driver max_veml7700_driver = {
	.driver = {
		.name	= DRIVER_NAME,
		.owner  = THIS_MODULE,
		.of_match_table = of_match_ptr(i2c_veml7700_of_match),
	},
	.probe = max_veml7700_probe,
	.remove = max_veml7700_remove,
	.id_table	= veml_device_id,
};

static int __init max_veml7700_init(void)
{
	printk("max_veml7700_init \n");
	i2c_add_driver(&max_veml7700_driver);
	return 0;
}

static void __exit max_veml7700_exit(void)
{
	i2c_del_driver(&max_veml7700_driver);
}

module_init(max_veml7700_init);
module_exit(max_veml7700_exit);

MODULE_DESCRIPTION("max Veml7700 sensor Driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("738270732@qq.com");

veml7700.h

#ifndef __VEML7700_H__
#define __VEML7700_H__

#define DRIVER_NAME     "max_veml7700"
#define DEVICE_NAME     "veml7700"

#define COMMAND_ALS_DEFAULT_VALUE        0x01
// Gain Register
#define COMMAND_ALS_GAIN                 0x00
#define ALS_GAIN_MASK                    0x1800
#define ALS_GAIN_SHIFT                   11

// ALS IT Register
#define COMMAND_ALS_IT                  0x00
#define ALS_IT_MASK                     0x03C0
#define ALS_IT_SHIFT                    6
// ALS Persistence Register
#define COMMAND_ALS_PER                 0x00
#define ALS_PER_MASK                    0x0030
#define ALS_PER_SHIFT                   4
// ALS INT EN Register
#define COMMAND_ALS_INT_EN              0x00
#define ALS_INT_EN_MASK                 0x0002
#define ALS_INT_EN_SHIFT                1
// ALS SD Register
#define COMMAND_ALS_SD                  0x00
#define ALS_SD_MASK                     0x0001
#define ALS_SD_SHIFT                    0
// ALS Window High
#define COMMAND_ALS_WH                  0x01
// ALS Window Low
#define COMMAND_ALS_WL                  0x02
// ALS Power Save Mode
#define COMMAND_PSM                     0x03
#define PSM_MASK                        0x0006
#define PSM_SHIFT                       1
// ALS Power Save Mode Enable
#define COMMAND_PSM_EN                  0x03
#define PSM_EN_MASK                     0x0001
#define PSM_EN_SHIFT                    0
// ALS High Resolution Output Data
#define COMMAND_ALS_DATA                0x04
//White Channel Output Data
#define COMMAND_WHITE_DATA              0x05
// Interrupt Status
#define COMMAND_ALS_IF_L                0x06
#define ALS_IF_L_MASK                   0x8000
#define ALS_IF_L_SHIFT                  15
#define COMMAND_ALS_IF_H                0x06
#define ALS_IF_H_MASK                   0x4000
#define ALS_IF_H_SHIFT                  14

#define ALS_GAIN_X1                      0x0
#define ALS_GAIN_X2                      0x1
#define ALS_GAIN_d8                      0x2
#define ALS_GAIN_d4                      0x3

#define ALS_INTEGRATION_25ms             0xC
#define ALS_INTEGRATION_50ms             0x8
#define ALS_INTEGRATION_100ms            0x0
#define ALS_INTEGRATION_200ms            0x1
#define ALS_INTEGRATION_400ms            0x2
#define ALS_INTEGRATION_800ms            0x3

#define ALS_PERSISTENCE_1                0x0
#define ALS_PERSISTENCE_2                0x1
#define ALS_PERSISTENCE_4                0x2
#define ALS_PERSISTENCE_8                0x3

#define ALS_POWER_MODE_1                 0x0
#define ALS_POWER_MODE_2                 0x1
#define ALS_POWER_MODE_3                 0x2
#define ALS_POWER_MODE_4                 0x3

#define ALS_POWER_MODE_ENABLE            0x1
#define ALS_POWER_MODE_DISABLE           0x0

#define ALS_INTERRUPT_ENABLE             0x1
#define ALS_INTERRUPT_DISABLE            0x0

//#define ALS_POWER_ON                     0x0
//#define ALS_POWER_SHUTDOWN               0x1

#define STATUS_OK                       0x0
#define STATUS_FAIL                     -1

#define TV_LIGHT_SENSOR_GAIN_LOW         0
#define TV_LIGHT_SENSOR_GAIN_MIDDLE      1
#define TV_LIGHT_SENSOR_GAIN_HIGH        2


typedef enum ALS_SD
{
    ALS_POWER_ON,
    ALS_POWER_SHUTDOWN
} Veml7700_Als_Sd_Mode;


struct max_veml7700_driver {

    struct i2c_client 	*client;
    struct device     	*dev;
    struct timer_list   timer;
    struct delayed_work work;
    unsigned int        delay;
    unsigned int        enable;
    unsigned int        is_support;
    struct input_dev    *input_dev;
};
#endif
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值