sprd_2721_charge.c 命名以 pmic 型號+charge 爲規則,實現平臺默認線性充電方案,文件將硬件實現和邏輯接口註冊放在同一個文件中。ios
static int sprdchg_2721_probe(struct platform_device *pdev) { struct sprd2721_device *sprd_2721 = NULL; struct sprd2721_platform_data *pdata = pdev->dev.platform_data; int ret = 0; struct power_supply *ret_ptr = NULL; struct power_supply_desc *charger_desc = NULL; printk("YGH:%s:start \n",__func__); reg_map = dev_get_regmap(pdev->dev.parent, NULL); if (!reg_map) { dev_err(&pdev->dev, "%s :NULL regmap for charge 2721\n", __func__); return -EINVAL; } sprd_2721 = devm_kzalloc(&pdev->dev, sizeof(*sprd_2721), GFP_KERNEL); if (!sprd_2721) return -ENOMEM; if (!pdata) //解析設備樹,在其中有一個gpio_chg_cv_state、chg-ovi-gpios //其中chg-cv-gpio,當vbat高於cccv時觸發(CCCV恆壓恆流充電) //其中chg-ovi-gpios,充電電壓較高時觸發 pdata = sprdchg_2721_parse_dt(&pdev->dev); if (IS_ERR_OR_NULL(pdata)) return PTR_ERR(pdata); g_pdata = pdata; sprd_2721->dev = &pdev->dev; platform_set_drvdata(pdev, sprd_2721); if (pdata->gpio_chg_cv_state) { ret = devm_gpio_request(&pdev->dev, pdata->gpio_chg_cv_state, "chg_cv_state"); if (ret) { dev_err(&pdev->dev, "failed to request gpio: %d\n", ret); return ret; } gpio_direction_input(pdata->gpio_chg_cv_state); pdata->irq_chg_cv_state = gpio_to_irq(pdata->gpio_chg_cv_state); irq_set_status_flags(pdata->irq_chg_cv_state, IRQ_NOAUTOEN); ret = devm_request_threaded_irq(&pdev->dev, pdata->irq_chg_cv_state, NULL, sprdchg_chg_cv_irq, IRQF_NO_SUSPEND | IRQF_ONESHOT, "sprdbat_chg_cv_state", sprd_2721); if (ret) { dev_err(&pdev->dev, "failed to request chg cv irq: %d\n", ret); return ret; } } if (pdata->gpio_vchg_ovi) { ret = devm_gpio_request(&pdev->dev, pdata->gpio_vchg_ovi, "vchg_ovi"); if (ret) { dev_err(&pdev->dev, "failed to request gpio: %d\n", ret); return ret; } gpio_direction_input(pdata->gpio_vchg_ovi); pdata->irq_vchg_ovi = gpio_to_irq(pdata->gpio_vchg_ovi); irq_set_status_flags(pdata->irq_vchg_ovi, IRQ_NOAUTOEN); ret = devm_request_threaded_irq(&pdev->dev, pdata->irq_vchg_ovi, NULL, sprdchg_vchg_ovi_irq, IRQF_NO_SUSPEND | IRQF_ONESHOT, "sprdbat_vchg_ovi", sprd_2721); if (ret) { dev_err(&pdev->dev, "failed to request chg ovi irq: %d\n", ret); return ret; } } //若是CONFIG_OTP_SPRD_PMIC_EFUSE這個選項有的話,就會調用,而後獲取cv的電壓值 sprdchg_cccv_cal_get(); //註冊回調函數 sprdbat_register_ext_ops(&sprd_2721_op); charger_desc = devm_kzalloc(&pdev->dev, sizeof(*charger_desc), GFP_KERNEL); if (charger_desc == NULL) { ret = -ENOMEM; sprd_2721 = NULL; return ret; } //註冊內部充電的power_supply sprd_2721->charger.desc = charger_desc; charger_desc->name = CHG_PSY_INNER; charger_desc->type = POWER_SUPPLY_TYPE_UNKNOWN; charger_desc->get_property = sprd2721_get_property; ret_ptr = power_supply_register(&pdev->dev, sprd_2721->charger.desc, NULL); if (IS_ERR(ret_ptr)) { dev_err(&pdev->dev, "failed to register sprd_2721 psy: %p\n", ret_ptr); return PTR_ERR(ret_ptr); } SPRDCHG_DEBUG("%s probe ok\n", __func__); printk("YGH:%s:end \n",__func__); return 0; }
其中來簡單介紹下sprd_2721_op的回調函數的:函數
static struct sprd_ext_ic_operations sprd_2720_op = { .ic_init = sprdchg_chip_init, .charge_start_ext = sprdchg_start_charge, .set_charge_cur = sprdchg_set_chg_cur, .charge_stop_ext = sprdchg_stop_charge, .get_charging_status = sprdchg_get_cccvstate, .get_charging_fault = sprdchg_get_charge_fault, .get_charge_cur_ext = sprdchg_get_chg_cur, .set_termina_vol_ext = sprdchg_termina_vol_set, };
其中sprdchg_chip_init函數是初始化充電芯片的:ui
static void sprdchg_chip_init(struct sprdbat_drivier_data *bdata) { if (bdata == NULL) return; bat_drv_data = bdata; glb_adi_write(ANA_REG_GLB_CHGR_CTRL0, BIT_CHGR_CC_EN, BIT_CHGR_CC_EN); chg_adi_write(ANA_REG_GLB_CHGR_CTRL0, BITS_CHGR_CV_V(0U), BITS_CHGR_CV_V(~0U)); chg_adi_write(ANA_REG_GLB_CHGR_CTRL0, BITS_CHGR_DPM(3), BITS_CHGR_DPM(~0U)); sprdchg_termina_vol_set(bat_drv_data->pdata->chg_end_vol_pure); sprdchg_set_chg_ovp(bat_drv_data->pdata->ovp_stop); sprdchg_set_eoc_level(0); }
static void sprdchg_start_charge(void) { chg_adi_write(ANA_REG_GLB_CHGR_CTRL0, 0, BIT_CHGR_PD); _sprdchg_set_recharge(); }
設置充電狀態,而且設置復充狀態位code
線性充電方案充電電流設置下限爲 300mA,電流上限爲 2300mA,300mA – 1400mA 設置最小步進單位爲 50mA,1400mA – 2300mA 設置最小步進單位爲 100mA。orm
static void sprdchg_set_chg_cur(uint32_t chg_current) { uint32_t temp; if (bat_drv_data == NULL) return; if (bat_drv_data->bat_info.chg_current_type_limit < chg_current) bat_drv_data->bat_info.chg_current_type_limit = chg_current; if (chg_current > SPRDBAT_CHG_CUR_LEVEL_MAX) chg_current = SPRDBAT_CHG_CUR_LEVEL_MAX; if (chg_current < SPRDBAT_CHG_CUR_LEVEL_MIN) chg_current = SPRDBAT_CHG_CUR_LEVEL_MIN; if (chg_current < 1400) { temp = ((chg_current - 300) / 50); } else { temp = ((chg_current - 1400) / 100); temp += 0x16; } chg_adi_write(ANA_REG_GLB_CHGR_CTRL0, 0, BIT_CHGR_CC_EN); chg_adi_write(ANA_REG_GLB_CHGR_CTRL1, BITS_CHGR_CC_I(temp), BITS_CHGR_CC_I(~0U)); chg_adi_write(ANA_REG_GLB_CHGR_CTRL0, BIT_CHGR_CC_EN, BIT_CHGR_CC_EN); }
開關充電充電電流須要根據使用的 IC 不一樣區分設置。接口
中止充電ip
static int sprdchg_get_cccvstate(void) { SPRDCHG_DEBUG("sprdbat:cv state:0x%x, iterm:0x%x", chg_adi_read(ANA_REG_GLB_CHGR_STATUS), chg_adi_read(ANA_REG_GLB_CHGR_CTRL0)); return ((chg_adi_read(ANA_REG_GLB_CHGR_STATUS) & BIT_CHGR_CV_STATUS) ? 1 : 0); }