qcom charger

1.充电类型

The four power source types that are detected are:

1. Standard downstream port (SDP)
– This is a computer USB port capable of USB 1.1 (100 mA), USB 2.0 (100/500 mA), or USB 3.0 (150/900 mA). D+ and Dare independently pulled down in the host with a 14.2524.8 kΩ resistance.

2. Charging downstream port (CDP)
– This is typically a powered USB hub capable of 1.5 A.

3. Dedicated charging port (DCP)  标充
– This is a (standard wall charger) capable of at least 500 mA. D+ and D- are shorted in the wall adapter with a maximum
resistance of 200 Ω. SCHG defaults to high current mode and runs automatic input current limiting (AICL).


4. Other charging port (not covered by USB charging specification 1.2)
– This is a non-standard charger with a proprietary D+/D- configuration. Typically, these chargers have similar current
capability to normal DCPs. D+ and D- are connected to Vbus via a resistor divider, which causes them to be at specific fixed
voltage levels

    from <80-p2536-5a_e_pm8953_+_pmi8952_power_management_ic_design_guidelines_training_slides.pdf>
*/

2.charger

2.1 usb 插入、充电类型检测、快充检测

// 

 "usbin-src-det",


static irqreturn_t src_detect_handler(int irq, void *_chip)
{
....
if (src_detect) {
        update_usb_status(chip, usb_present, 0);
    } else {
        update_usb_status(chip, 0, false);
....
}


void update_usb_status(struct smbchg_chip *chip, bool usb_present, bool force)
{

...
            if (!chip->usb_present && usb_present) {
                    chip->usb_present = usb_present;
                    handle_usb_insertion(chip);
                } else if (chip->usb_present && !usb_present) {
                    chip->usb_present = usb_present;
                    handle_usb_removal(chip);
                }
...
}





 // usb插入开启快充检测

 static void handle_usb_insertion(struct smbchg_chip *chip)
 {
...
    read_usb_type(chip, &usb_type_name, &usb_supply_type);      ->    smbchg_read(chip, &reg, chip->misc_base + IDEV_STS, 1);    // 读取1608寄存器获取充电类型

    smbchg_change_usb_supply_type(chip, usb_supply_type);


         // 快充检测
        if (!chip->hvdcp_not_supported &&(usb_supply_type == POWER_SUPPLY_TYPE_USB_DCP)) 
        {
        cancel_delayed_work_sync(&chip->hvdcp_det_work);
        smbchg_stay_awake(chip, PM_DETECT_HVDCP);
        schedule_delayed_work(&chip->hvdcp_det_work,msecs_to_jiffies(HVDCP_NOTIFY_MS));
    }


 }

2.2 复充,充电截止






        pmi8950_fg: qcom,fg {
            spmi-dev-container;
            compatible = "qcom,qpnp-fg";
            #address-cells = <1>;
            #size-cells = <1>;
            qcom,resume-soc = <95>;            // 复充电量
            status = "okay";
            qcom,bcl-lm-threshold-ma = <127>;   
            qcom,bcl-mh-threshold-ma = <405>;
            qcom,fg-iterm-ma = <150>;               // 截止电流
            qcom,fg-chg-iterm-ma = <100>;       // 截止电流
                        qcom,fg-cutoff-voltage-mv = <3400>;    // 关机电压






// msm-pmi8950.dtsi
  pmi8950_charger: qcom,qpnp-smbcharger {
            spmi-dev-container;
            compatible = "qcom,qpnp-smbcharger";
                        qcom,iterm-ma = <256>;                                  // 充电截止电流
                        qcom,resume-delta-mv = <100>;                   // 复充电压
            qcom,chg-inhibit-fg;                                         // 如果有这个定义,则复充条件都使用上边的fg设置

            qcom,float-voltage-mv = <4400>;                    // Maximum voltage up to which the battery is charged; supported range is 3.6 V to 4.5 V.
                        qcom,thermal-mitigation = <1900 1900 1900 0>;   // 不同温度的电流限制


                         qcom,fg-cc-cv-threshold-mv = <4400>;       // cc - cv的电压条件
             qcom,autoadjust-vfloat;               // A Boolean property that when set, makes the driver automatically readjust vfloat using the fuel gauge ADC readings to make chargingmore accurate.
             }                        






//


        chip->chg_inhibit_source_fg = of_property_read_bool(node,"qcom,chg-inhibit-fg");        // 如果有这个定义,则截止电流复充条件都使用上边的fg设置





static int smbchg_hw_init(struct smbchg_chip *chip)

{

....
          // 复充条件使用fg adc还是
    /*
     * Based on the configuration, use the analog sensors or the fuelgauge
     * adc for recharge threshold source.
     */

    if (chip->chg_inhibit_source_fg)
        rc = smbchg_sec_masked_write(chip, chip->chgr_base + CHGR_CFG1,
            TERM_I_SRC_BIT | RECHG_THRESHOLD_SRC_BIT,
            TERM_SRC_FG | RECHG_THRESHOLD_SRC_BIT);
    else
        rc = smbchg_sec_masked_write(chip, chip->chgr_base + CHGR_CFG1,
            TERM_I_SRC_BIT | RECHG_THRESHOLD_SRC_BIT, 0);
....
}

2.3.根据pmic寄存器判断是否充满

get_prop_batt_status

2.4 根据充电类型限制充电电流

static int smbchg_change_usb_supply_type(struct smbchg_chip *chip,enum power_supply_type type)
{

if (type == POWER_SUPPLY_TYPE_USB)
        current_limit_ma = DEFAULT_SDP_MA;
    else if (type == POWER_SUPPLY_TYPE_USB)
        current_limit_ma = DEFAULT_SDP_MA;
    else if (type == POWER_SUPPLY_TYPE_USB_CDP)
        current_limit_ma = DEFAULT_CDP_MA;
    else if (type == POWER_SUPPLY_TYPE_USB_HVDCP)
        current_limit_ma = smbchg_default_hvdcp_icl_ma;         // 快充充电电流限制
    else if (type == POWER_SUPPLY_TYPE_USB_HVDCP_3)
        current_limit_ma = smbchg_default_hvdcp3_icl_ma;
    else
        current_limit_ma = smbchg_default_dcp_icl_ma;

        rc = vote(chip->usb_icl_votable, PSY_ICL_VOTER, true,
                current_limit_ma);

.....


}

2.5 充电电流限制的 vote & votable


static int smbchg_probe(struct spmi_device *spmi)

{

...
    // 创建充电电流限制的vote
    chip->usb_icl_votable = create_votable(&spmi->dev,
            "SMBCHG: usb_icl",
            VOTE_MIN, NUM_ICL_VOTER, 3000,
            set_usb_current_limit_vote_cb);   // 回调函数
....
}

2.6 获取充电状态

static int get_prop_batt_status(struct smbchg_chip *chip)
{
....
charger_present = is_usb_present(chip) | is_dc_present(chip) |
              chip->hvdcp_3_det_ignore_uv;
    if (!charger_present)
        return POWER_SUPPLY_STATUS_DISCHARGING;
...
    POWER_SUPPLY_STATUS_FULL
    POWER_SUPPLY_STATUS_NOT_CHARGING
    POWER_SUPPLY_STATUS_CHARGING
}

2.7 打开、关闭充电

static int smbchg_charging_en(struct smbchg_chip *chip, bool en)
{
/* The en bit is configured active low */
    return smbchg_masked_write(chip, chip->bat_if_base + CMD_CHG_REG,
            EN_BAT_CHG_BIT, en ? 0 : EN_BAT_CHG_BIT);
}

2.8 设置满电电压

static int smbchg_float_voltage_set(struct smbchg_chip *chip, int vfloat_mv)

2.9 限制充电电流

static int smbchg_set_fastchg_current_raw(struct smbchg_chip *chip,int current_ma)

2.10 thermal & jeta


cat sys/class/power_supply/battery/system_temp_level    // 正常值为0

qcom,thermal-mitigation = <1900 1900 1900 0>;   // 不同温度的电流限制

// 超过限制temp level会导致usb charger suspend

static int smbchg_system_temp_level_set(struct smbchg_chip *chip,int lvl_sel)
{
    ...
            if (chip->therm_lvl_sel == (chip->thermal_levels - 1)) {
                  // disable charger  
                  rc = vote(chip->usb_suspend_votable, THERMAL_EN_VOTER, true, 0);
               }
 ....

                //限制充电电流
                thermal_icl_ma =(int)chip->thermal_mitigation[chip->therm_lvl_sel];
            vote(chip->usb_icl_votable, THERMAL_ICL_VOTER, true,thermal_icl_ma);     
 ....

            if (prev_therm_lvl == chip->thermal_levels - 1)  //恢复回充温度
                // enable charger
                rc = vote(chip->usb_suspend_votable, THERMAL_EN_VOTER, false, 0);
...

}

2.11 是否支持快充

chip->hvdcp_not_supported

2.12.非标充

    usb_otg: usb@78db000 {
        compatible = "qcom,hsusb-otg";          // phy-msm-usb.c
...
                qcom,floated-charger-enable = <1>;   //enable float charger 需添加高通patch
...
    }

2.13 满电电量

POWER_SUPPLY_PROP_VOLTAGE_MAX

2.14 .限制充电电流

 smbchg_set_fastchg_current_raw(chip, val->intval);

3.fg

3.1 battery thermal && qcom,battery-data && some property (dts)

// msm8953-qrd.dtsi

&pmi8950_fg {
    compatible = "qcom,qpnp-fg";
    qcom,battery-data = <&qrd_batterydata>;

        // 通过fg内部adc读取温度值
        qcom,thermal-coefficients = [DA 86 F0 50 08 3C];            // ntc热敏电阻的系数查表得出  (80-nv610-41_c_linux_android_pmic_fuel_gauge_user_guide.pdf page 11    80-vt310-123_c_pmi8994_fuel_gauge_hw_sw_control.pdf page 14)
...

    }



/ {
    qrd_batterydata: qcom,battery-data {
        qcom,batt-id-range-pct = <15>;                  // battey_id 电阻精确范围
        #include "xxxxx_7000mAh_averaged_MasterSlave.dtsi"  
                #include "xxxxx_7000mAh_averaged_SecondSlave.dtsi" 
    };
};



// xxxx_7000mAh_averaged_MasterSlave.dtsi
qcom,xxxxxxx6000atl_7000mah_averaged_masterslave_feb15th2017 {
...
    qcom,batt-id-kohm = <51>;                       // battery id
    qcom,max-voltage-uv = <4400000>;                   // 满电电压
    qcom,nom-batt-capacity-mah = <7000>;            // 电池容量
        qcom,fastchg-current-ma = <2500>;                   // charger current

...



3.2 获取 battery_id 电阻大小 (POWER_SUPPLY_PROP_RESISTANCE_ID)

static int fg_power_get_property(struct power_supply *psy,
                       enum power_supply_property psp,
                       union power_supply_propval *val)

{
        case POWER_SUPPLY_PROP_RESISTANCE_ID:
                //val->intval = get_sram_prop_now(chip, FG_DATA_BATT_ID);
                 val->intval = cm_get_ID1();
                if(val->intval == 0x21)
                     val->intval = 100000;
                else
                val->intval =1000000;
                break;

}

3.3 根据battery_id获取最佳电池数据dtsi文件


static int fg_batt_profile_init(struct fg_chip *chip)
{

        /*
         (of_batterydata.c)   
         获取最佳node by "qcom,batt-id-kohm" 
         内阻值在 "qcom,batt-id-range-pct" 范围内则使用这个node    

         fg_batt_type 为指定电池name,如果指定就只会从指定name的 dts中查找,一般不指定
     */        
    profile_node = of_batterydata_get_best_profile(batt_node, "bms",fg_batt_type);     


}

3.4 qcom,charge-unknown-battery; bringup未设置电池参数时,开启这个选项

PMI8952 charger bringup without battery profile To allow charging to proceed with an unknown battery profile (for example, for bringup purposes before
battery characterization), include the following device tree property in your charger device tree node
(qcom,qpnp-smbcharger):
qcom,charge-unknown-battery;

3.5 高低温下满电、充电电流修改



//3.  msm-pmi8950.dtsi   warm charge cold charger 


--- a/arch/arm/boot/dts/qcom/msm-pmi8950.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pmi8950.dtsi
@@ -217,7 +217,7 @@
            qcom,aicl-rerun-period-s = <180>;
            qcom,autoadjust-vfloat;
            qcom,fastchg-current-comp = <700>;// 高低温下的充电电流 Supported values are 250, 700,900 and 1200mA. Set normal current is 2A.\u9ad8\u4f4e\u6e29\u8bbe\u7f6e\u7ea6\u4e3a0.3*2A
-           qcom,float-voltage-comp =<11>;//warm或者cool状态的限制电压为4.2V,4.4V对应的值0x2E.4.1V is 0x23, so 0x2E-0x23 = 11(10进制)( 80-nt391-2x_e_pmi8952_hardware_register_description.pdf  SMBCHGL_CHGR_FV_CFG)
+           qcom,float-voltage-comp =<9>;//warm或者cool状态的限制电压为4.2V,4.4V对应的值0x2E.4.1V is 0x23, so 0x2E-0x23 = 11(10进制)
            qcom,chgr@1000 {
                reg = <0x1000 0x100>;



diff --git a/drivers/power/qpnp-smbcharger.c b/drivers/power/qpnp-smbcharger.c
index bad46e2..36c1dd8 100644
--- a/drivers/power/qpnp-smbcharger.c
+++ b/drivers/power/qpnp-smbcharger.c
@@ -6207,7 +6203,16 @@ static irqreturn_t batt_warm_handler(int irq, void *_chip)
 {
    struct smbchg_chip *chip = _chip;
    u8 reg = 0;
-
+   int rc;
+   /* 高温设置满电电压为 4.24V */
+   if (chip->float_voltage_comp != -EINVAL) {
+       rc = smbchg_float_voltage_comp_set(chip,
+           chip->float_voltage_comp);
+       if (rc < 0)
+           dev_err(chip->dev, "Couldn't set float voltage comp rc = %d\n",rc);
+       pr_smb(PR_STATUS, "set float voltage comp to %d\n",
+           chip->float_voltage_comp);
+   }
    smbchg_read(chip, &reg, chip->bat_if_base + RT_STS, 1);
    chip->batt_warm = !!(reg & HOT_BAT_SOFT_BIT);
    pr_smb(PR_INTERRUPT, "triggered: 0x%02x\n", reg);


@@ -6223,7 +6228,11 @@ static irqreturn_t batt_cool_handler(int irq, void *_chip)
 {
    struct smbchg_chip *chip = _chip;
    u8 reg = 0;
-
+   int rc;
+   /* 低温设置满电电压为 4.4V*/
+   rc = smbchg_float_voltage_comp_set(chip,0);
+   if (rc < 0)
+       dev_err(chip->dev, "Couldn't set float voltage comp rc = %d\n",rc);
    smbchg_read(chip, &reg, chip->bat_if_base + RT_STS, 1);
    chip->batt_cool = !!(reg & COLD_BAT_SOFT_BIT);
    pr_smb(PR_INTERRUPT, "triggered: 0x%02x\n", reg);


3.6 电量跳变


// 4.

 //   修改内部电量计的更新频率


--- a/drivers/power/qpnp-fg.c
+++ b/drivers/power/qpnp-fg.c
@@ -1973,12 +1973,12 @@ static void fg_handle_battery_insertion(struct fg_chip *chip)
    schedule_delayed_work(&chip->update_sram_data, msecs_to_jiffies(0));
 }

-
+#if 0     //this function is not used for a while.  it used in the "fg_common_hw_init" function originally
 static int soc_to_setpoint(int soc)
 {
    return DIV_ROUND_CLOSEST(soc * 255, 100);
 }
-
+#endif
 static void batt_to_setpoint_adc(int vbatt_mv, u8 *data)
 {
    int val;
@@ -7931,7 +7931,7 @@ static int fg_common_hw_init(struct fg_chip *chip)
    }

    rc = fg_mem_masked_write(chip, settings[FG_MEM_DELTA_SOC].address, 0xFF,
-           soc_to_setpoint(settings[FG_MEM_DELTA_SOC].value),
+           settings[FG_MEM_DELTA_SOC].value,
            settings[FG_MEM_DELTA_SOC].offset);
    if (rc) {
        pr_err("failed to write delta soc rc=%d\n", rc);


3.7 fg从reg中读取数据值更新



static int update_sram_data(struct fg_chip *chip, int *resched_ms)


// fg_data[i] 的数据含义
enum fg_mem_data_index {
    FG_DATA_BATT_TEMP = 0,
    FG_DATA_OCV,
    FG_DATA_VOLTAGE,
    FG_DATA_CURRENT,
    FG_DATA_BATT_ESR,
    FG_DATA_BATT_ESR_COUNT,
    FG_DATA_BATT_SOC,
    FG_DATA_CC_CHARGE,
    FG_DATA_VINT_ERR,
    FG_DATA_CPRED_VOLTAGE,
    /* values below this only gets read once per profile reload */
    FG_DATA_BATT_ID,
    FG_DATA_BATT_ID_INFO,
    FG_DATA_MAX,
};

4. vadc

qpnp-adc-voltage.c

4.1 获取温度值方法一





 //4.1 mpp2设置为vac输入模式

pm8937_mpps: mpps {
    ...     
            mpp@a100 {     
                /* MPP2 - VBUS CHARGE THERMAL config */
                reg = <0xa100 0x100>;
                qcom,pin-num = <2>;
                qcom,mode = <4>; /* AIN input */
                qcom,invert = <1>; /* Enable MPP */
                qcom,ain-route = <1>; /* AMUX 6 */
                qcom,master-en = <1>;
                qcom,src-sel = <0>; /* Function constant */
            };
    ...
}


 // 4.2 mmp2对应chanel 11 ( form 80-nv610-45_b_pmic_adc_software_user_guide.pdf PM8952 AMUX channels )
pm8937_vadc: vadc@3100 {
    compatible = "qcom,qpnp-vadc";
...
        chan@11 {               
                    label = "vbus_therm";    
                    reg = <0x11>;
                    qcom,decimation = <0>;
                    qcom,pre-div-channel-scaling = <0>;
                    qcom,calibration-type = "ratiometric";
                    qcom,scale-function = <11>;  
                    qcom,hw-settle-time = <2>;
                    qcom,fast-avg-setup = <0>;
                    qcom,vadc-thermal-node;
                };
...
}



// 4.3 哪边使用此vadc,及标明channel值
pmi8937_charger: qcom,qpnp-smbcharger {
    ...
            qcom,vbus_therm-vadc = <&pm8937_vadc>;      
            qcom,board_temp-vadc = <&pm8937_vadc>;
            qcom,usbchg_temp-channel-id = <17>;
            qcom,board_temp-channel-id = <19>;
    ....        
        }


// 4.4 .c文件中使用adc

// 根据名字获取对应的adc   ( qcom,vbus_therm-vadc    -  snprintf(prop_name, QPNP_MAX_PROP_NAME_LEN, "qcom,%s-vadc", name);)
if (of_find_property(spmi->dev.of_node, "qcom,vbus_therm-vadc", NULL)) 
    qpnp_get_vadc(&spmi->dev, "vbus_therm");   



// 4.5获取adc数据
static inline int32_t qpnp_vadc_read(struct qpnp_vadc_chip *dev,uint32_t channel,struct qpnp_vadc_result *result)

4.2 获取温度值方法二


/*

*/


pm8937_mpps: mpps {
            compatible = "qcom,qpnp-pin";


            mpp@a100 {
                /* MPP2 - PA_THERM config */
                reg = <0xa100 0x100>;
                qcom,pin-num = <2>;
                qcom,mode = <4>; /* AIN input */
                qcom,invert = <1>; /* Enable MPP */
                qcom,ain-route = <1>; /* AMUX 6 */
                qcom,master-en = <1>;
                qcom,src-sel = <0>; /* Function constant */
            };





pm8937_vadc: vadc@3100 {
            compatible = "qcom,qpnp-vadc";
            reg = <0x3100 0x100>;
            #address-cells = <1>;
            #size-cells = <0>;
            interrupts = <0x0 0x31 0x0>;
            interrupt-names = "eoc-int-en-set";
            qcom,adc-bit-resolution = <15>;
            qcom,adc-vdd-reference = <1800>;
            qcom,vadc-poll-eoc;


            chan@11 {
                label = "pa_therm1";
                reg = <0x11>;
                qcom,decimation = <0>;
                qcom,pre-div-channel-scaling = <0>;
                qcom,calibration-type = "ratiometric";
                qcom,scale-function = <2>;
                qcom,hw-settle-time = <2>;
                qcom,fast-avg-setup = <0>;
                qcom,vadc-thermal-node;
            };



    struct thermal_zone_device *usb_connector_device;
        long temperature;

        usb_connector_device = thermal_zone_get_zone_by_name("pa_therm1");
    ret = thermal_zone_get_temp(usb_connector_device, &temperature);


struct charger_manager->desc->thermal_zone   = "thermal name"

5. usb3.0

// drivers\usb\dwc3\dwc3-msm.c
usb3: ssusb@7000000{
        compatible = "qcom,dwc-usb3-msm";
}

6. otg

//drivers\usb\phy\phy-msm-usb.c

    usb_otg: usb@78db000 {
        compatible = "qcom,hsusb-otg";         


power_supply_set_usb_otg  //设置otg是否在线

POWER_SUPPLY_PROP_USB_OTG

7. lk 获取开机原因



pm8950_get_pon_reason

target_pause_for_battery_charge   // 判断是否为关机充电

8. charger led

&pmi8950_charger {
...
    qcom,chg-led-sw-controls; 
    qcom,chg-led-support;   // charger led 使用pmi芯片默认的 CHG_LED pin脚
  ..

}

            // qpnp-smbcharger.c
            static int smbchg_probe(struct spmi_device *spmi)
            {
            ....
                if (chip->cfg_chg_led_support &&chip->schg_version == QPNP_SCHG_LITE) {         
                        rc = smbchg_register_chg_led(chip);
                }
            ....
            }
  • 9
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值