mtk平台sensor分析一:alsps框架下的光距感驱动流程

一、前言

mtk平台为了方便光距感驱动的兼容和统一管理,将所有的光距感驱动程序都放置在alsps框架中;
本文以MT8183平台alsps框架下的光距感ltr559为例进行分析;

 涉及文件及目录:
 设备树:   kernel-4.4/arch/arm64/boot/dts/mediatek/mt6771.dts   
           kernel-4.4/arch/arm64/boot/dts/mediatek/k71v1_64_bsp.dts
 alsps架构:kernel-4.4/drivers/misc/mediatek/sensors-1.0/alsps/alsps.c
           kernel-4.4/drivers/misc/mediatek/sensors-1.0/hwmon/sensor_attributes/sensor_attr.c
 光距感驱动:kernel-4.4/drivers/misc/mediatek/sensors-1.0/alsps/LTR559/ltr559.c

二、alsps框架分析

1、驱动加载顺序

ltr599.c和alsps.c驱动程序在内核初始化过程中的调用顺序跟两者选择加载入口函数的方式有关;
ltr599.c:module_init(ltr559_init);
alsps.c:late_initcall(alsps_init);
从kernel-4.4/include/linux/init.h文件中可以获取启动顺序的宏列表和排序;

#define early_initcall(fn)		__define_initcall(fn, early)
#define pure_initcall(fn)		__define_initcall(fn, 0)
#define core_initcall(fn)		__define_initcall(fn, 1)
#define core_initcall_sync(fn)		__define_initcall(fn, 1s)
#define postcore_initcall(fn)		__define_initcall(fn, 2)
#define postcore_initcall_sync(fn)	__define_initcall(fn, 2s)
#define arch_initcall(fn)		__define_initcall(fn, 3)
#define arch_initcall_sync(fn)		__define_initcall(fn, 3s)
#define subsys_initcall(fn)		__define_initcall(fn, 4)
#define subsys_initcall_sync(fn)	__define_initcall(fn, 4s)
#define fs_initcall(fn)			__define_initcall(fn, 5)
#define fs_initcall_sync(fn)		__define_initcall(fn, 5s)
#define rootfs_initcall(fn)		__define_initcall(fn, rootfs)
#define device_initcall(fn)		__define_initcall(fn, 6)
#define device_initcall_sync(fn)	__define_initcall(fn, 6s)
#define late_initcall(fn)		__define_initcall(fn, 7)
#define late_initcall_sync(fn)		__define_initcall(fn, 7s

module_init对应默认的device_initcall,比late_initcall数字小,数字越小的优先级越高;所以内核初始化调用顺序是先调用ltr559.c入口函数后调用alsps.c的入口函数

2、sensor内核初始化驱动流程

机器刚开始启动进入kernel初始化阶段时,光距感sensor驱动流程:
在这里插入图片描述

先调用ltr559.c文件中的ltr559_init,在alsps_driver_add函数中先向内核平台总线注册一个als_ps_driver结构体的设备驱动:platform_driver_register(&als_ps_driver)),之后将所有加载过的光距感驱动程序通过调用alsps_driver_add(obj);函数,将alsps_init_list[MAX_CHOOSE_ALSPS_NUM]数组中的成员都指向对应的obj

//ltr599.c
static struct alsps_init_info ltr559_init_info = {
   
		.name = LTR559_DEV_NAME,
		.init = alsps_local_init,
		.uninit = alsps_remove,
	
};
static int __init ltr559_init(void)
{
   
  alsps_driver_add(&ltr559_init_info);
  return 0}
//mt6771.dts 
//配置alsps架构下的device信息
alsps:als_ps@0 {
   
    compatible = "mediatek,als_ps";
};
//alsps.c
static const struct of_device_id als_ps_of_match[] = {
   
  {
   .compatible = "mediatek,als_ps",},
};
static struct platform_driver als_ps_driver = {
   
	.probe = als_ps_probe,
	.remove = als_ps_remove,
	.driver = {
   
		.name = "als_ps",
		.of_match_table = als_ps_of_match,
	}
};
int alsps_driver_add(struct alsps_init_info *obj)
{
   
    int err = 0;
	int i = 0;
	
	for (i = 0; i < MAX_CHOOSE_ALSPS_NUM; i++) {
     //MAX_CHOOSE_ALSPS_NUM = 5
		if ((i == 0) && (alsps_init_list[0] == NULL))	
			if (platform_driver_register(&als_ps_driver))
		if (alsps_init_list[i] == NULL) {
   
			obj->platform_diver_addr = &als_ps_driver;
			alsps_init_list[i] = obj; 
			break;
		}
	}
	//光距感驱动遍历数量超过5(MAX_CHOOSE_ALSPS_NUM)个时会报错
	if (i >= MAX_CHOOSE_ALSPS_NUM) {
   
		pr_err("ALSPS driver add err\n");
		err = -1;
	}
	return err;
}

当alsps_init_list数组成员与所有的光距感obj绑定后,开始运行alsps.c中alsps_init->alsps_probe->alsps_real_driver_init->alsps_init_list[i]->init();, 通过操作alsps_init_list数组成员的init函数指针来运行对应光距感驱动程序中的obj结构体init指针函数,如ltr559.c中的alsps_local_init函数;

之后的流程就很熟悉了,向i2c平台注册了ltr559_i2c_driver,当alsps_of_match中的compatible与dts中compatible的属性保持一致就会调用ltr559_i2c_probe;

//k71v1_64_bsp.dts
&i2c1 {
   
	alsps1@3b{
   
	  compatible = "mediatek,alsps559";
		reg = <0x3b>;
	};
}
//ltr559.c
static const struct of_device_id alsps_of_match[] = {
   
	{
   .compatible = "mediatek,alsps559"},
	{
   },
};
static struct i2c_driver ltr559_i2c_driver = {
   	
	.probe      = ltr559_i2c_probe
  • 8
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值