/**
 * hsi_driver_cancel_write_interrupt - Cancel pending write interrupt.
 * @dev - hsi device channel where to cancel the pending interrupt.
 *
 * Return: -ECANCELED : write cancel success, data not transfered to TX FIFO
 *	   0 : transfer is already over, data already transfered to TX FIFO
 *
 * Note: whatever returned value, write callback will not be called after
 *       write cancel.
 */
int hsi_driver_cancel_write_interrupt(struct hsi_channel *ch)
{
	struct hsi_port *p = ch->hsi_port;
	unsigned int port = p->port_number;
	unsigned int channel = ch->channel_number;
	void __iomem *base = p->hsi_controller->base;
	u32 status_reg;
	long buff_offset;

	status_reg = hsi_inl(base,
			 HSI_SYS_MPU_ENABLE_CH_REG(port, p->n_irq, channel));

	if (!(status_reg & HSI_HST_DATAACCEPT(channel))) {
		dev_dbg(&ch->dev->device, "Write cancel on not "
			"enabled channel %d ENABLE REG 0x%08X", channel,
			status_reg);
	}
	status_reg &= hsi_inl(base,
			HSI_SYS_MPU_STATUS_CH_REG(port, p->n_irq, channel));

	hsi_outl_and(~HSI_HST_DATAACCEPT(channel), base,
			HSI_SYS_MPU_ENABLE_CH_REG(port, p->n_irq, channel));

	buff_offset = hsi_hst_bufstate_f_reg(p->hsi_controller, port, channel);
	if (buff_offset >= 0)
		hsi_outl_and(~HSI_BUFSTATE_CHANNEL(channel), base, buff_offset);
	hsi_reset_ch_write(ch);
	return status_reg & HSI_HST_DATAACCEPT(channel) ? 0 : -ECANCELED;
}
Example #2
0
/**
 * hsi_driver_cancel_write_dma - Cancel an ongoing GDD [DMA] write for the
 *				specified hsi channel.
 * @hsi_ch - pointer to the hsi_channel to cancel DMA write.
 *
 * hsi_controller lock must be held before calling this function.
 *
 * Return: -ENXIO : No DMA channel found for specified HSI channel
 *	   -ECANCELED : DMA cancel success, data not transfered to TX FIFO
 *	   0 : DMA transfer is already over, data already transfered to TX FIFO
 *
 * Note: whatever returned value, write callback will not be called after
 *       write cancel.
 */
int hsi_driver_cancel_write_dma(struct hsi_channel *hsi_ch)
{
	int lch = hsi_ch->write_data.lch;
	unsigned int port = hsi_ch->hsi_port->port_number;
	unsigned int channel = hsi_ch->channel_number;
	struct hsi_dev *hsi_ctrl = hsi_ch->hsi_port->hsi_controller;
	u16 ccr, gdd_csr;
	long buff_offset;
	u32 status_reg;
	dma_addr_t dma_h;
	size_t size;

	if (lch < 0) {
		dev_err(&hsi_ch->dev->device, "No DMA channel found for HSI "
				"channel %d\n", hsi_ch->channel_number);
		return -ENXIO;
	}
	ccr = hsi_inw(hsi_ctrl->base, HSI_GDD_CCR_REG(lch));
	if (!(ccr & HSI_CCR_ENABLE)) {
		dev_dbg(&hsi_ch->dev->device, "Write cancel on not "
			"enabled logical channel %d CCR REG 0x%04X\n",
			lch, ccr);
	}
	status_reg = hsi_inl(hsi_ctrl->base, HSI_SYS_GDD_MPU_IRQ_STATUS_REG);
	status_reg &= hsi_inl(hsi_ctrl->base, HSI_SYS_GDD_MPU_IRQ_ENABLE_REG);
	hsi_outw_and(~HSI_CCR_ENABLE, hsi_ctrl->base, HSI_GDD_CCR_REG(lch));

	/* Clear CSR register by reading it, as it is cleared automaticaly */
	/* by HW after SW read. */
	gdd_csr = hsi_inw(hsi_ctrl->base, HSI_GDD_CSR_REG(lch));
	hsi_outl_and(~HSI_GDD_LCH(lch), hsi_ctrl->base,
			HSI_SYS_GDD_MPU_IRQ_ENABLE_REG);
	hsi_outl(HSI_GDD_LCH(lch), hsi_ctrl->base,
			HSI_SYS_GDD_MPU_IRQ_STATUS_REG);

	/* Unmap DMA region */
	dma_h = hsi_inl(hsi_ctrl->base, HSI_GDD_CSSA_REG(lch));
	size = hsi_inw(hsi_ctrl->base, HSI_GDD_CEN_REG(lch)) * 4;
	dma_unmap_single(hsi_ctrl->dev, dma_h, size, DMA_TO_DEVICE);

	buff_offset = hsi_hst_bufstate_f_reg(hsi_ctrl, port, channel);
	if (buff_offset >= 0)
		hsi_outl_and(~HSI_BUFSTATE_CHANNEL(channel), hsi_ctrl->base,
			     buff_offset);

	hsi_reset_ch_write(hsi_ch);
	return status_reg & HSI_GDD_LCH(lch) ? 0 : -ECANCELED;
}