static void do_channel_rx(struct hsi_channel *ch)
{
	struct hsi_dev *hsi_ctrl = ch->hsi_port->hsi_controller;
	void __iomem *base = ch->hsi_port->hsi_controller->base;
	unsigned int n_ch;
	unsigned int n_p;
	unsigned int irq;
	long buff_offset;
	int rx_poll = 0;
	int data_read = 0;

	n_ch = ch->channel_number;
	n_p = ch->hsi_port->port_number;
	irq = ch->hsi_port->n_irq;

	spin_lock(&hsi_ctrl->lock);

	if (ch->flags & HSI_CH_RX_POLL)
		rx_poll = 1;

	if (ch->read_data.addr) {
		buff_offset = hsi_hsr_buffer_reg(hsi_ctrl, n_p, n_ch);
		if (buff_offset >= 0) {
			data_read = 1;
			*(ch->read_data.addr) = hsi_inl(base, buff_offset);
		}
	}

	hsi_outl_and(~HSI_HSR_DATAAVAILABLE(n_ch), base,
				HSI_SYS_MPU_ENABLE_CH_REG(n_p, irq, n_ch));
	hsi_reset_ch_read(ch);

	spin_unlock(&hsi_ctrl->lock);

	if (rx_poll)
		hsi_port_event_handler(ch->hsi_port,
				HSI_EVENT_HSR_DATAAVAILABLE, (void *)n_ch);

	if (data_read)
		(*ch->read_done)(ch->dev, 1);
}
/* HSR_AVAILABLE interrupt processing */
static void hsi_do_channel_rx(struct hsi_channel *ch)
{
	struct hsi_dev *hsi_ctrl = ch->hsi_port->hsi_controller;
	void __iomem *base = ch->hsi_port->hsi_controller->base;
	unsigned int n_ch;
	unsigned int n_p;
	unsigned int irq;
	long buff_offset;
	int rx_poll = 0;
	int data_read = 0;
	int fifo, fifo_words_avail;

	n_ch = ch->channel_number;
	n_p = ch->hsi_port->port_number;
	irq = ch->hsi_port->n_irq;

	dev_dbg(hsi_ctrl->dev,
		"Data Available interrupt for channel %d.\n", n_ch);

	/* Check if there is data in FIFO available for reading */
	if (hsi_driver_device_is_hsi(to_platform_device(hsi_ctrl->dev))) {
		fifo = hsi_fifo_get_id(hsi_ctrl, n_ch, n_p);
		if (unlikely(fifo < 0)) {
			dev_err(hsi_ctrl->dev, "No valid FIFO id found for "
					       "channel %d.\n", n_ch);
			return;
		}
		fifo_words_avail = hsi_get_rx_fifo_occupancy(hsi_ctrl, fifo);
		if (!fifo_words_avail) {
			dev_dbg(hsi_ctrl->dev,
				"WARNING: RX FIFO %d empty before CPU copy\n",
				fifo);

			/* Do not disable interrupt becaue another interrupt */
			/* can still come, this time with a real frame. */
			return;
		}
	}

	/* Disable interrupts if not needed for polling */
	if (!(ch->flags & HSI_CH_RX_POLL))
		hsi_driver_disable_read_interrupt(ch);

	/*
	 * Check race condition: RX transmission initiated but DMA transmission
	 * already started - acknowledge then ignore interrupt occurence
	 */
	if (ch->read_data.lch != -1) {
		dev_warn(hsi_ctrl->dev,
			"Race condition between RX Int ch %d and DMA %0x\n",
			n_ch, ch->read_data.lch);
		goto done;
	}

	if (ch->flags & HSI_CH_RX_POLL)
		rx_poll = 1;

	if (ch->read_data.addr) {
		buff_offset = hsi_hsr_buffer_reg(hsi_ctrl, n_p, n_ch);
		if (buff_offset >= 0) {
			data_read = 1;
			*(ch->read_data.addr) = hsi_inl(base, buff_offset);
		}
	}

	hsi_reset_ch_read(ch);

done:
	if (rx_poll) {
		spin_unlock(&hsi_ctrl->lock);
		hsi_port_event_handler(ch->hsi_port,
				       HSI_EVENT_HSR_DATAAVAILABLE,
				       (void *)n_ch);
		spin_lock(&hsi_ctrl->lock);
	}

	if (data_read) {
		spin_unlock(&hsi_ctrl->lock);
		dev_dbg(hsi_ctrl->dev, "Calling ch %d read callback.\n", n_ch);
		(*ch->read_done) (ch->dev, 1);
		spin_lock(&hsi_ctrl->lock);
	}
}
static int hsi_debug_port_show(struct seq_file *m, void *p)
{
	struct hsi_port *hsi_port = m->private;
	struct hsi_dev *hsi_ctrl = hsi_port->hsi_controller;
	void __iomem *base = hsi_ctrl->base;
	unsigned int port = hsi_port->port_number;
	int ch, fifo;
	long buff_offset;
	struct platform_device *pdev = to_platform_device(hsi_ctrl->dev);

	hsi_clocks_enable(hsi_ctrl->dev, __func__);

	if (hsi_port->cawake_gpio >= 0)
		seq_printf(m, "CAWAKE\t\t: %d\n", hsi_get_cawake(hsi_port));

	seq_printf(m, "WAKE\t\t: 0x%08x\n",
		   hsi_inl(base, HSI_SYS_WAKE_REG(port)));
	seq_printf(m, "MPU_ENABLE_IRQ%d\t: 0x%08x\n", hsi_port->n_irq,
		   hsi_inl(base,
			   HSI_SYS_MPU_ENABLE_REG(port, hsi_port->n_irq)));
	seq_printf(m, "MPU_STATUS_IRQ%d\t: 0x%08x\n", hsi_port->n_irq,
		   hsi_inl(base,
			   HSI_SYS_MPU_STATUS_REG(port, hsi_port->n_irq)));
	if (hsi_driver_device_is_hsi(pdev)) {
		seq_printf(m, "MPU_U_ENABLE_IRQ%d\t: 0x%08x\n",
			   hsi_port->n_irq,
			   hsi_inl(base, HSI_SYS_MPU_U_ENABLE_REG(port,
							hsi_port->n_irq)));
		seq_printf(m, "MPU_U_STATUS_IRQ%d\t: 0x%08x\n", hsi_port->n_irq,
			   hsi_inl(base,
				   HSI_SYS_MPU_U_STATUS_REG(port,
							    hsi_port->n_irq)));
	}
	/* HST */
	seq_printf(m, "\nHST\n===\n");
	seq_printf(m, "MODE\t\t: 0x%08x\n",
		   hsi_inl(base, HSI_HST_MODE_REG(port)));
	seq_printf(m, "FRAMESIZE\t: 0x%08x\n",
		   hsi_inl(base, HSI_HST_FRAMESIZE_REG(port)));
	seq_printf(m, "DIVISOR\t\t: 0x%08x\n",
		   hsi_inl(base, HSI_HST_DIVISOR_REG(port)));
	seq_printf(m, "CHANNELS\t: 0x%08x\n",
		   hsi_inl(base, HSI_HST_CHANNELS_REG(port)));
	seq_printf(m, "ARBMODE\t\t: 0x%08x\n",
		   hsi_inl(base, HSI_HST_ARBMODE_REG(port)));
	seq_printf(m, "TXSTATE\t\t: 0x%08x\n",
		   hsi_inl(base, HSI_HST_TXSTATE_REG(port)));
	if (hsi_driver_device_is_hsi(pdev)) {
		seq_printf(m, "BUFSTATE P1\t: 0x%08x\n",
			   hsi_inl(base, HSI_HST_BUFSTATE_REG(1)));
		seq_printf(m, "BUFSTATE P2\t: 0x%08x\n",
			   hsi_inl(base, HSI_HST_BUFSTATE_REG(2)));
	} else {
		seq_printf(m, "BUFSTATE\t: 0x%08x\n",
			   hsi_inl(base, HSI_HST_BUFSTATE_REG(port)));
	}
	seq_printf(m, "BREAK\t\t: 0x%08x\n",
		   hsi_inl(base, HSI_HST_BREAK_REG(port)));
	for (ch = 0; ch < 8; ch++) {
		buff_offset = hsi_hst_buffer_reg(hsi_ctrl, port, ch);
		if (buff_offset >= 0)
			seq_printf(m, "BUFFER_CH%d\t: 0x%08x\n", ch,
				   hsi_inl(base, buff_offset));
	}
	if (hsi_driver_device_is_hsi(pdev)) {
		for (fifo = 0; fifo < HSI_HST_FIFO_COUNT; fifo++) {
			seq_printf(m, "FIFO MAPPING%d\t: 0x%08x\n", fifo,
				   hsi_inl(base,
					   HSI_HST_MAPPING_FIFO_REG(fifo)));
		}
	}
	/* HSR */
	seq_printf(m, "\nHSR\n===\n");
	seq_printf(m, "MODE\t\t: 0x%08x\n",
		   hsi_inl(base, HSI_HSR_MODE_REG(port)));
	seq_printf(m, "FRAMESIZE\t: 0x%08x\n",
		   hsi_inl(base, HSI_HSR_FRAMESIZE_REG(port)));
	seq_printf(m, "CHANNELS\t: 0x%08x\n",
		   hsi_inl(base, HSI_HSR_CHANNELS_REG(port)));
	seq_printf(m, "COUNTERS\t: 0x%08x\n",
		   hsi_inl(base, HSI_HSR_COUNTERS_REG(port)));
	seq_printf(m, "RXSTATE\t\t: 0x%08x\n",
		   hsi_inl(base, HSI_HSR_RXSTATE_REG(port)));
	if (hsi_driver_device_is_hsi(pdev)) {
		seq_printf(m, "BUFSTATE P1\t: 0x%08x\n",
			   hsi_inl(base, HSI_HSR_BUFSTATE_REG(1)));
		seq_printf(m, "BUFSTATE P2\t: 0x%08x\n",
			   hsi_inl(base, HSI_HSR_BUFSTATE_REG(2)));
	} else {
		seq_printf(m, "BUFSTATE\t: 0x%08x\n",
			   hsi_inl(base, HSI_HSR_BUFSTATE_REG(port)));
	}
	seq_printf(m, "BREAK\t\t: 0x%08x\n",
		   hsi_inl(base, HSI_HSR_BREAK_REG(port)));
	seq_printf(m, "ERROR\t\t: 0x%08x\n",
		   hsi_inl(base, HSI_HSR_ERROR_REG(port)));
	seq_printf(m, "ERRORACK\t: 0x%08x\n",
		   hsi_inl(base, HSI_HSR_ERRORACK_REG(port)));
	for (ch = 0; ch < 8; ch++) {
		buff_offset = hsi_hsr_buffer_reg(hsi_ctrl, port, ch);
		if (buff_offset >= 0)
			seq_printf(m, "BUFFER_CH%d\t: 0x%08x\n", ch,
				   hsi_inl(base, buff_offset));
	}
	if (hsi_driver_device_is_hsi(pdev)) {
		for (fifo = 0; fifo < HSI_HSR_FIFO_COUNT; fifo++) {
			seq_printf(m, "FIFO MAPPING%d\t: 0x%08x\n", fifo,
				   hsi_inl(base,
					   HSI_HSR_MAPPING_FIFO_REG(fifo)));
		}
		seq_printf(m, "DLL\t: 0x%08x\n",
			   hsi_inl(base, HSI_HSR_DLL_REG));
		seq_printf(m, "DIVISOR\t: 0x%08x\n",
			   hsi_inl(base, HSI_HSR_DIVISOR_REG(port)));
	}

	hsi_clocks_disable(hsi_ctrl->dev, __func__);

	return 0;
}