内核通知链的使用说明:

注册:

int srcu_notifier_chain_register(struct srcu_notifier_head *nh, struct notifier_block *n);

void srcu_init_notifier_head(struct srcu_notifier_head *nh);

通知:

int srcu_notifier_call_chain(struct srcu_notifier_head *nh, unsigned long val, void *v)

示例:

int charger_dev_event(struct notifier_block *nb, unsigned long event, void *v){... ...}

struct srcu_notifier_head evt_nh;

struct notifier_block chg1_nb;

chg1_nb.notifier_call = charger_psy_event;

srcu_init_notifier_head(&evt_nh);

srcu_notifier_chain_register(&evt_nh, &chg1_nb);

---------------------------------------------------------------------------------------------------------------------

线程定时器:

C Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

static enum alarmtimer_restart mtk_charger_alarm_timer_func(struct alarm *alarm, ktime_t now)
{
    struct charger_manager *info =
    container_of(alarm, struct charger_manager, charger_timer);
    unsigned long flags;

if (info->is_suspend == false) {
        chr_err("%s: not suspend, wake up charger\n", __func__);
        _wake_up_charger(info);
    } else {
        chr_err("%s: alarm timer timeout\n", __func__);
        spin_lock_irqsave(&info->slock, flags);
        if (!info->charger_wakelock.active)
            __pm_stay_awake(&info->charger_wakelock);
        spin_unlock_irqrestore(&info->slock, flags);
    }

return ALARMTIMER_NORESTART;
}
static void mtk_charger_start_timer(struct charger_manager *info)
{
    struct timespec time, time_now;
    ktime_t ktime;
    int ret = 0;

/* If the timer was already set, cancel it */
    ret = alarm_try_to_cancel(&pinfo->charger_timer);
    if (ret < 0) {
        chr_err("%s: callback was running, skip timer\n", __func__);
        return;
    }

get_monotonic_boottime(&time_now);
    time.tv_sec = info->polling_interval;
    time.tv_nsec = 0;
    info->endtime = timespec_add(time_now, time);

ktime = ktime_set(info->endtime.tv_sec, info->endtime.tv_nsec);

chr_err("%s: alarm timer start:%d, %ld %ld\n", __func__, ret,
        info->endtime.tv_sec, info->endtime.tv_nsec);
    alarm_start(&pinfo->charger_timer, ktime);
}
static void mtk_charger_init_timer(struct charger_manager *info)
{
    alarm_init(&info->charger_timer, ALARM_BOOTTIME,
            mtk_charger_alarm_timer_func);
    mtk_charger_start_timer(info);

#ifdef CONFIG_PM
    if (register_pm_notifier(&charger_pm_notifier_func))
        chr_err("%s: register pm failed\n", __func__);
#endif /* CONFIG_PM */
}

充电中断流程:

C Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

/kernel-4.14/drivers/misc/mediatek/pmic/mt6390/v1/pmic_chr_type_det_v2.c

/kernel-4.19/drivers/power/supply/mt6357-charger-type.c
pmic_chrdet_init //pmic_register_interrupt_callback(INT_CHRDET_EDGE, chrdet_int_handler); pmic_enable_interrupt(INT_CHRDET_EDGE, 1, "PMIC");
    ->chrdet_int_handler
        ->pmic_set_register_value(PMIC_RG_USBDL_RST, 1);
        ->do_charger_detect()
            ->mtk_pmic_enable_chr_type_det(pmic_get_register_value(PMIC_RGS_CHRDET))
                ->if (!mt_usb_is_device()) { return;}
                ->g_chr_type = hw_charging_get_charger_type();  //获取硬件充电类型
                ->chrdet_inform_psy_changed(g_chr_type, 1);
power_supply_core.c ->static struct power_supply *chrdet_psy = power_supply_get_by_name("charger"); //pmic_chrdet_init(void)

->propval.intval = chg_type;
                    ->power_supply_set_property(chrdet_psy, POWER_SUPPLY_PROP_ONLINE, &propval)
                    ->power_supply_set_property(chrdet_psy, POWER_SUPPLY_PROP_CHARGE_TYPE, &propval)
                        ->psy->desc->set_property   //psy->desc = &mt_chg->chg_desc in power_supply_register()
mtk_chg_type_det.c          ->mt_charger_set_property   //mt_chg->chg_desc.set_property = mt_charger_set_property
                                ->switch (psp) {
                                ->case POWER_SUPPLY_PROP_ONLINE:
                                    ->mtk_chg->chg_online = val->intval;
                                    ->mt_charger_online(mtk_chg);
                                        ->if (!mtk_chg->chg_online) {   //如果充电器不存在
                                            ->boot_mode = get_boot_mode();
                                            ->if (boot_mode == KERNEL_POWER_OFF_CHARGING_BOOT || boot_mode == LOW_POWER_OFF_CHARGING_BOOT) {
                                                ->kernel_power_off()    //如果是关机充电模式,则关机
                                                ->orderly_poweroff(true)    //使用这个,上面的没作用
                                ->case POWER_SUPPLY_PROP_CHARGE_TYPE:
                                    ->mtk_chg->chg_type = val->intval;//将g_chr_type保存在struct mt_charger *mtk_chg,以供mt_get_charger_type()使用
                                ->if (mtk_chg->chg_type == STANDARD_HOST/CHARGING_HOST/NONSTANDARD_CHARGER)
                                    ->mt_usb_connect();  //连接PC
                                    ->info->vbus_state = 1;
                                ->else
                                    ->mt_usb_disconnect();
                                    ->info->vbus_state = 0;
                                ->queue_work(cti->chg_in_wq, &cti->chg_in_work);    //INIT_WORK(&cti->chg_in_work, charger_in_work_handler);
                                    ->charger_in_work_handler
mtk_charger.c                           ->mtk_charger_int_handler
                                            ->charger_manager_notifier(pinfo, CHARGER_NOTIFY_STOP_CHARGING);    //if (mt_get_charger_type() == CHARGER_UNKNOWN) {
                                            ->charger_manager_notifier(pinfo, CHARGER_NOTIFY_START_CHARGING);   //else
notifier.c                                      ->srcu_notifier_call_chain(&info->evt_nh, event, NULL); //int srcu_notifier_call_chain(struct srcu_notifier_head *nh, unsigned long val, void *v)
                                                    ->battery_callback
                                            ->_wake_up_charger(pinfo)
                                                ->wake_up(&info->wait_que)
                                                    ->charger_routine_thread
mtk_battery_core.c                      ->fg_charger_in_handler
mtk_chg_type_det.c                          ->mt_get_charger_type  //去拿充电类型
mtk_battery.c                               ->wakeup_fg_algo_atomic(FG_INTR_CHARGER_IN)  //唤醒gm3.0算法
                                                ->nl_send_to_user(gm.g_fgd_pid, 0, fgd_msg);
                                ->queue_delayed_work(system_power_efficient_wq, &info->wq_detcable, info->debounce_jiffies); //INIT_DELAYED_WORK(&info->wq_detcable, usb_extcon_detect_cable);
                                   ->usb_extcon_detect_cable 
                                        ->if (info->vbus_state)
                                            ->extcon_set_state_sync(info->edev, EXTCON_USB, true);
                                        ->else
                                            ->extcon_set_state_sync(info->edev, EXTCON_USB, false);
                                                ->ssusb_vbus_notifier(struct notifier_block *nb, unsigned long event, void *ptr)
                                                    ->if (event)
                                                        ->ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID);
                                                    ->else
                                                        ->ssusb_set_mailbox(otg_sx, MTU3_VBUS_OFF);
power_supply_core.c             ->power_supply_changed(mtk_chg->ac_psy);
                                    ->schedule_work(&psy->changed_work)
                                ->power_supply_changed(mtk_chg->usb_psy);
                                    ->schedule_work(&psy->changed_work) //INIT_WORK(&psy->changed_work, power_supply_changed_work);
                                        ->power_supply_changed_work(struct work_struct *work)
notifier.c                                  ->atomic_notifier_call_chain(&power_supply_notifier, PSY_EVENT_PROP_CHANGED, psy);
                                                ->__atomic_notifier_call_chain(nh, val, v, -1, NULL)
                                                    ->notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
mtk_power_misc.c                                        ->int mtk_power_misc_psy_event(struct notifier_block *nb, unsigned long event, void *v)
                                                            ->if (strcmp(psy->desc->name, "battery") == 0) {
                                                                ->psy->desc->get_property(psy, POWER_SUPPLY_PROP_TEMP, &val);
mtk_battery.c                                                       ->int battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val)
                                                                ->wake_up_overheat(&sdc);
                                                        ->int charger_psy_event(struct notifier_block *nb, unsigned long event, void *v)
                                                            ->if (strcmp(psy->desc->name, "battery") == 0)
                                                                ->power_supply_get_property(psy, POWER_SUPPLY_PROP_TEMP, &val);
                                                                    ->int battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val)
                                                                ->_wake_up_charger(info);

C Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

mtk_charger.c   static int charger_routine_thread(void *arg)
                    ->if (!info->charger_wakelock.active)
                        __pm_stay_awake(&info->charger_wakelock);   //增加combined_event_count计数
                    ->chr_err("Vbat=%d,Ibat=%d,I=%d,VChr=%d,T=%d,Soc=%d:%d,CT:%d:%d hv:%d pd:%d:%d\n",
                    ->is_charger_on = mtk_is_charger_on(info)
                        ->chr_type = mt_get_charger_type(); //去拿充电类型
                            ->return mtk_chg->chg_type;
                        ->if (chr_type == CHARGER_UNKNOWN && info->chr_type != CHARGER_UNKNOWN) {
                            ->mtk_charger_plug_out(info);
                                ->info->chr_type = CHARGER_UNKNOWN;
                                ->info->charger_thread_polling = false;
                                ->info->plug_out(info);
mtk_switch_charging.c               ->int mtk_switch_charging_plug_out(struct charger_manager *info)
                                        ->swchgalg->total_charging_time = 0;
                                ->wakeup_sc_algo_cmd(&pinfo->sc.data, SC_EVENT_PLUG_OUT, 0);
charger_class.c                 ->charger_dev_set_input_current(info->chg1_dev, 100000);    //info->chg1_dev = get_charger_by_name("primary_chg");
                                ->charger_dev_plug_out(info->chg1_dev);
                                    ->chg_dev->ops->plug_out(chg_dev)   //hl7019没实现,不会报错吗
                        ->else if (info->chr_type == CHARGER_UNKNOWN)
                            ->mtk_charger_plug_in(info, chr_type);
                                ->info->chr_type = chr_type;
                                ->info->charger_thread_polling = true;
                                ->info->can_charging = true;
                                ->info->plug_in(info)
mtk_switch_charging.c               ->int mtk_switch_charging_plug_in(struct charger_manager *info)
                                        ->swchgalg->state = CHR_CC;
                                        ->info->polling_interval = CHARGING_INTERVAL;  //10s
                                        ->get_monotonic_boottime(&swchgalg->charging_begin_time);   //保存充电启示时间
                                ->wakeup_sc_algo_cmd(&pinfo->sc.data, SC_EVENT_PLUG_IN, 0);
charger_class.c                 ->charger_dev_set_input_current(info->chg1_dev, info->chg1_data.input_current_limit);
                                ->charger_dev_plug_in(info->chg1_dev);
                                    ->chg_dev->ops->plug_in(chg_dev)    //hl7019没实现,不会报错吗
                    ->if (info->charger_thread_polling == true)
                        ->mtk_charger_start_timer(info);    //开启定时器用于唤醒线程
                            ->alarm_start(&pinfo->charger_timer, ktime);
mtk_charger.c       ->charger_update_data(info) //检查电池温度
                    ->check_battery_exist(info)
                    ->check_dynamic_mivr(info)
                    ->charger_check_status(info)    //检查充电过程中温度、时间、vbus电压等等,拔插中断不会跑
                        ->charging = true/false;    //先默认为true,然后根据不同状态决定是否赋值false

->if (!mtk_chg_check_vbus(info))  //检查充电器vbus电压

->charging = false;

->if (mt_get_charger_type() == CHARGER_UNKNOWN) //如果是拔出充电器状态,那么直接return;

->return;

->mtk_battery_notify_check(info);

->mtk_battery_notify_VCharger_check(info);  //检查充电器电压

->mtk_battery_notify_VBatTemp_check(info);  //检查电池温度
                        ->if (charging != info->can_charging)   //如果状态发生改变(充电器插入时,一般这里不会跑,因为这两个值都是true)
                            ->_charger_manager_enable_charging(info->chg1_consumer,0, charging);
                                ->_mtk_charger_do_charging(info, en);
                                    ->info->do_charging(info, en);
                                        ->mtk_switch_charging_do_charging(struct charger_manager *info, bool en)
                                            ->if (en)
                                                ->algo_data->disable_charging = false;
                                                ->algo_data->state = CHR_CC;
                                                ->charger_manager_notifier(info, CHARGER_NOTIFY_NORMAL);
                                                    ->int battery_callback(struct notifier_block *nb, unsigned long event, void *v)
                                                        ->battery_main.BAT_STATUS = POWER_SUPPLY_STATUS_CHARGING;
                                                        ->battery_update(&battery_main);
                                            ->else
                                                ->algo_data->disable_charging = true;
                                                ->algo_data->state = CHR_ERROR;
                                                ->charger_manager_notifier(info, CHARGER_NOTIFY_ERROR);
                                                    ->int battery_callback(struct notifier_block *nb, unsigned long event, void *v)
                                                        ->battery_main.BAT_STATUS = POWER_SUPPLY_STATUS_NOT_CHARGING;
                                                        ->battery_update(&battery_main);
                                                ->_disable_all_charging(info);
                                                    ->charger_dev_enable(info->chg1_dev, false);
                    ->kpoc_power_off_check(info)
                        ->boot_mode = get_boot_mode();
                        ->if (boot_mode == KERNEL_POWER_OFF_CHARGING_BOOT || boot_mode == LOW_POWER_OFF_CHARGING_BOOT) {
                            ->orderly_poweroff(true);   //if (system_state != SYSTEM_POWER_OFF) //system_state是整个系统的全局变量
                    ->if (is_charger_on == true) {
                        ->info->do_algorithm(info);
mtk_switch_charging.c       ->mtk_switch_charging_run(struct charger_manager *info)
                                ->struct switch_charging_alg_data *swchgalg = info->algorithm_data
                                ->switch (swchgalg->state) {
                                ->case CHR_CC:
                                    ->mtk_switch_chr_cc(info)
                                        ->get_monotonic_boottime(&time_now);    //获取当前时间
                                        ->charging_time = timespec_sub(time_now, swchgalg->charging_begin_time);    //相减得到充电时间
                                        ->swchg_turn_on_charging(info)
                                            ->swchg_select_charging_current_limit(info) //如果不是META_BOOT
                                                ->struct charger_data *pdata = &info->chg1_data;
                                                ->charger_dev_set_input_current(info->chg1_dev, pdata->input_current_limit)
                                                    ->chg_dev->ops->set_input_current(chg_dev, uA)  //kernel-4.14/drivers/power/supply/mediatek/charger/hl7019.c
                                                ->charger_dev_set_charging_current(info->chg1_dev, pdata->charging_current_limit)
                                                    ->chg_dev->ops->set_charging_current(chg_dev, uA)
                                                ->/*If thermal current limit is larger than charging IC's minimum current setting, enable the charger immediately*/
                                                    ->charger_dev_enable(info->chg1_dev, true);
                                            ->swchg_select_cv(info);
                                                ->charger_dev_set_constant_voltage(info->chg1_dev, constant_voltage);
                                            ->charger_dev_enable(info->chg1_dev, charging_enable)
                                                ->chg_dev->ops->enable(chg_dev, en)
                                        ->charger_dev_is_charging_done(info->chg1_dev, &chg_done);  //读取充电IC CHRG_STAT状态,判断是否充满
                                            ->chg_dev->ops->is_charging_done(chg_dev, done);
                                        ->if (chg_done)
                                            ->swchgalg->state = CHR_BATFULL;
                                            ->charger_dev_do_event(info->chg1_dev, EVENT_EOC, 0);
                                                ->chg_dev->ops->event(chg_dev, event, args);
                                                    ->charger_dev_notify(chg_dev, CHARGER_DEV_NOTIFY_EOC);  //充电IC驱动的.event()会调用charger_dev_notify()
                                                        ->srcu_notifier_call_chain(&chg_dev->evt_nh, event, &chg_dev->noti);

->int charger_dev_event(struct notifier_block *nb, unsigned long event, void *v)  //??
                                ->case CHR_BATFULL:
                                    ->mtk_switch_chr_full(info);
                                        ->swchg_select_cv(info);    //如果被JEITA降低了,这里重新设回来
                                        ->info->polling_interval = CHARGING_FULL_INTERVAL;  //20s
                                        ->charger_dev_is_charging_done(info->chg1_dev, &chg_done);
                                        ->if (!chg_done)
                                            ->swchgalg->state = CHR_CC;
                                            ->get_monotonic_boottime(&swchgalg->charging_begin_time);
                                            ->info->polling_interval = CHARGING_INTERVAL;   
                                ->mtk_switch_check_charging_time(info); //check total charging time
                                ->charger_dev_dump_registers(info->chg1_dev);
                                    ->chg_dev->ops->dump_registers(chg_dev)
mtk_charger.c           ->wakeup_sc_algo_cmd(&pinfo->sc.data, SC_EVENT_CHARGING, 0);
                    ->if (is_charger_on == false) {
                        ->wakeup_sc_algo_cmd(&pinfo->sc.data, SC_EVENT_STOP_CHARGING, 0);
                    __pm_relax(&info->charger_wakelock);   //减少combined_event_count计数

如果温度过高:

/kernel-4.14/drivers/misc/mediatek/thermal/common/coolers/mtk_cooler_bcct_v1.c

chrlmt_set_limit_handler  //INIT_WORK(&bcct_chrlmt_work, chrlmt_set_limit_handler);

  charger_manager_set_charging_current_limit(pthermal_consumer, 0, ((chrlmt_bat_chr_curr_limit != -1) ?chrlmt_bat_chr_curr_limit * 1000 : -1));

    pdata->thermal_charging_current_limit = charging_current;

linear_chg_select_charging_current_limit

  chr_err("force:%d thermal:%d setting:%d type:%d usb_unlimited:%d usbif:%d usbsm:%d\n",

MT8168中断流程相关推荐

  1. QN902X在KEIL中使用定时器中断流程记录

    仅以此篇,记录蓝牙BLE(QN902x)开发过程中,使用ke_timer_set ((p_ke_timer_set)(_ke_timer_set))的流程: 首先,我们要使用这个函数,必须先了解它能干 ...

  2. 【3分钟秒懂】示例讲解MCU中断流程 基于NXP MPC574xG

    目录 1. 简述 2. 中断配置流程 3. 中断发生时的代码调用流程 1. 简述 MPC574xG的中断向量寄存器(IVPR)提供了下面12个个中断类型, 本文主要介绍IVOR4 ,因为所有的时钟,外 ...

  3. Linux中断流程分析

    裸机中断: 1.中断流入口 2.事先注册中断处理程序 3.根据中断源编号,调取处理程序 irq_svc:1.等到产生中断源的编号(每一个中断号都有一个描述结构) 2. 转载于:https://www. ...

  4. 7.21.05 中断流程控制语句

    // 1. break //break语句用于do-while while for语句时,可以是程序终止循环,而执行循环体后的语句. //一般和一条判断语句一起使用,条件判断为真得时候,跳出循环. / ...

  5. [答疑]-中断流程举例:在TEE侧时产生了FIQ,回到REE后为啥又产生了IRQ

    快速链接: .

  6. [答疑]-中断流程举例:在REE(SCR.FIQ=1)侧时产生了FIQ,跳转到EL3后做了哪些事情?

    快速链接: .

  7. 中断处理过程示意图_PCIe中断方法和系统与流程

    本发明实施例涉及通信技术领域,尤其涉及一种PCIe中断方法和系统. 背景技术: PCIe(Peripheral Component Interconnect Express,高速外围组件互联)是最新的 ...

  8. PicoBlaze中断

    PicoBlaze中断 我们知道,PicoBlaze微控制器只提供一个中断输入口,如果设计中需要多个中断,可以在FPGA中用逻辑实现.图12-4 所示为一个简单的中断连接图,当有中断发生时,触发器的2 ...

  9. [gic]-linux和optee的中断处理流程举例(gicv3举例)

    ★★★ 友情链接 : 个人博客导读首页-点击此处 ★★★ 环境配置: 在linux/optee双系统环境下, linux系统的SCR.IRQ=0.SCR.FIQ=1, optee系统的SCR.IRQ= ...

最新文章

  1. oracle12c不能进入到http://localhost:1158/em的解决办法
  2. [云炬创业基础笔记]第七张创业资源测试12
  3. SQL Server 表变量和临时表的区别
  4. 【重版】朴素贝叶斯与拣鱼的故事
  5. 求数组中k个数的所有组合
  6. .Net学习(二):vb.net总结之似曾相识
  7. scala 辅助构造函数_Scala辅助构造函数的深入介绍
  8. java 数组减除值_java数组操作 - osc_hwpd2zko的个人空间 - OSCHINA - 中文开源技术交流社区...
  9. 呼吸灯 裸机 S3C2416
  10. grpc(5):使用grpc+consul 开发服务调用
  11. Visual Studio Code编辑器的实用插件和工作中实用的技巧
  12. 安卓蓝牙键盘按键映射_安卓手游键盘映射工具(凤凰系统键盘映射) v2.0 最新版...
  13. 大学生爱情兵法-洪亚非-听课笔记
  14. Excel的FIND函数及其用法
  15. f2fs系列之一:实战f2fs 下载、编译和挂载 [转载系列]
  16. Java 类详解 9章
  17. 目标检测——小目标检测问题
  18. Uva 1616 Caravan Robbers (商队抢劫者)
  19. Meta再放大招!VR新模型登CVPR Oral:像人一样「读」懂语音
  20. 为什么英语学习得不到我们想要的效果?

热门文章

  1. 【C语言进阶】文件的顺序读写、随机读写、文本文件和二进制文件、文件读取结束的判定以及文件缓冲区相关知识
  2. 利用unity和steamVR完成场景漫游(二) 关于steamVR插件中的代码详解
  3. 君子签:用区块链技术打造电子签约全生态闭环服务
  4. 有道精品课python-诚意推荐几个腾讯、美团、阿里技术大佬的公号
  5. ExcelUtils
  6. uni-app导入到微信开发工具失败端口没有打开
  7. RS232/RS422/RS485串口引脚连线
  8. 中国移动5G套餐预约用户已超100万
  9. 机器学习和人工智能方法在CADD中的应用
  10. 改善二阶系统动态性能的方法