void charging_algorithm_step(void) { #if IMX233_SUBTARGET >= 3780 bool is_5v_present = usb_detect() == USB_INSERTED; /* initial state & 5v -> battery transition */ if(!is_5v_present && charge_state != DISCHARGING) { logf("pwrmgmt: * -> discharging"); logf("pwrmgmt: disable charger and 4p2"); /* 5V has been lost: disable 4p2 power rail */ BF_SET(POWER_CHARGE, PWD_BATTCHRG); BF_WR(POWER_DCDC4P2, ENABLE_DCDC, 0); BF_WR(POWER_DCDC4P2, ENABLE_4P2, 0); BF_SET(POWER_5VCTRL, PWD_CHARGE_4P2); charge_state = DISCHARGING; } /* battery -> 5v transition */ else if(is_5v_present && charge_state == DISCHARGING) { logf("pwrmgmt: discharging -> trickle"); logf("pwrmgmt: begin charging 4p2"); /* 5V has been detected: prepare 4.2V power rail for activation */ BF_WR(POWER_DCDC4P2, ENABLE_4P2, 1); BF_SET(POWER_CHARGE, ENABLE_LOAD); BF_WR(POWER_5VCTRL, CHARGE_4P2_ILIMIT, 1); BF_CLR(POWER_5VCTRL, PWD_CHARGE_4P2);// FIXME: manual error ? BF_WR(POWER_DCDC4P2, ENABLE_DCDC, 1); timeout_4p2_ilimit_increase = current_tick + HZ / 100; charge_state = TRICKLE; } else if(charge_state == TRICKLE && TIME_AFTER(current_tick, timeout_4p2_ilimit_increase)) { /* if 4.2V current limit has not reached 780mA, increase it slowly to * charge the 4.2V capacitance */ if(BF_RD(POWER_5VCTRL, CHARGE_4P2_ILIMIT) != 0x3f) { //logf("pwrmgmt: incr 4.2 ilimit"); HW_POWER_5VCTRL += BF_POWER_5VCTRL_CHARGE_4P2_ILIMIT(1); timeout_4p2_ilimit_increase = current_tick + HZ / 100; } /* we've reached the maximum, take action */ else { logf("pwrmgmt: enable dcdc and charger"); logf("pwrmgmt: trickle -> charging"); BF_CLR(POWER_5VCTRL, DCDC_XFER); BF_SET(POWER_5VCTRL, ENABLE_DCDC); /* enable battery charging */ BF_CLR(POWER_CHARGE, PWD_BATTCHRG); charge_state = CHARGING; timeout_charging = current_tick + IMX233_CHARGING_TIMEOUT; } } else if(charge_state == CHARGING && TIME_AFTER(current_tick, timeout_charging)) { /* we have charged for a too long time, declare charger broken */ logf("pwrmgmt: charging timeout exceeded!"); logf("pwrmgmt: charging -> error"); /* stop charging */ BF_SET(POWER_5VCTRL, PWD_CHARGE_4P2); /* goto error state */ charge_state = CHARGE_STATE_ERROR; } else if(charge_state == CHARGING && !BF_RD(POWER_STS, CHRGSTS)) { logf("pwrmgmt: topping off"); logf("pwrmgmt: charging -> topoff"); charge_state = TOPOFF; timeout_topping_off = current_tick + IMX233_TOPOFF_TIMEOUT; } else if(charge_state == TOPOFF && TIME_AFTER(current_tick, timeout_topping_off)) { logf("pwrmgmt: charging finished"); logf("pwrmgmt: topoff -> disabled"); /* stop charging */ BF_SET(POWER_CHARGE, PWD_BATTCHRG); charge_state = CHARGE_STATE_DISABLED; } #endif }
static void ramp_up_4p2_rail(void) { /* only ramp up in the TRICKLE state and if we haven't reached the maximum yet */ if(charge_state == TRICKLE && BF_RD(POWER_5VCTRL, CHARGE_4P2_ILIMIT) < MAX_4P2_ILIMIT) HW_POWER_5VCTRL += BF_POWER_5VCTRL_CHARGE_4P2_ILIMIT(1); }