Beispiel #1
0
struct imx233_dcp_info_t imx233_dcp_get_info(unsigned flags)
{
    struct imx233_dcp_info_t info;
    memset(&info, 0, sizeof(info));
    if(flags & DCP_INFO_CAPABILITIES)
    {
        info.has_crypto = HW_DCP_CTRL & HW_DCP_CTRL__PRESENT_CRYPTO;
        info.has_csc = HW_DCP_CTRL & HW_DCP_CTRL__PRESENT_CSC;
        info.num_keys = __XTRACT(HW_DCP_CAPABILITY0, NUM_KEYS);
        info.num_channels = __XTRACT(HW_DCP_CAPABILITY0, NUM_CHANNELS);
        info.ciphers = __XTRACT(HW_DCP_CAPABILITY1, CIPHER_ALGORITHMS);
        info.hashs = __XTRACT(HW_DCP_CAPABILITY1, HASH_ALGORITHMS);
    }
    if(flags & DCP_INFO_GLOBAL_STATE)
    {
        info.otp_key_ready = HW_DCP_STAT & HW_DCP_STAT__OTP_KEY_READY;
        info.context_switching = HW_DCP_CTRL & HW_DCP_CTRL__ENABLE_CONTEXT_SWITCHING;
        info.context_caching = HW_DCP_CTRL & HW_DCP_CTRL__ENABLE_CONTEXT_CACHING;
        info.gather_writes = HW_DCP_CTRL & HW_DCP_CTRL__GATHER_RESIDUAL_WRITES;
        info.ch0_merged = HW_DCP_CHANNELCTRL & HW_DCP_CHANNELCTRL__CH0_IRQ_MERGED;
    }
    if(flags & DCP_INFO_CHANNELS)
    {
        for(int i = 0; i < HW_DCP_NUM_CHANNELS; i++)
        {
            info.channel[i].irq_en = HW_DCP_CTRL & HW_DCP_CTRL__CHANNEL_INTERRUPT_ENABLE(i);
            info.channel[i].irq = HW_DCP_STAT & HW_DCP_STAT__IRQ(i);
            info.channel[i].ready = HW_DCP_STAT & HW_DCP_STAT__READY_CHANNELS(i);
            info.channel[i].high_priority = HW_DCP_CHANNELCTRL & HW_DCP_CHANNELCTRL__HIGH_PRIORITY_CHANNEL(i);
            info.channel[i].enable = HW_DCP_CHANNELCTRL & HW_DCP_CHANNELCTRL__ENABLE_CHANNEL(i);
            info.channel[i].sema = __XTRACT_EX(HW_DCP_CHxSEMA(i), HW_DCP_CHxSEMA__VALUE);
            info.channel[i].cmdptr = HW_DCP_CHxCMDPTR(i);
            info.channel[i].acquired = arbiter_acquired(&channel_arbiter, i);
        }
    }
    if(flags & DCP_INFO_CSC)
    {
        info.csc.irq_en = HW_DCP_CTRL & HW_DCP_CTRL__CSC_INTERRUPT_ENABLE;
        info.csc.irq = HW_DCP_STAT & HW_DCP_STAT__CSCIRQ;
        info.csc.priority = __XTRACT(HW_DCP_CHANNELCTRL, CSC_PRIORITY);
        info.csc.enable = HW_DCP_CSCCTRL0 & HW_DCP_CSCCTRL0__ENABLE;
    }
    return info;
}
Beispiel #2
0
void imx233_dcp_init(void)
{
    /* Reset block */
    imx233_reset_block(&HW_DCP_CTRL);
    /* Setup contexte pointer */
    HW_DCP_CONTEXT = (uint32_t)PHYSICAL_ADDR(&dcp_context);
    /* Enable context switching and caching */
    __REG_SET(HW_DCP_CTRL) = HW_DCP_CTRL__ENABLE_CONTEXT_CACHING |
        HW_DCP_CTRL__ENABLE_CONTEXT_SWITCHING;
    /* Check that there are sufficiently many channels */
    if(__XTRACT(HW_DCP_CAPABILITY0, NUM_CHANNELS) != HW_DCP_NUM_CHANNELS)
        panicf("DCP has %lu channels but was configured to use %d !",
               __XTRACT(HW_DCP_CAPABILITY0, NUM_CHANNELS), HW_DCP_NUM_CHANNELS);
    /* Setup channel arbiter to use */
    arbiter_init(&channel_arbiter, HW_DCP_NUM_CHANNELS);
    /* Merge channel0 interrupt */
    __REG_SET(HW_DCP_CHANNELCTRL) = HW_DCP_CHANNELCTRL__CH0_IRQ_MERGED;
    /* setup semaphores */
    for(int i = 0; i< HW_DCP_NUM_CHANNELS; i++)
        semaphore_init(&channel_sema[i], 1, 0);
}
Beispiel #3
0
unsigned imx233_lcdif_enable_irqs(unsigned irq_bm)
{
    unsigned old_msk = __XTRACT(HW_LCDIF_CTRL1, IRQ_EN);
    /* clear irq status */
    __REG_CLR(HW_LCDIF_CTRL1) = irq_bm << HW_LCDIF_CTRL1__IRQ_BP;
    /* disable irqs */
    __REG_CLR(HW_LCDIF_CTRL1) = HW_LCDIF_CTRL1__IRQ_EN_BM;
    /* enable irqs */
    __REG_SET(HW_LCDIF_CTRL1) = irq_bm << HW_LCDIF_CTRL1__IRQ_EN_BP;

    return old_msk;
}
Beispiel #4
0
int imx233_lradc_read_battery_voltage(void)
{
    return __XTRACT(HW_LRADC_CONVERSION, SCALED_BATT_VOLTAGE);
}
Beispiel #5
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;
    }
}
Beispiel #6
0
/* Returns battery voltage from ADC [millivolts] */
int _battery_voltage(void)
{
    /* battery value is in 8mV LSB */
    return __XTRACT(HW_POWER_BATTMONITOR, BATT_VAL) * 8;
}