展讯线性充电器

编程

平台默认 pmic 线性充电

sprd_2721_charge.c 命名以 pmic 型号+charge 为规则,实现平台默认线性充电方案,文件将硬件实现和逻辑接口注册放在同一个文件中。

probe函数:

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

",__func__);

reg_map = dev_get_regmap(pdev->dev.parent, NULL);

if (!reg_map) {

dev_err(&pdev->dev, "%s :NULL regmap for charge 2721

",

__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

", 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

", 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

", 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

", 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

",

ret_ptr);

return PTR_ERR(ret_ptr);

}

SPRDCHG_DEBUG("%s probe ok

", __func__);

printk("YGH:%s:end

",__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函数是初始化充电芯片的:

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);

}

sprdchg_start_charge函数:

static void sprdchg_start_charge(void)

{

chg_adi_write(ANA_REG_GLB_CHGR_CTRL0, 0, BIT_CHGR_PD);

_sprdchg_set_recharge();

}

设置充电状态,并且设置复充状态位

设置充电sprdchg_set_chg_cur电流:

线性充电方案充电电流设置下限为 300mA,电流上限为 2300mA,300mA – 1400mA 设置最小步进单位为 50mA,1400mA – 2300mA 设置最小步进单位为 100mA。

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 不同区分设置。

sprdchg_stop_charge函数

停止充电

sprdchg_get_cccvstate函数

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);

}

sprdchg_get_charge_fault是个空函数

sprdchg_set_cccvpoint暂且不清楚

sprdchg_get_chg_cur暂且不清楚

以上是 展讯线性充电器 的全部内容, 来源链接: utcz.com/z/513369.html

回到顶部