/** * 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; }
static void do_channel_tx(struct hsi_channel *ch) { struct hsi_dev *hsi_ctrl = ch->hsi_port->hsi_controller; void __iomem *base = hsi_ctrl->base; unsigned int n_ch; unsigned int n_p; unsigned int irq; long buff_offset; 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->write_data.addr == NULL) { hsi_outl_and(~HSI_HST_DATAACCEPT(n_ch), base, HSI_SYS_MPU_ENABLE_CH_REG(n_p, irq, n_ch)); hsi_reset_ch_write(ch); spin_unlock(&hsi_ctrl->lock); (*ch->write_done)(ch->dev, 1); } else { buff_offset = hsi_hst_buffer_reg(hsi_ctrl, n_p, n_ch); if (buff_offset >= 0) { hsi_outl(*(ch->write_data.addr), base, buff_offset); ch->write_data.addr = NULL; } spin_unlock(&hsi_ctrl->lock); } }
void hsi_driver_disable_read_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; hsi_outl_and(~HSI_HSR_DATAAVAILABLE(channel), base, HSI_SYS_MPU_ENABLE_CH_REG(port, p->n_irq, channel)); }
/* Enables the Data Available Interrupt of HSR for the given channel */ int hsi_driver_enable_read_interrupt(struct hsi_channel *ch, u32 * data) { struct hsi_port *p = ch->hsi_port; unsigned int port = p->port_number; unsigned int channel = ch->channel_number; hsi_outl_or(HSI_HSR_DATAAVAILABLE(channel), p->hsi_controller->base, HSI_SYS_MPU_ENABLE_CH_REG(port, p->n_irq, channel)); return 0; }
/** * hsi_driver_cancel_read_interrupt - Cancel pending read interrupt. * @dev - hsi device channel where to cancel the pending interrupt. * * Return: -ECANCELED : read cancel success data not available at expected * address. * 0 : transfer is already over, data already available at expected * address. * * Note: whatever returned value, read callback will not be called after cancel. */ int hsi_driver_cancel_read_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; status_reg = hsi_inl(base, HSI_SYS_MPU_ENABLE_CH_REG(port, p->n_irq, channel)); if (!(status_reg & HSI_HSR_DATAAVAILABLE(channel))) { dev_dbg(&ch->dev->device, "Read 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_HSR_DATAAVAILABLE(channel), base, HSI_SYS_MPU_ENABLE_CH_REG(port, p->n_irq, channel)); hsi_reset_ch_read(ch); return status_reg & HSI_HSR_DATAAVAILABLE(channel) ? 0 : -ECANCELED; }
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); }