/* 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);
	}
}