Exemplo n.º 1
0
/* Commit and/or discard all DMA descriptors and buffers pointed by them,
 * handle circular lists. At the same time, convert virtual pointers to
 * real ones */
static void dma_commit_and_discard(unsigned chan, struct apb_dma_command_t *cmd)
{
    /* We handle circular descriptors by using unused bits:
     * bits 8-11 are not used by the hardware so we first go through the whole
     * list and mark them all a special value at the same time we commit buffers
     * and then we go through the list another time to clear the mark and
     * commit the descriptors */
    struct apb_dma_command_t *cur = cmd;

    while((cur->cmd & HW_APB_CHx_CMD__UNUSED_BM) != HW_APB_CHx_CMD__UNUSED_MAGIC)
    {
        cur->cmd = (cur->cmd & ~HW_APB_CHx_CMD__UNUSED_BM) | HW_APB_CHx_CMD__UNUSED_MAGIC;
        int op = cur->cmd & HW_APB_CHx_CMD__COMMAND_BM;
        int sz = __XTRACT_EX(cur->cmd, HW_APB_CHx_CMD__XFER_COUNT);
        /* device > host: discard */
        if(op == HW_APB_CHx_CMD__COMMAND__WRITE)
            discard_dcache_range(cur->buffer, sz);
        /* host > device: commit and discard */
        else if(op == HW_APB_CHx_CMD__COMMAND__READ)
            commit_discard_dcache_range(cur->buffer, sz);
        if((uint32_t)cur->buffer % CACHEALIGN_SIZE)
            apb_nr_unaligned[chan]++;
        /* Virtual to physical buffer pointer conversion */
        cur->buffer = PHYSICAL_ADDR(cur->buffer);
        /* chain ? */
        if(cur->cmd & HW_APB_CHx_CMD__CHAIN)
            cur = cur->next;
        else
            break;
    }

    cur = cmd;
    while((cur->cmd & HW_APB_CHx_CMD__UNUSED_BM) != 0)
    {
        cur->cmd = cur->cmd & ~HW_APB_CHx_CMD__UNUSED_BM;
        int sz = __XTRACT_EX(cur->cmd, HW_APB_CHx_CMD__CMDWORDS) * sizeof(uint32_t);
        /* commit descriptor and discard descriptor */
        /* chain ? */
        if(cur->cmd & HW_APB_CHx_CMD__CHAIN)
        {
            struct apb_dma_command_t *next = cur->next;
            cur->next = PHYSICAL_ADDR(cur->next);
            commit_dcache_range(cur, sizeof(struct apb_dma_command_t) + sz);
            cur = next;
        }
        else
        {
            commit_dcache_range(cur, sizeof(struct apb_dma_command_t) + sz);
            break;
        }
    }
}
Exemplo n.º 2
0
static enum imx233_dcp_error_t imx233_dcp_job(int ch)
{
    /* if IRQs are not enabled, don't enable channel interrupt and do some polling */
    bool irq_enabled = irq_enabled();
    /* enable channel, clear interrupt, enable interrupt */
    imx233_icoll_enable_interrupt(INT_SRC_DCP, true);
    if(irq_enabled)
        __REG_SET(HW_DCP_CTRL) = HW_DCP_CTRL__CHANNEL_INTERRUPT_ENABLE(ch);
    __REG_CLR(HW_DCP_STAT) = HW_DCP_STAT__IRQ(ch);
    __REG_SET(HW_DCP_CHANNELCTRL) = HW_DCP_CHANNELCTRL__ENABLE_CHANNEL(ch);

    /* write back packet */
    commit_discard_dcache_range(&channel_packet[ch], sizeof(struct imx233_dcp_packet_t));
    /* write 1 to semaphore to run job */
    HW_DCP_CHxCMDPTR(ch) = (uint32_t)PHYSICAL_ADDR(&channel_packet[ch]);
    HW_DCP_CHxSEMA(ch) = 1;
    /* wait completion */
    if(irq_enabled)
        semaphore_wait(&channel_sema[ch], TIMEOUT_BLOCK);
    else
        while(__XTRACT_EX(HW_DCP_CHxSEMA(ch), HW_DCP_CHxSEMA__VALUE))
            udelay(10);
    /* disable channel and interrupt */
    __REG_CLR(HW_DCP_CTRL) = HW_DCP_CTRL__CHANNEL_INTERRUPT_ENABLE(ch);
    __REG_CLR(HW_DCP_CHANNELCTRL) = HW_DCP_CHANNELCTRL__ENABLE_CHANNEL(ch);
    /* read status */
    return get_error_status(ch);
}
Exemplo n.º 3
0
int lradc_read_channel(int channel)
{
    /* check the channel index */
    if ((channel < 0) || (channel > MAX_USER_LRADC)) {
        return -1;
    }
    return __XTRACT_EX(HW_LRADC_CHx(channel), HW_LRADC_CHx__VALUE);
}
Exemplo n.º 4
0
int dma_wait_completion(unsigned chan, unsigned tmo)
{
    tmo += current_tick;
    volatile uint32_t *sema;
    if(APB_IS_APBX_CHANNEL(chan))
        sema = &HW_APBX_CHx_SEMA(APB_GET_DMA_CHANNEL(chan));
    else
        sema = &HW_APBH_CHx_SEMA(APB_GET_DMA_CHANNEL(chan));

    while(*sema & HW_APB_CHx_SEMA__PHORE_BM && !TIME_AFTER(current_tick, tmo))
        udelay(10);
    return __XTRACT_EX(*sema, HW_APB_CHx_SEMA__PHORE);
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
static enum imx233_dcp_error_t get_error_status(int ch)
{
    uint32_t stat = channel_packet[ch].status;
    if(stat & HW_DCP_STATUS__ERROR_SETUP)
        return DCP_ERROR_SETUP;
    if(stat & HW_DCP_STATUS__ERROR_PACKET)
        return DCP_ERROR_PACKET;
    if(stat & HW_DCP_STATUS__ERROR_SRC)
        return DCP_ERROR_SRC;
    if(stat & HW_DCP_STATUS__ERROR_DST)
        return DCP_ERROR_DST;
    switch(__XTRACT_EX(stat, HW_DCP_STATUS__ERROR_CODE))
    {
        case 0: return DCP_SUCCESS;
        case 1: return DCP_ERROR_CHAIN_IS_0;
        case 2: return DCP_ERROR_NO_CHAIN;
        case 3: return DCP_ERROR_CONTEXT;
        case 4: return DCP_ERROR_PAYLOAD;
        case 5: return DCP_ERROR_MODE;
        default: return DCP_ERROR;
    }
}
Exemplo n.º 7
0
int imx233_lradc_read_channel(int channel)
{
    return __XTRACT_EX(HW_LRADC_CHx(channel), HW_LRADC_CHx__VALUE);
}