/* Send the BC command to the device */ static void stmp3xxx_mmc_bc(struct stmp3xxx_mmc_host *host) { struct mmc_command *cmd = host->cmd; struct stmp3xxx_dma_descriptor *dma_desc = &host->dma_desc; dma_desc->command->cmd = BM_APBH_CHn_CMD_WAIT4ENDCMD | BM_APBH_CHn_CMD_SEMAPHORE | BM_APBH_CHn_CMD_IRQONCMPLT | BF(0, APBH_CHn_CMD_XFER_COUNT) | BF(3, APBH_CHn_CMD_CMDWORDS) | BF(0, APBH_CHn_CMD_COMMAND); /* NO_DMA_XFER */ dma_desc->command->pio_words[0] = BM_SSP_CTRL0_ENABLE | BM_SSP_CTRL0_IGNORE_CRC; dma_desc->command->pio_words[1] = BF(cmd->opcode, SSP_CMD0_CMD) | BM_SSP_CMD0_APPEND_8CYC; dma_desc->command->pio_words[2] = BF(cmd->arg, SSP_CMD1_CMD_ARG); init_completion(&host->dma_done); stmp3xxx_dma_reset_channel(host->dmach); stmp3xxx_dma_go(host->dmach, dma_desc, 1); wait_for_completion(&host->dma_done); cmd->error = stmp3xxx_mmc_cmd_error(host->status); if (stmp3xxx_dma_running(host->dmach)) dev_dbg(host->dev, "DMA command not finished\n"); if (cmd->error) { dev_dbg(host->dev, "Command error 0x%x\n", cmd->error); stmp3xxx_dma_reset_channel(host->dmach); } }
static int stmp_appuart_startup(struct uart_port *u) { struct stmp_appuart_port *s = to_appuart(u); int err; dev_dbg(s->dev, "%s\n", __func__); s->tx_buffer_index = 0; err = stmp_appuart_request_irqs(s); if (err) goto out; if (!s->keep_irq) /* Release the block from reset and start the clocks. */ stmp3xxx_reset_block(s->mem, 0); HW_UARTAPP_CTRL2_SET_NB(s->mem, BM_UARTAPP_CTRL2_UARTEN); /* Enable the Application UART DMA bits. */ if (!pio_mode) { HW_UARTAPP_CTRL2_SET_NB(s->mem, BM_UARTAPP_CTRL2_TXDMAE | BM_UARTAPP_CTRL2_RXDMAE | BM_UARTAPP_CTRL2_DMAONERR); /* clear any pending interrupts */ HW_UARTAPP_INTR_WR_NB(s->mem, 0); /* reset all dma channels */ stmp3xxx_dma_reset_channel(s->dma_tx); stmp3xxx_dma_reset_channel(s->dma_rx); } else { HW_UARTAPP_INTR_WR_NB(s->mem, BM_UARTAPP_INTR_RXIEN | BM_UARTAPP_INTR_RTIEN); } HW_UARTAPP_INTR_SET_NB(s->mem, BM_UARTAPP_INTR_CTSMIEN); /* * Enable fifo so all four bytes of a DMA word are written to * output (otherwise, only the LSB is written, ie. 1 in 4 bytes) */ HW_UARTAPP_LINECTRL_SET_NB(s->mem, BM_UARTAPP_LINECTRL_FEN); if (!pio_mode) { #ifndef RX_CHAIN stmp_appuart_submit_rx(s); #else circ_clear_chain(&s->rx_chain); stmp3xxx_dma_go(s->dma_rx, &s->rxd[0], 0); circ_advance_active(&s->rx_chain, 1); #endif } else { init_timer(&timer_task); timer_task.function = stmp_appuart_check_rx; timer_task.expires = jiffies + HZ; timer_task.data = (unsigned long)s; add_timer(&timer_task); } out: return err; }
/** * 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; }
static inline void stmp_appuart_submit_rx(struct stmp_appuart_port *s) { #ifndef RX_CHAIN struct stmp3xxx_dma_descriptor *r = &s->rx_desc; dev_dbg(s->dev, "Submitting RX DMA request\n"); r->command->cmd = BM_APBX_CHn_CMD_HALTONTERMINATE | 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 | BF_APBX_CHn_CMD_COMMAND( BV_APBX_CHn_CMD_COMMAND__DMA_WRITE); r->command->pio_words[0] = HW_UARTAPP_CTRL0_RD() | BF_UARTAPP_CTRL0_XFER_COUNT(RX_BUFFER_SIZE)| BM_UARTAPP_CTRL0_RXTO_ENABLE | BF_UARTAPP_CTRL0_RXTIMEOUT(3); r->command->pio_words[0] &= ~BM_UARTAPP_CTRL0_RUN; stmp3xxx_dma_reset_channel(s->dma_rx); stmp3xxx_dma_go(s->dma_rx, r, 1); #endif }
static void stmp_appuart_shutdown(struct uart_port *u) { struct stmp_appuart_port *s = to_appuart(u); dev_dbg(s->dev, "%s\n", __func__); if (!s->keep_irq) /* set the IP block to RESET; this should disable clock too. */ HW_UARTAPP_CTRL0_SET_NB(s->mem, BM_UARTAPP_CTRL0_SFTRST); if (!pio_mode) { /* reset all dma channels */ stmp3xxx_dma_reset_channel(s->dma_tx); stmp3xxx_dma_reset_channel(s->dma_rx); } else { del_timer(&timer_task); } stmp_appuart_free_irqs(s); }
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); }
static void stmp_appuart_on(struct platform_device *dev) { struct stmp_appuart_port *s = platform_get_drvdata(dev); if (!pio_mode) { /* Tell DMA to select UART. Both DMA channels are shared between app UART and IrDA. Target id of 0 means UART, 1 means IrDA */ stmp3xxx_dma_set_alt_target(s->dma_rx, 0); stmp3xxx_dma_set_alt_target(s->dma_tx, 0); /* Reset DMA channels */ stmp3xxx_dma_reset_channel(s->dma_rx); stmp3xxx_dma_reset_channel(s->dma_tx); stmp3xxx_dma_enable_interrupt(s->dma_rx); stmp3xxx_dma_enable_interrupt(s->dma_tx); } }
/* 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; }
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; }
/* Send adtc command to the card */ static void stmp3xxx_mmc_adtc(struct stmp3xxx_mmc_host *host) { struct mmc_command *cmd = host->cmd; struct stmp3xxx_dma_descriptor *dma_desc = &host->dma_desc; int ignore_crc, resp, long_resp; int is_reading = 0; unsigned int copy_size; u32 ssp_ctrl0; u32 ssp_cmd0; u32 ssp_cmd1; u32 timeout; u32 val; u32 data_size = cmd->data->blksz * cmd->data->blocks; u32 log2_block_size; ignore_crc = mmc_resp_type(cmd) & MMC_RSP_CRC ? 0 : 1; resp = mmc_resp_type(cmd) & MMC_RSP_PRESENT ? 1 : 0; long_resp = mmc_resp_type(cmd) & MMC_RSP_136 ? 1 : 0; dev_dbg(host->dev, "ADTC command:\n" "response: %d, ignore crc: %d\n" "data list: %u, blocksz: %u, blocks: %u, timeout: %uns %uclks, " "flags: 0x%x\n", resp, ignore_crc, cmd->data->sg_len, cmd->data->blksz, cmd->data->blocks, cmd->data->timeout_ns, cmd->data->timeout_clks, cmd->data->flags); if (cmd->data->flags & MMC_DATA_WRITE) { dev_dbg(host->dev, "Data Write\n"); copy_size = stmp3xxx_sg_dma_copy(host, data_size, 1); BUG_ON(copy_size < data_size); is_reading = 0; if (!host->regulator) __init_reg(host->dev, &host->regulator); if (host->regulator) regulator_set_current_limit(host->regulator, host->write_uA, host->write_uA); } else if (cmd->data->flags & MMC_DATA_READ) { dev_dbg(host->dev, "Data Read\n"); is_reading = 1; if (!host->regulator) __init_reg(host->dev, &host->regulator); if (host->regulator) regulator_set_current_limit(host->regulator, host->read_uA, host->read_uA); } else { dev_warn(host->dev, "Unsuspported data mode, 0x%x\n", cmd->data->flags); BUG(); } BUG_ON(cmd->data->flags & MMC_DATA_STREAM); BUG_ON((data_size % 8) > 0); dma_desc->command->cmd = BM_APBH_CHn_CMD_WAIT4ENDCMD | BM_APBH_CHn_CMD_SEMAPHORE | BM_APBH_CHn_CMD_IRQONCMPLT | BF(data_size, APBH_CHn_CMD_XFER_COUNT) | BF(3, APBH_CHn_CMD_CMDWORDS); /* when is_reading is set, DMA controller performs WRITE operation. */ dma_desc->command->cmd |= BF(is_reading ? BV_APBH_CHn_CMD_COMMAND__DMA_WRITE : BV_APBH_CHn_CMD_COMMAND__DMA_READ, APBH_CHn_CMD_COMMAND); ssp_ctrl0 = (ignore_crc ? BM_SSP_CTRL0_IGNORE_CRC : 0) | (resp ? BM_SSP_CTRL0_GET_RESP : 0) | (long_resp ? BM_SSP_CTRL0_LONG_RESP : 0) | (is_reading ? BM_SSP_CTRL0_READ : 0) | BM_SSP_CTRL0_DATA_XFER | BM_SSP_CTRL0_WAIT_FOR_IRQ | BM_SSP_CTRL0_ENABLE | BF(data_size, SSP_CTRL0_XFER_COUNT) | BF(host->bus_width_4 ? BV_SSP_CTRL0_BUS_WIDTH__FOUR_BIT : BV_SSP_CTRL0_BUS_WIDTH__ONE_BIT, SSP_CTRL0_BUS_WIDTH); /* * We need to set the hardware register to the logarithm to base 2 of * the block size. */ log2_block_size = ilog2(cmd->data->blksz); ssp_cmd0 = BF(log2_block_size, SSP_CMD0_BLOCK_SIZE) | BF(cmd->opcode, SSP_CMD0_CMD) | BF(cmd->data->blocks - 1, SSP_CMD0_BLOCK_COUNT); if (cmd->opcode == 12) ssp_cmd0 |= BM_SSP_CMD0_APPEND_8CYC; ssp_cmd1 = BF(cmd->arg, SSP_CMD1_CMD_ARG); dma_desc->command->pio_words[0] = ssp_ctrl0; dma_desc->command->pio_words[1] = ssp_cmd0; dma_desc->command->pio_words[2] = ssp_cmd1; /* Set the timeout count */ timeout = stmp3xxx_ns_to_ssp_ticks(host->clkrt, cmd->data->timeout_ns); val = __raw_readl(host->ssp_base + HW_SSP_TIMING); val &= ~(BM_SSP_TIMING_TIMEOUT); val |= BF(timeout, SSP_TIMING_TIMEOUT); __raw_writel(val, host->ssp_base + HW_SSP_TIMING); init_completion(&host->dma_done); stmp3xxx_dma_reset_channel(host->dmach); stmp3xxx_dma_go(host->dmach, dma_desc, 1); wait_for_completion(&host->dma_done); if (host->regulator) regulator_set_current_limit(host->regulator, 0, 0); switch (mmc_resp_type(cmd)) { case MMC_RSP_NONE: break; case MMC_RSP_R1: case MMC_RSP_R3: cmd->resp[0] = __raw_readl(host->ssp_base + HW_SSP_SDRESP0); break; case MMC_RSP_R2: cmd->resp[3] = __raw_readl(host->ssp_base + HW_SSP_SDRESP0); cmd->resp[2] = __raw_readl(host->ssp_base + HW_SSP_SDRESP1); cmd->resp[1] = __raw_readl(host->ssp_base + HW_SSP_SDRESP2); cmd->resp[0] = __raw_readl(host->ssp_base + HW_SSP_SDRESP3); break; default: dev_warn(host->dev, "Unsupported response type 0x%x\n", mmc_resp_type(cmd)); BUG(); break; } cmd->error = stmp3xxx_mmc_cmd_error(host->status); if (stmp3xxx_dma_running(host->dmach)) dev_dbg(host->dev, "DMA command not finished\n"); if (cmd->error) { dev_dbg(host->dev, "Command error 0x%x\n", cmd->error); stmp3xxx_dma_reset_channel(host->dmach); } else { if (is_reading) cmd->data->bytes_xfered = stmp3xxx_sg_dma_copy(host, data_size, 0); else cmd->data->bytes_xfered = data_size; dev_dbg(host->dev, "Transferred %u bytes\n", cmd->data->bytes_xfered); } }
/* Send the ac command to the device */ static void stmp3xxx_mmc_ac(struct stmp3xxx_mmc_host *host) { struct mmc_command *cmd = host->cmd; struct stmp3xxx_dma_descriptor *dma_desc = &host->dma_desc; u32 ignore_crc, resp, long_resp; u32 ssp_ctrl0; u32 ssp_cmd0; u32 ssp_cmd1; ignore_crc = (mmc_resp_type(cmd) & MMC_RSP_CRC) ? 0 : BM_SSP_CTRL0_IGNORE_CRC; resp = (mmc_resp_type(cmd) & MMC_RSP_PRESENT) ? BM_SSP_CTRL0_GET_RESP : 0; long_resp = (mmc_resp_type(cmd) & MMC_RSP_136) ? BM_SSP_CTRL0_LONG_RESP : 0; dma_desc->command->cmd = BM_APBH_CHn_CMD_WAIT4ENDCMD | BM_APBH_CHn_CMD_SEMAPHORE | BM_APBH_CHn_CMD_IRQONCMPLT | BF(0, APBH_CHn_CMD_XFER_COUNT) | BF(3, APBH_CHn_CMD_CMDWORDS) | BF(0, APBH_CHn_CMD_COMMAND); ssp_ctrl0 = BM_SSP_CTRL0_ENABLE | ignore_crc | long_resp | resp; ssp_cmd0 = BF(cmd->opcode, SSP_CMD0_CMD); ssp_cmd1 = BF(cmd->arg, SSP_CMD1_CMD_ARG); dma_desc->command->pio_words[0] = ssp_ctrl0; dma_desc->command->pio_words[1] = ssp_cmd0; dma_desc->command->pio_words[2] = ssp_cmd1; stmp3xxx_dma_reset_channel(host->dmach); init_completion(&host->dma_done); stmp3xxx_dma_go(host->dmach, dma_desc, 1); wait_for_completion(&host->dma_done); switch (mmc_resp_type(cmd)) { case MMC_RSP_NONE: while (__raw_readl(host->ssp_base + HW_SSP_CTRL0) & BM_SSP_CTRL0_RUN) continue; break; case MMC_RSP_R1: case MMC_RSP_R1B: case MMC_RSP_R3: cmd->resp[0] = __raw_readl(host->ssp_base + HW_SSP_SDRESP0); break; case MMC_RSP_R2: cmd->resp[3] = __raw_readl(host->ssp_base + HW_SSP_SDRESP0); cmd->resp[2] = __raw_readl(host->ssp_base + HW_SSP_SDRESP1); cmd->resp[1] = __raw_readl(host->ssp_base + HW_SSP_SDRESP2); cmd->resp[0] = __raw_readl(host->ssp_base + HW_SSP_SDRESP3); break; default: dev_warn(host->dev, "Unsupported response type 0x%x\n", mmc_resp_type(cmd)); BUG(); break; } cmd->error = stmp3xxx_mmc_cmd_error(host->status); if (stmp3xxx_dma_running(host->dmach)) dev_dbg(host->dev, "DMA command not finished\n"); if (cmd->error) { dev_dbg(host->dev, "Command error 0x%x\n", cmd->error); stmp3xxx_dma_reset_channel(host->dmach); } }