static irqreturn_t stmp_appuart_irq_rx(int irq, void *context) { struct stmp_appuart_port *s = context; int count = -1; stmp3xxx_dma_clear_interrupt(s->dma_rx); dev_dbg(s->dev, "%s(%d), count = %d\n", __func__, irq, count); #ifndef RX_CHAIN stmp_appuart_rx(s, s->rx_desc.virtual_buf_ptr, count); stmp_appuart_submit_rx(s); #else if (circ_advance_cooked(&s->rx_chain) == 0) { BUG(); return IRQ_HANDLED; } circ_advance_active(&s->rx_chain, 1); while (s->rx_chain.cooked_count) { stmp_appuart_rx(s, stmp3xxx_dma_circ_get_cooked_head(&s->rx_chain)-> virtual_buf_ptr, -1); circ_advance_free(&s->rx_chain, 1); } #endif return IRQ_HANDLED; }
/** * queue_run - run the chain * * @priv: private data. */ int queue_run(void *priv) { struct gpmi_perchip_data *g = priv; if (!g->d_tail) return 0; stmp3xxx_dma_reset_channel(g->dma_ch); stmp3xxx_dma_clear_interrupt(g->dma_ch); stmp3xxx_dma_enable_interrupt(g->dma_ch); g->d[g->d_tail-1].command->cmd &= ~(BM_APBH_CHn_CMD_NANDLOCK | BM_APBH_CHn_CMD_CHAIN); g->d[g->d_tail-1].command->cmd |= BM_APBH_CHn_CMD_IRQONCMPLT ; g->d[g->d_tail-1].command->pio_words[0] &= ~BM_GPMI_CTRL0_LOCK_CS; #ifdef DEBUG /*stmp37cc_dma_print_chain(&g->chain);*/ #endif init_completion(&g->done); stmp3xxx_dma_go(g->dma_ch, g->d, 1); wait_for_completion(&g->done); g->d_tail = 0; return 0; }
/* Allocate and initialise the DMA chains */ static int stmp3xxx_mmc_dma_init(struct stmp3xxx_mmc_host *host, int reset) { int ret; if (!reset) { /* Allocate DMA channel */ ret = stmp3xxx_dma_request(host->dmach, host->dev, "STMP37XX MMC/SD"); if (ret) { dev_err(host->dev, "Unable to request DMA channel\n"); return ret; } host->dma_buf = dma_alloc_coherent(host->dev, SSP_BUFFER_SIZE, &host->dma_buf_phys, GFP_DMA); if (host->dma_buf == NULL) { dev_err(host->dev, "Unable to allocate DMA memory\n"); ret = -ENOMEM; goto out_mem; } ret = stmp3xxx_dma_allocate_command(host->dmach, &host->dma_desc); if (ret) { dev_err(host->dev, "Unable to allocate DMA descriptor\n"); goto out_cmd; } host->dma_desc.command->next = (u32) host->dma_desc.handle; host->dma_desc.command->buf_ptr = (u32) host->dma_buf_phys; host->dma_desc.virtual_buf_ptr = host->dma_buf; } /* Reset DMA channel */ stmp3xxx_dma_reset_channel(host->dmach); /* Enable DMA interrupt */ stmp3xxx_dma_clear_interrupt(host->dmach); stmp3xxx_dma_enable_interrupt(host->dmach); return 0; out_cmd: dma_free_coherent(host->dev, SSP_BUFFER_SIZE, host->dma_buf, host->dma_buf_phys); out_mem: stmp3xxx_dma_release(host->dmach); return ret; }
/** * gpmi_irq - IRQ handler * * @irq: irq no * @context: IRQ context, pointer to gpmi_nand_data */ static irqreturn_t gpmi_irq(int irq, void *context) { struct lba_data *data = context; int i; for (i = 0; i < max_chips; i++) { if (stmp3xxx_dma_is_interrupt(data->nand[i].dma_ch)) { stmp3xxx_dma_clear_interrupt(data->nand[i].dma_ch); complete(&data->nand[i].done); } } HW_GPMI_CTRL1_CLR(BM_GPMI_CTRL1_DEV_IRQ | BM_GPMI_CTRL1_TIMEOUT_IRQ); return IRQ_HANDLED; }
static irqreturn_t stmp_appuart_irq_tx(int irq, void *context) { struct stmp_appuart_port *s = context; struct uart_port *u = &s->port; int bytes; stmp3xxx_dma_clear_interrupt(s->dma_tx); dev_dbg(s->dev, "%s(%d)\n", __func__, irq); bytes = stmp_appuart_copy_tx(u, s->tx_desc.virtual_buf_ptr, TX_BUFFER_SIZE); if (bytes > 0) { dev_dbg(s->dev, "Sending %d bytes\n", bytes); stmp_appuart_submit_tx(s, bytes); } return IRQ_HANDLED; }
/* SSP DMA interrupt handler */ static irqreturn_t mmc_irq_handler(int irq, void *dev_id) { struct stmp3xxx_mmc_host *host = dev_id; u32 c1; c1 = __raw_readl(host->ssp_base + HW_SSP_CTRL1); __raw_writel(c1 & STMP3XXX_MMC_IRQ_BITS, host->ssp_base + HW_SSP_CTRL1_CLR); if (irq == host->dmairq) stmp3xxx_dma_clear_interrupt(host->dmach); host->status = __raw_readl(host->ssp_base + HW_SSP_STATUS); if (host->cmd) /* else it is a bogus interrupt */ complete(&host->dma_done); return IRQ_HANDLED; }
int stmp3xxx_lcdif_dma_init(struct device *dev, dma_addr_t phys, int memsize, int lcd_master) { int ret = 0; stmp378x_lcd_master = lcd_master; if (lcd_master) { stmp3xxx_setl(BM_LCDIF_CTRL_LCDIF_MASTER, REGS_LCDIF_BASE + HW_LCDIF_CTRL); __raw_writel(phys, REGS_LCDIF_BASE + HW_LCDIF_CUR_BUF); __raw_writel(phys, REGS_LCDIF_BASE + HW_LCDIF_NEXT_BUF); } else { ret = stmp3xxx_dma_request(STMP3XXX_DMA (LCD_DMA_CHANNEL, STMP3XXX_BUS_APBH), dev, "lcdif"); if (ret) { dev_err(dev, "stmp3xxx_dma_request failed: error %d\n", ret); goto out; } stmp3xxx_dma_reset_channel(STMP3XXX_DMA (LCD_DMA_CHANNEL, STMP3XXX_BUS_APBH)); stmp3xxx_dma_clear_interrupt(STMP3XXX_DMA (LCD_DMA_CHANNEL, STMP3XXX_BUS_APBH)); stmp3xxx_dma_enable_interrupt(STMP3XXX_DMA (LCD_DMA_CHANNEL, STMP3XXX_BUS_APBH)); dotclk_dma_chain_init(memsize, phys, video_dma_descriptor, dma_chain_info, &dma_chain_info_pos); } out: return ret; }