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; }