高通平台 input类 sensor驱动分析 :陀螺仪/加速度计 mpu6050 driver分析

mpu6050driver分析

1: 驱动中入口


    module_i2c_driver(mpu6050_i2c_driver);  直接moudle_i2c_driver  == moudle_init + i2c_register_driver

	使用 设备树 匹配
	static struct i2c_driver mpu6050_i2c_driver = {
	.driver	= {
		.name	= "mpu6050",
		.owner	= THIS_MODULE,
		.pm	= &mpu6050_pm,
		.of_match_table = mpu6050_of_match,
	},
	.probe		= mpu6050_probe,
	.remove		= mpu6050_remove,
	.id_table	= mpu6050_ids,
};

高通 I2c 注册使用框架 待解析 1.

2: 设备树信息 分析:

在设备树中 I2c的子节点中 配置如下:
mpu6050@68 { /* Gyroscope and accelerometer sensor combo */
compatible = "invn,mpu6050";
reg = <0x68>;
pinctrl-names = "mpu_default","mpu_sleep";
pinctrl-0 = <&mpu6050_default>;
pinctrl-1 = <&mpu6050_sleep>;
interrupt-parent = <&msm_gpio>;
interrupts = <96 0x1>;
vdd-supply = <&pm8909_l17>;
vlogic-supply = <&pm8909_l6>;
invn,gpio-int = <&msm_gpio 96 0x1>;
invn,place = "Portrait Down Back Side";
};
  1. 设置gpio96
pinctrl-names = "mpu_default","mpu_sleep";
pinctrl-0 = <&mpu6050_default>;
pinctrl-1 = <&mpu6050_sleep>;
	在msm8909-mtp.dtsi 中中 补充定义了 mpu6050_ini_pin
	定义了 mpu6050_default 与 mpu6050_sleep的两种状态。
	&tlmm_pinmux {
			mpu6050_int_pin {
				qcom,pins = <&gp 96>;
				qcom,pin-func = <0>;
				qcom,num-grp-pins = <1>;
				label = "mpu6050-irq";
				mpu6050_default: mpu6050_default {
					drive-strength = <6>;
					bias-pull-down;
				};
				mpu6050_sleep: mpu6050_sleep {
					drive-strength = <2>;
					bias-pull-down;
				};
			};
  1. 设置中断
		interrupt-parent = <&msm_gpio>;
		interrupts = <96 0x1>
  1. 电相关
		vdd-supply = <&pm8909_l17>;
		vlogic-supply = <&pm8909_l6>;
  1. gpio 信息
		invn,gpio-int = <&msm_gpio 96 0x1>;
		invn,place = "Portrait Down Back Side";

3 driver probe过程 解析:

static int mpu6050_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
    i2c_check_functionality
    sensor = devm_kzalloc(&client->dev, sizeof(struct mpu6050_sensor),GFP_KERNEL);  /* 申请 设备数据 结构内存空间, 这里是用devm_kzalloc, 需要填充device 的设备结构, 当设备被卸载时, 该内存自动会被释放掉。*/
    sensor->client = client;
    sensor->dev = &client->dev;
    i2c_set_clientdata(client, sensor);  /*保存设备相关数据*/
    if (client->dev.of_node) {    /* 判断是否获取到设备树 的节点信息, 解析并存储 platform_data 设备的私有数据 */
   {
    pdata = devm_kzalloc(&client->dev,sizeof(struct mpu6050_platform_data), GFP_KERNEL); /* 申请 平台设备的 数据内容*/
    ret = mpu6050_parse_dt(&client->dev, pdata); /*	解析 设备树的 内容*/
    mpu6050_dt_get_place(dev, pdata);  /* 解析 mpu的位置设置状态*/
    pdata->gpio_int = of_get_named_gpio_flags(dev->of_node,
    "invn,gpio-int", 0, &pdata->int_flags);
    pdata->gpio_en = of_get_named_gpio_flags(dev->of_node,
    "invn,gpio-en", 0, NULL);
    pdata->use_int = of_property_read_bool(dev->of_node,
    "invn,use-interrupt");
    }
    pdata	/* Platform specific data, device core doesn't touch it */
    sensor->pdata = pdata; /* 将设备私有数据这块内存  保存到 设备数据中, 用相应的指针链接上*/
    sensor->enable_gpio = sensor->pdata->gpio_en;  /* 单独记录下 使能脚的gpio号*/
    
    if (gpio_is_valid(sensor->enable_gpio)) {   /* 申请 使能gpio */
				ret = gpio_request(sensor->enable_gpio, "MPU_EN_PM");
				gpio_direction_output(sensor->enable_gpio, 0);
     mpu6050_pinctrl_init /* 初始化设置  pinctrl的状态, 具体见上面配置(gpio96), 方便后面设置 非 default的状态*/
     mpu6050_power_init(sensor);   /* 上电初始化*/
     {
				sensor->vdd = regulator_get(&sensor->client->dev, "vdd"); /* 获取电 ,会根据设备树中“vdd-supply“  "vdd"会被加上 -supply string 解析*/
					if (regulator_count_voltages(sensor->vdd) > 0) {
					ret = regulator_set_voltage(sensor->vdd, MPU6050_VDD_MIN_UV,MPU6050_VDD_MAX_UV);
					sensor->vlogic = regulator_get(&sensor->client->dev, "vlogic");
					if (regulator_count_voltages(sensor->vlogic) > 0) {
					ret = regulator_set_voltage(sensor->vlogic,mpu6050_power_ctl(sensor, true); /* 上电操作*/
    regulator_enable(sensor->vdd);
    regulator_enable(sensor->vi2c);
    gpio_set_value(sensor->enable_gpio, 1);
    mpu6050_pinctrl_state(sensor, true);
    /*设置 mpu6050的相关信息*/mpu_check_chip_type(sensor, id);
    sensor->chip_type = INV_MPU6050;
    setup_mpu6050_reg(reg);   /* 初始化 寄存器信息, 是将 设备树中配置的 reg 获取后,转换成mpu_reg_map , 在这里传入一个默认的状态。 */
    mpu6050_set_power_mode(sensor, false);  /* turn off and turn on power to ensure gyro engine is on */
    mpu6050_set_power_mode(sensor, true);   /* 发送i2c 信息给 相关的寄存器, 来完成  power mode的 改变(唤醒与休眠状态)*/
    mpu6050_init_engine(sensor);  /* 写相关的寄存器, 先disable 相关engine*/
    mpu6050_switch_engine(sensor, false, BIT_PWR_GYRO_STBY_MASK);
    mpu6050_switch_engine(sensor, false, BIT_PWR_ACCEL_STBY_MASK);
    ret = mpu6050_set_lpa_freq(sensor, MPU6050_LPA_5HZ);	
    sensor->cfg.is_asleep = false;
    atomic_set(&sensor->accel_en, 0); /* 原子操作,设置过程不会被打断*/
    atomic_set(&sensor->gyro_en, 0);
    ret = mpu6050_init_config(sensor);
    mpu6050_reset_chip(sensor);
    ......./* 各种写寄存器 初始化 */
    sensor->accel_dev = devm_input_allocate_device(&client->dev);	/* 待分析 使用 devm_input_allocate_device 申请注册了 两个input_dev 设备*/				
	sensor->gyro_dev = devm_input_allocate_device(&client->dev);			
					
    	sensor->accel_dev->name = MPU6050_DEV_NAME_ACCEL;       /* 分别 对sensor 结构体中 属于 加速度计 陀螺仪的相关信息 填充*/
    	sensor->gyro_dev->name = MPU6050_DEV_NAME_GYRO;
    	sensor->accel_dev->id.bustype = BUS_I2C;
    	sensor->gyro_dev->id.bustype = BUS_I2C;
    	sensor->accel_poll_ms = MPU6050_ACCEL_DEFAULT_POLL_INTERVAL_MS;
    	sensor->gyro_poll_ms = MPU6050_GYRO_DEFAULT_POLL_INTERVAL_MS;
    	sensor->acc_use_cal = false;
		{	/* 对于 sensor 信息是注册 输入子系统 
		以下是  输入子系统相关信息的 初始化 */
		input_set_capability(sensor->accel_dev, EV_ABS, ABS_MISC);
		input_set_capability(sensor->gyro_dev, EV_ABS, ABS_MISC);
		input_set_abs_params(sensor->accel_dev, ABS_X,
				MPU6050_ACCEL_MIN_VALUE, MPU6050_ACCEL_MAX_VALUE,
				0, 0);
		input_set_abs_params(sensor->accel_dev, ABS_Y,
				MPU6050_ACCEL_MIN_VALUE, MPU6050_ACCEL_MAX_VALUE,
				0, 0);
		input_set_abs_params(sensor->accel_dev, ABS_Z,
				MPU6050_ACCEL_MIN_VALUE, MPU6050_ACCEL_MAX_VALUE,
				0, 0);
		input_set_abs_params(sensor->gyro_dev, ABS_RX,
					 MPU6050_GYRO_MIN_VALUE, MPU6050_GYRO_MAX_VALUE,
					 0, 0);
		input_set_abs_params(sensor->gyro_dev, ABS_RY,
					 MPU6050_GYRO_MIN_VALUE, MPU6050_GYRO_MAX_VALUE,
					 0, 0);
		input_set_abs_params(sensor->gyro_dev, ABS_RZ,
					 MPU6050_GYRO_MIN_VALUE, MPU6050_GYRO_MAX_VALUE,
					 0, 0);
		sensor->accel_dev->dev.parent = &client->dev;
		sensor->gyro_dev->dev.parent = &client->dev;
		input_set_drvdata(sensor->accel_dev, sensor);
		input_set_drvdata(sensor->gyro_dev, sensor);
		}
		gpio_request(sensor->pdata->gpio_int,"mpu_gpio_int"); 
		gpio_direction_input(sensor->pdata->gpio_int);   
		/*申请  中断 gpio, 设置gpio为 输入状态   待分析 为什么前面设置中断gpio pinctrl */
		request_threaded_irq(client->irq,NULL, mpu6050_interrupt_thread,sensor->pdata->int_flags | IRQF_ONESHOT,"mpu6050", sensor); 
		/* 申请一个 gpio 中断 , 中断触发方式 在上面的 config函数中已经有设置过*/
		disable_irq(client->irq); 	/* Disable interrupt until event is enabled */
		--->
    		static irqreturn_t mpu6050_interrupt_thread(int irq, void *data)    /* 待分析  sensor中注册的 中断处理 函数 func*/
    			{
    				struct mpu6050_sensor *sensor = data;
    				ret = i2c_smbus_read_byte_data(sensor->client,sensor->reg.int_status);
    				if (ret & BIT_FIFO_OVERFLOW)
    					mpu6050_flush_fifo(sensor);
    				else if (ret & (BIT_MOT_EN | BIT_ZMOT_EN))
    					mpu6050_read_single_event(sensor);
    				else if (ret & BIT_DATA_RDY_INT)
    					mpu6050_read_single_event(sensor);
    				else
    					dev_info(&sensor->client->dev, "Unknown interrupt 0x%x", ret);
    			}
        --->
    sensor->data_wq = create_freezable_workqueue("mpu6050_data_work");		 /* 创建 一个工作队列 */	
    			
    INIT_DELAYED_WORK(&sensor->fifo_flush_work, mpu6050_fifo_flush_fn);   /* 待分析  INIT_DELAYED_WORK 创建了 延时执行的 工作*/
    INIT_WORK(&sensor->resume_work, mpu6050_resume_work_fn);			  /* 绑定处理函数 static void mpu6050_resume_work_fn(struct work_struct *work) */
    			 -> static void mpu6050_resume_work_fn(struct work_struct *work) /* 待分析  func  */  

    hrtimer_init(&sensor->gyro_timer, CLOCK_BOOTTIME, HRTIMER_MODE_REL);   /* 初始化 一个 高精度 延时定时器*/
    sensor->gyro_timer.function = gyro_timer_handle;					   /* 绑定 陀螺仪 的定时器处理函数 */
    --->
        static enum hrtimer_restart gyro_timer_handle(struct hrtimer *hrtimer)   /*待分析 陀螺仪的 定时器中断处理函数 func */
    			{
    				struct mpu6050_sensor *sensor;
    				sensor = container_of(hrtimer, struct mpu6050_sensor, gyro_timer);
    				sensor->gyro_wkp_flag = 1;
    				wake_up_interruptible(&sensor->gyro_wq);
    				if (mpu6050_manage_polling(SNS_TYPE_GYRO, sensor) < 0)
    					dev_err(&sensor->client->dev,
    							"gyr: failed to start/cancel timer\n");
    				return HRTIMER_NORESTART;
    			}
    --->
    hrtimer_init(&sensor->accel_timer, CLOCK_BOOTTIME, HRTIMER_MODE_REL); /* 初始化 一个 高精度 延时定时器*/
		sensor->accel_timer.function = accel_timer_handle;					  /* 绑定 加速度计 的定时器处理函数 */
        static enum hrtimer_restart accel_timer_handle(struct hrtimer *hrtimer)		/*待分析  加速度计 的 定时器中断处理函数 func */
				{
					struct mpu6050_sensor *sensor;
					sensor = container_of(hrtimer, struct mpu6050_sensor, accel_timer);
					sensor->accel_wkp_flag = 1;
					wake_up_interruptible(&sensor->accel_wq);
					if (mpu6050_manage_polling(SNS_TYPE_ACCEL, sensor) < 0)
						dev_err(&sensor->client->dev,
								"acc: failed to start/cancel timer\n");
					return HRTIMER_NORESTART;
				}
				init_waitqueue_head(&sensor->gyro_wq);   /* 初始化一个 等待队列*/
		init_waitqueue_head(&sensor->accel_wq);  /* 初始化一个 等待队列*/
		sensor->gyro_wkp_flag = 0;
		sensor->accel_wkp_flag = 0;	
		sensor->gyr_task   = kthread_run(gyro_poll_thread, sensor, "sns_gyro");   /* 待分析 内核线程的创建,  创建并启动 一个内核线程 */
					->gyro_poll_thread(void *data)  /* 待分析  陀螺仪 线程处理函数 func */
		sensor->accel_task = kthread_run(accel_poll_thread, sensor,"sns_accel");  
					->accel_poll_thread(void *data)  /*待分析  加速度计 线程处理函数 func*/	
		input_register_device(sensor->accel_dev);  /* 输入子系统 注册  待分析 与前面的 devm_input_allocate_device 的区别 */
		input_register_device(sensor->gyro_dev);
		create_accel_sysfs_interfaces(&sensor->accel_dev->dev); /* 待分析 创建文件访问*/
		create_gyro_sysfs_interfaces(&sensor->gyro_dev->dev);
		device_create_file(dev, gyro_attr + i);   /* 待分析 device_create_file */

        sensor->accel_cdev = mpu6050_acc_cdev;
		/*  加速度计 sensor 的功能性 函数指针的 传参   待分析 这些函数的 具体实现*/
		
		sensor->accel_cdev.delay_msec = sensor->accel_poll_ms;
		sensor->accel_cdev.sensors_enable = mpu6050_accel_cdev_enable;
		sensor->accel_cdev.sensors_poll_delay = mpu6050_accel_cdev_poll_delay;
		sensor->accel_cdev.sensors_enable_wakeup =mpu6050_accel_cdev_enable_wakeup;
		sensor->accel_cdev.fifo_reserved_event_count = 0;
		sensor->accel_cdev.sensors_set_latency = mpu6050_accel_cdev_set_latency;
		sensor->accel_cdev.sensors_flush = mpu6050_accel_cdev_flush;
		sensor->accel_cdev.sensors_calibrate = mpu6050_accel_calibration;
		sensor->accel_cdev.sensors_write_cal_params =mpu6050_write_accel_cal_params;
		
		sensors_classdev_register(&sensor->accel_dev->dev,&sensor->accel_cdev); /* 待分析  注册一个 sensor 设备的过程 */
		
		sensor->gyro_cdev = mpu6050_gyro_cdev;
		/*  陀螺仪 sensor 的功能性 函数指针的 传参   待分析 这些函数的 具体实现*/
		sensor->gyro_cdev.delay_msec = sensor->gyro_poll_ms;
		sensor->gyro_cdev.sensors_enable = mpu6050_gyro_cdev_enable;
		sensor->gyro_cdev.sensors_poll_delay = mpu6050_gyro_cdev_poll_delay;
		sensor->gyro_cdev.fifo_reserved_event_count = 0;
		sensor->gyro_cdev.sensors_set_latency = mpu6050_gyro_cdev_set_latency;
		sensor->gyro_cdev.sensors_flush = mpu6050_gyro_cdev_flush;
		
		sensors_classdev_register(&sensor->gyro_dev->dev, &sensor->gyro_cdev); /* 待分析  注册一个 sensor 设备的过程 */
		
		mpu6050_power_ctl(sensor, false); /*先 下电*/
				/*完成probe 工作*/ 
		
		/* 若有 异常 进行 如下的异常处理 */
		err_remove_gyro_cdev:
			sensors_classdev_unregister(&sensor->gyro_cdev);
		err_remove_accel_cdev:
			 sensors_classdev_unregister(&sensor->accel_cdev);
		err_remove_gyro_sysfs:
			remove_accel_sysfs_interfaces(&sensor->gyro_dev->dev);
		err_remove_accel_sysfs:
			remove_accel_sysfs_interfaces(&sensor->accel_dev->dev);
		err_destroy_workqueue:
			destroy_workqueue(sensor->data_wq);
			if (client->irq > 0)
				free_irq(client->irq, sensor);
			hrtimer_try_to_cancel(&sensor->gyro_timer);
			hrtimer_try_to_cancel(&sensor->accel_timer);
			kthread_stop(sensor->gyr_task);
			kthread_stop(sensor->accel_task);
		err_free_gpio:
			if ((sensor->pdata->use_int) &&
				(gpio_is_valid(sensor->pdata->gpio_int)))
				gpio_free(sensor->pdata->gpio_int);
		err_power_off_device:
			mpu6050_power_ctl(sensor, false);
		err_deinit_regulator:
			mpu6050_power_deinit(sensor);
		err_free_enable_gpio:
			if (gpio_is_valid(sensor->enable_gpio))
				gpio_free(sensor->enable_gpio);
		err_free_devmem:
			devm_kfree(&client->dev, sensor);
			dev_err(&client->dev, "Probe device return error%d\n", ret);
			return ret;
}

  1. 高通 I2c框架解析 ↩︎

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值