Пример #1
0
void power_init(void)
{
    /* setup vbusvalid parameters: set threshold to 4v and power up comparators */
    __REG_CLR(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__VBUSVALID_TRSH_BM;
    __REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__VBUSVALID_TRSH_4V |
        HW_POWER_5VCTRL__PWRUP_VBUS_CMPS;
    /* enable vbusvalid detection method for the dcdc (improves efficiency) */
    __REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__VBUSVALID_5VDETECT;
    /* clear vbusvalid irq and set correct polarity */
    __REG_CLR(HW_POWER_CTRL) = HW_POWER_CTRL__VBUSVALID_IRQ;
    if(HW_POWER_STS & HW_POWER_STS__VBUSVALID)
        __REG_CLR(HW_POWER_CTRL) = HW_POWER_CTRL__POLARITY_VBUSVALID;
    else
        __REG_SET(HW_POWER_CTRL) = HW_POWER_CTRL__POLARITY_VBUSVALID;
    __REG_SET(HW_POWER_CTRL) = HW_POWER_CTRL__ENIRQ_VBUS_VALID;
    imx233_icoll_enable_interrupt(INT_SRC_VDD5V, true);
    /* setup linear regulator offsets to 25 mV below to prevent contention between
     * linear regulators and DCDC */
    __FIELD_SET(HW_POWER_VDDDCTRL, LINREG_OFFSET, 2);
    __FIELD_SET(HW_POWER_VDDACTRL, LINREG_OFFSET, 2);
    __FIELD_SET(HW_POWER_VDDIOCTRL, LINREG_OFFSET, 2);
    /* enable a few bits controlling the DC-DC as recommended by Freescale */
    __REG_SET(HW_POWER_LOOPCTRL) = HW_POWER_LOOPCTRL__TOGGLE_DIF |
        HW_POWER_LOOPCTRL__EN_CM_HYST;
    __FIELD_SET(HW_POWER_LOOPCTRL, EN_RCSCALE, HW_POWER_LOOPCTRL__EN_RCSCALE__2X);
}
Пример #2
0
void charging_algorithm_step(void)
{
    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 */
        __REG_SET(HW_POWER_CHARGE) = HW_POWER_CHARGE__PWD_BATTCHRG;
        __REG_CLR(HW_POWER_DCDC4P2) = HW_POWER_DCDC4P2__ENABLE_DCDC |
                                      HW_POWER_DCDC4P2__ENABLE_4P2;
        __REG_SET(HW_POWER_5VCTRL) = HW_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 */
        __REG_SET(HW_POWER_DCDC4P2) = HW_POWER_DCDC4P2__ENABLE_4P2;
        __REG_SET(HW_POWER_CHARGE) = HW_POWER_CHARGE__ENABLE_LOAD;
        __FIELD_SET(HW_POWER_5VCTRL, CHARGE_4P2_ILIMIT, 1);
        __REG_CLR(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__PWD_CHARGE_4P2;// FIXME: manual error ?
        __REG_SET(HW_POWER_DCDC4P2) = HW_POWER_DCDC4P2__ENABLE_DCDC;
        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(__XTRACT(HW_POWER_5VCTRL, CHARGE_4P2_ILIMIT) != 0x3f)
        {
            //logf("pwrmgmt: incr 4.2 ilimit");
            HW_POWER_5VCTRL += 1 << HW_POWER_5VCTRL__CHARGE_4P2_ILIMIT_BP;
            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");
            /* adjust arbitration between 4.2 and battery */
            __FIELD_SET(HW_POWER_DCDC4P2, CMPTRIP, 0); /* 85% */
            __FIELD_SET(HW_POWER_DCDC4P2, DROPOUT_CTRL, 0xe); /* select greater, 200 mV drop */
            __REG_CLR(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__DCDC_XFER;
            __REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__ENABLE_DCDC;
            /* enable battery charging */
            __REG_CLR(HW_POWER_CHARGE) = HW_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 */
        __REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__PWD_CHARGE_4P2;
        /* goto error state */
        charge_state = CHARGE_STATE_ERROR;
    }
    else if(charge_state == CHARGING && !(HW_POWER_STS & HW_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 */
        __REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__PWD_CHARGE_4P2;
        charge_state = CHARGE_STATE_DISABLED;
    }
}