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.
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";
};
- 设置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;
};
};
- 设置中断
interrupt-parent = <&msm_gpio>;
interrupts = <96 0x1>;
- 电相关
vdd-supply = <&pm8909_l17>;
vlogic-supply = <&pm8909_l6>;
- gpio 信息
invn,gpio-int = <&msm_gpio 96 0x1>;
invn,place = "Portrait Down Back Side";
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;
}
高通 I2c框架解析 ↩︎