/* 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); } }
void stmp37xx_circ_clear_chain(struct stmp37xx_circ_dma_chain *chain) { BUG_ON(stmp3xxx_dma_running(STMP3XXX_DMA(chain->channel, chain->bus))); chain->free_index = 0; chain->active_index = 0; chain->cooked_index = 0; chain->free_count = chain->total_count; chain->active_count = 0; chain->cooked_count = 0; }
static unsigned int stmp_appuart_tx_empty(struct uart_port *u) { struct stmp_appuart_port *s = to_appuart(u); if (pio_mode) if (HW_UARTAPP_STAT_RD_NB(s->mem) & BM_UARTAPP_STAT_TXFE) return TIOCSER_TEMT; else return 0; else return stmp3xxx_dma_running(s->dma_tx) ? 0: TIOCSER_TEMT; }
static void stmp_appuart_start_tx(struct uart_port *u) { struct stmp_appuart_port *s = to_appuart(u); int bytes; dev_dbg(s->dev, "%s\n", __func__); /* enable transmitter */ HW_UARTAPP_CTRL2_SET_NB(s->mem, BM_UARTAPP_CTRL2_TXE); if (!pio_mode) { if (stmp3xxx_dma_running(s->dma_tx)) return; bytes = stmp_appuart_copy_tx(u, s->tx_desc.virtual_buf_ptr, TX_BUFFER_SIZE); if (bytes <= 0) return; dev_dbg(s->dev, "Started DMA transfer with descriptor %p, " "command %p, %d bytes long\n", &s->tx_desc, s->tx_desc.command, bytes); stmp_appuart_submit_tx(s, bytes); } else { int count = 0; u8 c; while (!(HW_UARTAPP_STAT_RD_NB(s->mem) & BM_UARTAPP_STAT_TXFF)) { if (stmp_appuart_copy_tx(u, &c, 1) <= 0) break; dev_dbg(s->dev, "%d: '%c'/%x\n", ++count, chr(c), c); HW_UARTAPP_DATA_WR_NB(s->mem, c); } } }
/* 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); } }