/* * Circular dma chain management */ void stmp3xxx_dma_free_chain(struct stmp37xx_circ_dma_chain *chain) { int i; for (i = 0; i < chain->total_count; i++) stmp3xxx_dma_free_command( STMP3XXX_DMA(chain->channel, chain->bus), &chain->chain[i]); }
static void stmp3xxx_mmc_dma_release(struct stmp3xxx_mmc_host *host) { stmp3xxx_dma_reset_channel(host->dmach); dma_free_coherent(host->dev, SSP_BUFFER_SIZE, host->dma_buf, host->dma_buf_phys); stmp3xxx_dma_free_command(host->dmach, &host->dma_desc); stmp3xxx_dma_release(host->dmach); }
int stmp3xxx_dma_make_chain(int ch, struct stmp37xx_circ_dma_chain *chain, struct stmp3xxx_dma_descriptor descriptors[], unsigned items) { int i; int err = 0; if (items == 0) return err; for (i = 0; i < items; i++) { err = stmp3xxx_dma_allocate_command(ch, &descriptors[i]); if (err) { WARN_ON(err); /* * Couldn't allocate the whole chain. * deallocate what has been allocated */ if (i) { do { stmp3xxx_dma_free_command(ch, &descriptors [i]); } while (i-- > 0); } return err; } /* link them! */ if (i > 0) { descriptors[i - 1].next_descr = &descriptors[i]; descriptors[i - 1].command->next = descriptors[i].handle; } } /* make list circular */ descriptors[items - 1].next_descr = &descriptors[0]; descriptors[items - 1].command->next = descriptors[0].handle; chain->total_count = items; chain->chain = descriptors; chain->free_index = 0; chain->active_index = 0; chain->cooked_index = 0; chain->free_count = items; chain->active_count = 0; chain->cooked_count = 0; chain->bus = STMP3XXX_DMA_BUS(ch); chain->channel = STMP3XXX_DMA_CHANNEL(ch); return err; }
void stmp3xxx_lcdif_dma_release(void) { int i; if (stmp378x_lcd_master) { stmp3xxx_clearl(BM_LCDIF_CTRL_LCDIF_MASTER, REGS_LCDIF_BASE + HW_LCDIF_CTRL); return; } for (i = 0; i < dma_chain_info_pos; i++) stmp3xxx_dma_free_command(STMP3XXX_DMA (LCD_DMA_CHANNEL, STMP3XXX_BUS_APBH), &video_dma_descriptor[i]); stmp3xxx_dma_release(STMP3XXX_DMA(LCD_DMA_CHANNEL, STMP3XXX_BUS_APBH)); dma_chain_info_pos = 0; }
/* Allocate and initialize rx and tx DMA chains */ static inline int stmp_appuart_dma_init(struct stmp_appuart_port *s) { int err = 0; struct stmp3xxx_dma_descriptor *t = &s->tx_desc; #ifndef RX_CHAIN struct stmp3xxx_dma_descriptor *r = &s->rx_desc; #else int i; #endif err = stmp3xxx_dma_request(s->dma_rx, s->dev, s->dev->bus_id); if (err) goto out; err = stmp3xxx_dma_request(s->dma_tx, s->dev, s->dev->bus_id); if (err) goto out1; #ifndef RX_CHAIN err = stmp3xxx_dma_allocate_command(s->dma_rx, r); if (err) goto out2; #endif err = stmp3xxx_dma_allocate_command(s->dma_tx, t); if (err) goto out3; t->virtual_buf_ptr = dma_alloc_coherent(s->dev, TX_BUFFER_SIZE, &t->command->buf_ptr, GFP_DMA); if (!t->virtual_buf_ptr) goto out4; #ifdef DEBUG memset(t->virtual_buf_ptr, 0x4B, TX_BUFFER_SIZE); #endif #ifndef RX_CHAIN r->virtual_buf_ptr = dma_alloc_coherent(s->dev, RX_BUFFER_SIZE, &r->command->buf_ptr, GFP_DMA); if (!r->virtual_buf_ptr) goto out5; #ifdef DEBUG memset(r->virtual_buf_ptr, 0x4C, RX_BUFFER_SIZE); #endif #else stmp3xxx_dma_make_chain(s->dma_rx, &s->rx_chain, s->rxd, RX_CHAIN); for (i = 0; i < RX_CHAIN; i++) { struct stmp3xxx_dma_descriptor *r = s->rxd + i; r->command->cmd = BF_APBX_CHn_CMD_XFER_COUNT(RX_BUFFER_SIZE) | BF_APBX_CHn_CMD_CMDWORDS(1) | BM_APBX_CHn_CMD_WAIT4ENDCMD | BM_APBX_CHn_CMD_SEMAPHORE | BM_APBX_CHn_CMD_IRQONCMPLT | BM_APBX_CHn_CMD_CHAIN | BF_APBX_CHn_CMD_COMMAND( BV_APBX_CHn_CMD_COMMAND__DMA_WRITE); r->virtual_buf_ptr = dma_alloc_coherent(s->dev, RX_BUFFER_SIZE, &r->command->buf_ptr, GFP_DMA); r->command->pio_words[0] = /* BM_UARTAPP_CTRL0_RUN | */ BF_UARTAPP_CTRL0_XFER_COUNT(RX_BUFFER_SIZE)| BM_UARTAPP_CTRL0_RXTO_ENABLE | BF_UARTAPP_CTRL0_RXTIMEOUT(3); } #endif return 0; /* * would be necessary on other error paths dma_free_coherent( s->dev, RX_BUFFER_SIZE, r->virtual_buf_ptr, r->command->buf_ptr); */ out5: dma_free_coherent(s->dev, TX_BUFFER_SIZE, t->virtual_buf_ptr, t->command->buf_ptr); out4: stmp3xxx_dma_free_command(s->dma_tx, t); out3: #ifndef RX_CHAIN stmp3xxx_dma_free_command(s->dma_rx, r); #endif out2: stmp3xxx_dma_release(s->dma_tx); out1: stmp3xxx_dma_release(s->dma_rx); out: WARN_ON(err); return err; }