fg代码阅读笔记2

jeita配置

代码路径:
/kernel/msm-3.18/drivers/power/qpnp_smbcharger.c

smbchg_hw_init(struct smbchg_chip *chip)
/* configure jeita temperature hard limit */
    if (chip->jeita_temp_hard_limit >= 0) {
        rc = smbchg_sec_masked_write(chip,chip->chgr_base + CHGR_CCMP_CFG,
            JEITA_TEMP_HARD_LIMIT_BIT,chip->jeita_temp_hard_limit
            ? 0 : JEITA_TEMP_HARD_LIMIT_BIT);
    }
smb_parse_dt(struct smbchg_chip *chip)
OF_PROP_READ(chip, chip->jeita_temp_hard_limit,"jeita-temp-hard-limit", rc, 1);

看一下这个属性是什么作用?
qcom,jeita-temp-hard-limit property when present will enable or disable the jeita temperature hard limit based on the value 1 or 0. Specify 0 if the jeita temp hard limit needs to be disabled. If it is not present,jeita temperature hard limit will be based on what the bootloader had set earlier.
写1打开jeita hard temp limit写0关闭jieta hard temp limit ???目前代码里没有设置该属性。

这里写图片描述

fg_probe
   rc = fg_of_init(chip);
    OF_READ_SETTING(FG_MEM_SOFT_HOT, "warm-bat-decidegc", rc, 1);
    OF_READ_SETTING(FG_MEM_SOFT_COLD, "cool-bat-decidegc", rc, 1);
    OF_READ_SETTING(FG_MEM_HARD_HOT, "hot-bat-decidegc", rc, 1);
    OF_READ_SETTING(FG_MEM_HARD_COLD, "cold-bat-decidegc", rc, 1);
    //以上会将dtsi中配置的温度信息写入到setings中
    if (of_find_property(node, "qcom,cold-hot-jeita-hysteresis", NULL)) {//dtsi中是否配置了高低温迟滞属性
        int hard_hot = 0, soft_hot = 0, hard_cold = 0, soft_cold = 0;

        rc = of_property_read_u32_array(node,"qcom,cold-hot-jeita-hysteresis", temp, 2);
        if (rc) {//将设置的迟滞温度读到temp中
            pr_err("Error reading cold-hot-jeita-hysteresis rc=%d\n",rc);
            return rc;
        }

        chip->jeita_hysteresis_support = true;//支持高低温迟滞属性
        chip->cold_hysteresis = temp[0];//低温迟滞
        chip->hot_hysteresis = temp[1];//高温迟滞
        hard_hot = settings[FG_MEM_HARD_HOT].value;
        soft_hot = settings[FG_MEM_SOFT_HOT].value;
        hard_cold = settings[FG_MEM_HARD_COLD].value;
        soft_cold = settings[FG_MEM_SOFT_COLD].value;
        if (((hard_hot - chip->hot_hysteresis) < soft_hot) ||((hard_cold + chip->cold_hysteresis) > soft_cold)) {
            chip->jeita_hysteresis_support = false;//判断迟滞温度是否合法
            pr_err("invalid hysteresis: hot_hysterresis = %d cold_hysteresis = %d\n",
chip->hot_hysteresis, chip->cold_hysteresis);
        } else {
            pr_debug("cold_hysteresis = %d, hot_hysteresis = %d\n",chip->cold_hysteresis, chip->hot_hysteresis);
        }
    }

申请中断

fg_probe
 rc = fg_init_irqs(chip);
  case FG_BATT:
    chip->batt_irq[JEITA_SOFT_COLD].irq =spmi_get_irq_byname(chip->spmi, spmi_resource,
    "soft-cold");//通过中断名soft-cold获得中断号
    if (chip->batt_irq[JEITA_SOFT_COLD].irq < 0) {
        pr_err("Unable to get soft-cold irq\n");
        rc = -EINVAL;
        return rc;
}
    rc = devm_request_threaded_irq(chip->dev,chip->batt_irq[JEITA_SOFT_COLD].irq,NULL,
    fg_jeita_soft_cold_irq_handler,IRQF_TRIGGER_RISING |IRQF_TRIGGER_FALLING |
IRQF_ONESHOT,"soft-cold", chip);//注册申请soft cold中断,
中断处理函数fg_jeita_soft_cold_irq_handler,上升沿或下降沿触发
    if (rc < 0) {
pr_err("Can't request %d soft-cold: %d\n",
    chip->batt_irq[JEITA_SOFT_COLD].irq,rc);
    return rc;
    }
        disable_irq(chip->batt_irq[JEITA_SOFT_COLD].irq);//关闭中断
        chip->batt_irq[JEITA_SOFT_COLD].disabled = true;//设置关闭中断后变量的状态
        chip->batt_irq[JEITA_SOFT_HOT].irq =spmi_get_irq_byname(chip->spmi, spmi_resource,
        "soft-hot");//通过中断名soft-hot获得中断号
        if (chip->batt_irq[JEITA_SOFT_HOT].irq < 0) {
            pr_err("Unable to get soft-hot irq\n");
            rc = -EINVAL;
            return rc;
        }
        rc = devm_request_threaded_irq(chip->dev,chip->batt_irq[JEITA_SOFT_HOT].irq,NULL,
        fg_jeita_soft_hot_irq_handler,IRQF_TRIGGER_RISING |IRQF_TRIGGER_FALLING |
        IRQF_ONESHOT,"soft-hot", chip); //注册申请soft hot中断,
中断处理函数fg_jeita_soft_cold_irq_handler,上升沿或下降沿触发
        if (rc < 0) {
            pr_err("Can't request %d soft-hot: %d\n",
            chip->batt_irq[JEITA_SOFT_HOT].irq, rc);
            return rc;
        }
        disable_irq(chip->batt_irq[JEITA_SOFT_HOT].irq); //关闭中断
        chip->batt_irq[JEITA_SOFT_HOT].disabled = true; //设置关闭中断后变量的状态

先来看中断处理函数做了哪些事情?

fg_jeita_soft_hot_irq_handler
rc = fg_read(chip, &regval, INT_RT_STS(chip->batt_base), 1);//寄存器1218
batt_warm = !!(regval & BATT_SOFT_HOT_STS);//电池高温warm状态
if (chip->batt_warm == batt_warm) {
        pr_debug("warm state not change, ignore!\n");//之前的状态就是warm中断不做处理
        return IRQ_HANDLED;
    }
    chip->batt_warm = batt_warm;
if (batt_warm) {
        val.intval = POWER_SUPPLY_HEALTH_WARM;
        chip->batt_psy->set_property(chip->batt_psy,
            POWER_SUPPLY_PROP_HEALTH, &val);
//设置health property为POWER_SUPPLY_HEALTH_WARM
        /* kick the alarm timer for hard hot polling */
        rc = alarm_start_relative(&chip->hard_jeita_alarm,//启动定时器检测电池hot状态
                ns_to_ktime(HARD_JEITA_ALARM_CHECK_NS));
        if (rc)
            pr_err("start alarm for hard HOT detection failed, rc=%d\n",
                                    rc);
    } else {
        val.intval = POWER_SUPPLY_HEALTH_GOOD;
        chip->batt_psy->set_property(chip->batt_psy,POWER_SUPPLY_PROP_HEALTH, &val);
        /* cancel the alarm timer */
        alarm_try_to_cancel(&chip->hard_jeita_alarm);
    }
    return IRQ_HANDLED;

上面的处理函数中调用alarm_start_relative启动了一个10秒的定时器HARD_JEITA_ALARM_CHECK_NS = 10000000000ns=10000000us=10000ms =10s,这个定时器是在哪里初始化的?
fg_probe
alarm_init(&chip->hard_jeita_alarm, ALARM_BOOTTIME,fg_hard_jeita_alarm_cb);初始化一个定时器hard_jeita_alarm,定时时间到后执行回调函数fg_hard_jeita_alarm_cb
从上面的中断处理程序分析可以知道到soft_hot中断到来后会读状态寄存器1218查看是否是电池高温了,如果是电池warm则设置HEALTH属性,然后启动10s的定时器去检测这时候电池温度有没有达到hard hot的状态。现在就来看10s的回调函数都做了哪些事情?

fg_hard_jeita_alarm_cb
rc = fg_read(chip, &regval, BATT_INFO_STS(chip->batt_base), 1);
batt_hot = !!(regval & JEITA_HARD_HOT_RT_STS); //batt_hot=1或者batt_hot=0
batt_cold = !!(regval & JEITA_HARD_COLD_RT_STS);// batt_cold =1或者batt_cold = 0
if (batt_cold != chip->batt_cold) { 
        /* cool --> cold */
        if (chip->batt_cool) {
            chip->batt_cool = false;
            chip->batt_cold = true;
            health = POWER_SUPPLY_HEALTH_COLD;//电池由cool到了cold状态
        } else if (chip->batt_cold) { /* cold --> cool */
            chip->batt_cool = true;
            chip->batt_cold = false;
            health = POWER_SUPPLY_HEALTH_COOL; //电池由cold到了cool状态
        }
    }

    if (batt_hot != chip->batt_hot) {
        /* warm --> hot */
        if (chip->batt_warm) {
            chip->batt_warm = false;
            chip->batt_hot = true;
            health = POWER_SUPPLY_HEALTH_OVERHEAT; //电池由warm到了hot状态
        } else if (chip->batt_hot) { /* hot --> warm */
            chip->batt_hot = false;
            chip->batt_warm = true;
            health = POWER_SUPPLY_HEALTH_WARM; //电池由hot到了warm状态
        }
    }
if (health != POWER_SUPPLY_HEALTH_UNKNOWN) {
        pr_debug("FG report battery health: %d\n", health);
        val.intval = health;
        rc = chip->batt_psy->set_property(chip->batt_psy,
                POWER_SUPPLY_PROP_HEALTH, &val);再次设置health的属性为cold或者hot
        if (rc)
            pr_err("Set batt_psy health: %d failed\n", health);
    }

上面的分析中最后都调用了rc = chip->batt_psy->set_property(chip->batt_psy,
POWER_SUPPLY_PROP_HEALTH, &val);后面又是如何处理的?

fg_power_set_property
    case POWER_SUPPLY_PROP_HEALTH:
        chip->health = val->intval;
        if (chip->health == POWER_SUPPLY_HEALTH_GOOD) {
            fg_stay_awake(&chip->resume_soc_wakeup_source);
            schedule_work(&chip->set_resume_soc_work);
        }
        if (chip->jeita_hysteresis_support)
            fg_hysteresis_config(chip);
        break;

fg_hysteresis_config
    hard_hot = get_prop_jeita_temp(chip, FG_MEM_HARD_HOT);
    hard_cold = get_prop_jeita_temp(chip, FG_MEM_HARD_COLD);
    if (chip->health == POWER_SUPPLY_HEALTH_OVERHEAT && !chip->batt_hot) {
        /* turn down the hard hot threshold */
        chip->batt_hot = true;
        set_prop_jeita_temp(chip, FG_MEM_HARD_HOT,
            hard_hot - chip->hot_hysteresis);
        if (fg_debug_mask & FG_STATUS)
            pr_info("hard hot hysteresis: old hot=%d, new hot=%d\n",
                hard_hot, hard_hot - chip->hot_hysteresis);
    } else if (chip->health == POWER_SUPPLY_HEALTH_COLD &&
        !chip->batt_cold) {
        /* turn up the hard cold threshold */
        chip->batt_cold = true;
        set_prop_jeita_temp(chip, FG_MEM_HARD_COLD,
            hard_cold + chip->cold_hysteresis);
        if (fg_debug_mask & FG_STATUS)
            pr_info("hard cold hysteresis: old cold=%d, new cold=%d\n",
                hard_cold, hard_cold + chip->hot_hysteresis);
    } else if (chip->health != POWER_SUPPLY_HEALTH_OVERHEAT &&
        chip->batt_hot) {
        /* restore the hard hot threshold */
        set_prop_jeita_temp(chip, FG_MEM_HARD_HOT,
            hard_hot + chip->hot_hysteresis);
        chip->batt_hot = !chip->batt_hot;
        if (fg_debug_mask & FG_STATUS)
            pr_info("restore hard hot threshold: old hot=%d, new hot=%d\n",
                hard_hot,hard_hot + chip->hot_hysteresis);
    } else if (chip->health != POWER_SUPPLY_HEALTH_COLD &&
        chip->batt_cold) {
        /* restore the hard cold threshold */
        set_prop_jeita_temp(chip, FG_MEM_HARD_COLD,
            hard_cold - chip->cold_hysteresis);
        chip->batt_cold = !chip->batt_cold;
        if (fg_debug_mask & FG_STATUS)
            pr_info("restore hard cold threshold: old cold=%d, new cold=%d\n",
                hard_cold,hard_cold - chip->cold_hysteresis);
    }
### 日常Java代码片段或学习笔记 为了帮助理解和掌握Java编程语言,记录每日的学习笔记代码片段是非常有益的做法。下面是一些关于如何创建有效的Java学习笔记以及一些常见的代码示例。 #### 创建高效的学习笔记 保持结构化的学习日志有助于长期记忆和技术积累。建议按照以下方式组织: - **日期**:每次条目都应标注具体日期以便追踪进度。 - **主题/目标**:简要描述当天计划学习的内容或解决的问题。 - **知识点总结**:概述新学到的概念及其应用场景。 - **遇到的挑战与解决方案**:记录下任何困难之处及最终是如何克服这些障碍的[^1]。 #### 实用的Java代码片段 这里提供几个基础但重要的Java程序作为例子供参考: ##### 1. Hello World Program 这是每一个程序员接触一门新的编程语言时都会编写的第一个小程序。 ```java public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, world!"); } } ``` ##### 2. Fibonacci Sequence Generator 此函数可以用来生成斐波那契数列中的前n项。 ```java import java.util.ArrayList; import java.util.List; public class FibonacciGenerator { private List<Integer> generateFibonacci(int n){ ArrayList<Integer> fibSeries = new ArrayList<>(); int num1=0,num2=1; for (int i = 0; i < n ;i++){ if(i==0)fibSeries.add(num1); else if(i==1)fibSeries.add(num2); else{ int sum=num1+num2; fibSeries.add(sum); num1=num2; num2=sum; } } return fibSeries; } public static void main(String []args){ FibonacciGenerator fg=new FibonacciGenerator(); System.out.println(fg.generateFibonacci(10)); } } ``` ##### 3. Simple File Reader Example 展示如何读取文本文件并打印其内容到控制台。 ```java import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class FileReaderExample { public static void readFileContent(String filePath) throws IOException { try(BufferedReader br = new BufferedReader(new FileReader(filePath))) { String currentLine; while ((currentLine = br.readLine()) != null) { System.out.println(currentLine); } } } public static void main(String[] args)throws Exception { // Replace with your file path here. String fileName="example.txt"; readFileContent(fileName); } } ``` 通过持续更新个人的知识库,并定期回顾之前的工作成果,能够极大地促进技能的成长和发展。同时,在面对技术选型决策时,合理的讨论和灵活的态度也是至关重要的[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值