static void clear_chan_interrupts(int c) { out_le32(&(host_pvt.sata_dma_regs->interrupt_clear.tfr.low), DMA_CHANNEL(c)); out_le32(&(host_pvt.sata_dma_regs->interrupt_clear.block.low), DMA_CHANNEL(c)); out_le32(&(host_pvt.sata_dma_regs->interrupt_clear.srctran.low), DMA_CHANNEL(c)); out_le32(&(host_pvt.sata_dma_regs->interrupt_clear.dsttran.low), DMA_CHANNEL(c)); out_le32(&(host_pvt.sata_dma_regs->interrupt_clear.error.low), DMA_CHANNEL(c)); }
/* * Function: dma_request_channel * arguments: None * returns channel number if available else -1 * This function assigns the next available DMA channel from the list to the * requester */ static int dma_request_channel(void) { /* Check if the channel is not currently in use */ if (!(in_le32(&(host_pvt.sata_dma_regs->dma_chan_en.low)) & DMA_CHANNEL(host_pvt.dma_channel))) return host_pvt.dma_channel; dev_err(host_pvt.dwc_dev, "%s Channel %d is currently in use\n", __func__, host_pvt.dma_channel); return -1; }
static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status) { struct mmc_request *mrq = host->mrq; struct mmc_data *data; u32 crc; WARN_ON(host->status != HOST_S_DATA && host->status != HOST_S_STOP); if (host->mrq == NULL) return; data = mrq->cmd->data; if (status == 0) status = au_readl(HOST_STATUS(host)); /* The transaction is really over when the SD_STATUS_DB bit is clear */ while((host->flags & HOST_F_XMIT) && (status & SD_STATUS_DB)) status = au_readl(HOST_STATUS(host)); data->error = MMC_ERR_NONE; dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma.dir); /* Process any errors */ crc = (status & (SD_STATUS_WC | SD_STATUS_RC)); if (host->flags & HOST_F_XMIT) crc |= ((status & 0x07) == 0x02) ? 0 : 1; if (crc) data->error = MMC_ERR_BADCRC; /* Clear the CRC bits */ au_writel(SD_STATUS_WC | SD_STATUS_RC, HOST_STATUS(host)); data->bytes_xfered = 0; if (data->error == MMC_ERR_NONE) { if (host->flags & HOST_F_DMA) { u32 chan = DMA_CHANNEL(host); chan_tab_t *c = *((chan_tab_t **) chan); au1x_dma_chan_t *cp = c->chan_ptr; data->bytes_xfered = cp->ddma_bytecnt; } else data->bytes_xfered = (data->blocks * (1 << data->blksz_bits)) - host->pio.len; } au1xmmc_finish_request(host); }
static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status) { struct mmc_request *mrq = host->mrq; struct mmc_data *data; u32 crc; WARN_ON((host->status != HOST_S_DATA) && (host->status != HOST_S_STOP)); if (host->mrq == NULL) return; data = mrq->cmd->data; if (status == 0) status = au_readl(HOST_STATUS(host)); while ((host->flags & HOST_F_XMIT) && (status & SD_STATUS_DB)) status = au_readl(HOST_STATUS(host)); data->error = 0; dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma.dir); crc = (status & (SD_STATUS_WC | SD_STATUS_RC)); if (host->flags & HOST_F_XMIT) crc |= ((status & 0x07) == 0x02) ? 0 : 1; if (crc) data->error = -EILSEQ; au_writel(SD_STATUS_WC | SD_STATUS_RC, HOST_STATUS(host)); data->bytes_xfered = 0; if (!data->error) { if (host->flags & HOST_F_DMA) { #ifdef CONFIG_SOC_AU1200 u32 chan = DMA_CHANNEL(host); chan_tab_t *c = *((chan_tab_t **)chan); au1x_dma_chan_t *cp = c->chan_ptr; data->bytes_xfered = cp->ddma_bytecnt; #endif } else data->bytes_xfered = (data->blocks * data->blksz) - host->pio.len; } au1xmmc_finish_request(host); }
static int dma_request_channel(void) { int i; for (i = 0; i < DMA_NUM_CHANS; i++) { if (!(in_le32(&(host_pvt.sata_dma_regs->dma_chan_en.low)) &\ DMA_CHANNEL(i))) return i; } dev_err(host_pvt.dwc_dev, "%s NO channel chan_en: 0x%08x\n", __func__, in_le32(&(host_pvt.sata_dma_regs->dma_chan_en.low))); return -1; }
//! This function dynamic allocate a channel according the DMA requests. //! The \ref ulDMASrcRequest and \ref ulDMADestRequest can be: //! - \ref DMA_REQUEST_ADC0_RX //! - \ref DMA_REQUEST_TIM2_CH3 //! - \ref DMA_REQUEST_TIM4_CH1 //! - \ref DMA_REQUEST_UART3_TX //! - \ref DMA_REQUEST_TIM1_CH1 //! - \ref DMA_REQUEST_TIM2_UP //! - \ref DMA_REQUEST_TIM3_CH3 //! - \ref DMA_REQUEST_SPI1_RX //! - \ref DMA_REQUEST_UART3_RX //! - \ref DMA_REQUEST_TIM1_CH2 //! - \ref DMA_REQUEST_TIM3_CH4 //! - \ref DMA_REQUEST_TIM3_UP //! - others refrence \ref STM32F1xx_DMA_Request_Connections //! . //! //! \note ulDMASrcRequest can only be XX_RX and TIMx_CHx //! ulDMADestRequest can only be XX_TX,TIMx_TRIG,TIMx_COM and TIMx_UP. //! //! \return Returns a Channel ID that dynamic assignment. //! The channel ID can be: //! - DMA1_CHANNEL_1 //! - DMA1_CHANNEL_2 //! - others refrence \ref STM32F1xx_DMA_Channel_IDs //! . // //***************************************************************************** unsigned long DMAChannelDynamicAssign(unsigned long ulDMASrcRequest, unsigned long ulDMADestRequest) { unsigned long ulChannelID; // // Check the arguments. // xASSERT((ulDMASrcRequest == DMA_REQUEST_ADC0_RX) || (ulDMASrcRequest == DMA_REQUEST_TIM2_CH3) || (ulDMASrcRequest == DMA_REQUEST_TIM4_CH1) || (ulDMASrcRequest == xDMA_REQUEST_MEM) || (ulDMASrcRequest == DMA_REQUEST_TIM1_CH1) || (ulDMASrcRequest == DMA_REQUEST_TIM3_CH3) || (ulDMASrcRequest == DMA_REQUEST_SPI1_RX) || (ulDMASrcRequest == DMA_REQUEST_TIM3_CH4) || (ulDMASrcRequest == DMA_REQUEST_TIM1_CH4) || (ulDMASrcRequest == DMA_REQUEST_TIM4_CH2) || (ulDMASrcRequest == DMA_REQUEST_SPI2_RX) || (ulDMASrcRequest == DMA_REQUEST_I2S2_RX) || (ulDMASrcRequest == DMA_REQUEST_TIM2_CH1) || (ulDMASrcRequest == DMA_REQUEST_TIM4_CH3) || (ulDMASrcRequest == DMA_REQUEST_I2C2_RX) || (ulDMASrcRequest == DMA_REQUEST_TIM1_CH3) || (ulDMASrcRequest == DMA_REQUEST_TIM3_CH1) || (ulDMASrcRequest == DMA_REQUEST_TIM2_CH2) || (ulDMASrcRequest == DMA_REQUEST_TIM2_CH4) || (ulDMASrcRequest == DMA_REQUEST_I2C1_RX) || (ulDMASrcRequest == DMA_REQUEST_TIM5_CH4) || (ulDMASrcRequest == DMA_REQUEST_TIM8_CH3) || (ulDMASrcRequest == DMA_REQUEST_SPI3_RX) || (ulDMASrcRequest == DMA_REQUEST_I2S3_RX) || (ulDMASrcRequest == DMA_REQUEST_TIM8_CH4) || (ulDMASrcRequest == DMA_REQUEST_TIM5_CH3) || (ulDMASrcRequest == DMA_REQUEST_TIM8_CH1) || (ulDMASrcRequest == DMA_REQUEST_TIM5_CH2) || (ulDMASrcRequest == DMA_REQUEST_SDIO_RX) || (ulDMASrcRequest == DMA_REQUEST_ADC3_RX) || (ulDMASrcRequest == DMA_REQUEST_TIM8_CH2) || (ulDMASrcRequest == DMA_REQUEST_TIM5_CH1) || (ulDMASrcRequest == DMA_REQUEST_TIM1_CH2) ); xASSERT((ulDMADestRequest == DMA_REQUEST_UART3_TX) || (ulDMADestRequest == DMA_REQUEST_TIM1_UP) || (ulDMADestRequest == xDMA_REQUEST_MEM) || (ulDMADestRequest == DMA_REQUEST_TIM3_UP) || (ulDMADestRequest == DMA_REQUEST_SPI1_TX) || (ulDMADestRequest == DMA_REQUEST_UART1_TX) || (ulDMADestRequest == DMA_REQUEST_TIM1_TRIG) || (ulDMADestRequest == DMA_REQUEST_TIM1_COM) || (ulDMADestRequest == DMA_REQUEST_I2C2_TX) || (ulDMADestRequest == DMA_REQUEST_TIM1_UP) || (ulDMADestRequest == DMA_REQUEST_SPI2_TX) || (ulDMADestRequest == DMA_REQUEST_I2S2_TX) || (ulDMADestRequest == DMA_REQUEST_TIM3_TRIG) || (ulDMADestRequest == DMA_REQUEST_I2C1_TX) || (ulDMADestRequest == DMA_REQUEST_UART2_TX) || (ulDMADestRequest == DMA_REQUEST_TIM4_UP) || (ulDMADestRequest == DMA_REQUEST_TIM5_TRIG) || (ulDMADestRequest == DMA_REQUEST_TIM8_UP) || (ulDMADestRequest == DMA_REQUEST_TIM8_TRIG) || (ulDMADestRequest == DMA_REQUEST_TIM8_COM) || (ulDMADestRequest == DMA_REQUEST_TIM5_UP) || (ulDMADestRequest == DMA_REQUEST_SPI3_TX) || (ulDMADestRequest == DMA_REQUEST_I2S3_TX) || (ulDMADestRequest == DMA_REQUEST_TIM6_UP) || (ulDMADestRequest == DMA_REQUEST_DAC_CH1) || (ulDMADestRequest == DMA_REQUEST_SDIO_TX) || (ulDMADestRequest == DMA_REQUEST_TIM7_UP) || (ulDMADestRequest == DMA_REQUEST_DAC_CH2) || (ulDMADestRequest == DMA_REQUEST_UART4_TX) ); // // STM32F1xx DMA support P to P // if((ulDMASrcRequest != xDMA_REQUEST_MEM) && (ulDMADestRequest != xDMA_REQUEST_MEM)) { if(g_psDMAChannelAssignTable[DMA_CHANNEL(ulDMASrcRequest)].bChannelAssigned == xfalse) { g_psDMAChannelAssignTable[DMA_CHANNEL(ulDMASrcRequest)].bChannelAssigned = xtrue; xHWREG(DMA_ADDR(ulDMASrcRequest)) &= ~(DMA_CCR1_DIR | DMA_CCR1_MEM2MEM); xHWREG(DMA_ADDR(ulDMASrcRequest)) |= DMA_CCR1_DIR; return g_psDMAChannelAssignTable[DMA_CHANNEL(ulDMASrcRequest)].ulChannelID; } else { return xDMA_CHANNEL_NOT_EXIST; } } if((ulDMASrcRequest == xDMA_REQUEST_MEM) && (ulDMADestRequest & 0x00000100)) { if(g_psDMAChannelAssignTable[DMA_CHANNEL(ulDMADestRequest)].bChannelAssigned == xfalse) { g_psDMAChannelAssignTable[DMA_CHANNEL(ulDMADestRequest)].bChannelAssigned = xtrue; xHWREG(DMA_ADDR(ulDMADestRequest)) &= ~(DMA_CCR1_DIR | DMA_CCR1_MEM2MEM); xHWREG(DMA_ADDR(ulDMADestRequest)) |= DMA_CCR1_DIR; return g_psDMAChannelAssignTable[DMA_CHANNEL(ulDMADestRequest)].ulChannelID; } else { return xDMA_CHANNEL_NOT_EXIST; } } if((ulDMADestRequest == xDMA_REQUEST_MEM) && (ulDMASrcRequest != xDMA_REQUEST_MEM) && !(ulDMASrcRequest & 0x00000100)) { if(g_psDMAChannelAssignTable[DMA_CHANNEL(ulDMASrcRequest)].bChannelAssigned == xfalse) { g_psDMAChannelAssignTable[DMA_CHANNEL(ulDMASrcRequest)].bChannelAssigned = xtrue; xHWREG(DMA_ADDR(ulDMASrcRequest)) &= ~(DMA_CCR1_DIR | DMA_CCR1_MEM2MEM); return g_psDMAChannelAssignTable[DMA_CHANNEL(ulDMASrcRequest)].ulChannelID; } else { return xDMA_CHANNEL_NOT_EXIST; } } // // Mem to Mem type // if((ulDMASrcRequest & xDMA_REQUEST_MEM) && (ulDMADestRequest & xDMA_REQUEST_MEM)) { for(ulChannelID = 0; g_psDMAChannelAssignTable[ulChannelID].ulChannelID != xDMA_CHANNEL_NOT_EXIST; ulChannelID++) { if(g_psDMAChannelAssignTable[ulChannelID].bChannelAssigned == xfalse) { g_psDMAChannelAssignTable[ulChannelID].bChannelAssigned = xtrue; break; } } xHWREG(g_psDMAChannel[ulChannelID]) &= ~(DMA_CCR1_DIR | DMA_CCR1_MEM2MEM); xHWREG(g_psDMAChannel[ulChannelID]) |= (DMA_CCR1_MEM2MEM); return g_psDMAChannelAssignTable[ulChannelID].ulChannelID; } // // when the src request is tx type, or dest request is rx type, assign false. // return xDMA_CHANNEL_NOT_EXIST; }
.addr = 0xfe1f0064, .chcr = CHCR_TX(XMIT_SZ_32BIT), .mid_rid = 0xb5, }, }; #define DMA_CHANNEL(a, b, c) \ { \ .offset = a, \ .dmars = b, \ .dmars_bit = c, \ .chclr_offset = (0x220 - 0x20) + a \ } static const struct sh_dmae_channel r8a7740_dmae_channels[] = { DMA_CHANNEL(0x00, 0, 0), DMA_CHANNEL(0x10, 0, 8), DMA_CHANNEL(0x20, 4, 0), DMA_CHANNEL(0x30, 4, 8), DMA_CHANNEL(0x50, 8, 0), DMA_CHANNEL(0x60, 8, 8), }; static struct sh_dmae_pdata dma_platform_data = { .slave = r8a7740_dmae_slaves, .slave_num = ARRAY_SIZE(r8a7740_dmae_slaves), .channel = r8a7740_dmae_channels, .channel_num = ARRAY_SIZE(r8a7740_dmae_channels), .ts_low_shift = TS_LOW_SHIFT, .ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT, .ts_high_shift = TS_HI_SHIFT,
namespace chip { #ifdef DISTORTOS_CHIP_SPI1_ENABLE /*---------------------------------------------------------------------------------------------------------------------+ | SPI1 +---------------------------------------------------------------------------------------------------------------------*/ namespace { /** * \brief Low-level chip initializer for SPI1 * * This function is called before constructors for global and static objects via BIND_LOW_LEVEL_INITIALIZER(). */ void spi1LowLevelInitializer() { #if defined(RCC_APB1ENR_SPI1EN) RCC->APB1ENR |= RCC_APB1ENR_SPI1EN; #elif defined(RCC_APB1ENR1_SPI1EN) RCC->APB1ENR1 |= RCC_APB1ENR1_SPI1EN; #elif defined(RCC_APB2ENR_SPI1EN) RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; #else #error "Unsupported bus for SPI1!" #endif } BIND_LOW_LEVEL_INITIALIZER(50, spi1LowLevelInitializer); /// raw SPI1 peripheral const SpiPeripheral spi1Peripheral {SPI1_BASE}; } // namespace #ifdef DISTORTOS_CHIP_SPI1_DMA_BASED SpiMasterLowLevelDmaBased spi1 { spi1Peripheral, DMA_CHANNEL(DISTORTOS_CHIP_SPI1_RX_DMA, DISTORTOS_CHIP_SPI1_RX_DMA_CHANNEL), DISTORTOS_CHIP_SPI1_RX_DMA_REQUEST, DMA_CHANNEL(DISTORTOS_CHIP_SPI1_TX_DMA, DISTORTOS_CHIP_SPI1_TX_DMA_CHANNEL), DISTORTOS_CHIP_SPI1_TX_DMA_REQUEST }; #else // !def DISTORTOS_CHIP_SPI1_DMA_BASED SpiMasterLowLevelInterruptBased spi1 {spi1Peripheral}; /** * \brief SPI1 interrupt handler */ extern "C" void SPI1_IRQHandler() { spi1.interruptHandler(); } #endif // !def DISTORTOS_CHIP_SPI1_DMA_BASED #endif // def DISTORTOS_CHIP_SPI1_ENABLE #ifdef DISTORTOS_CHIP_SPI2_ENABLE /*---------------------------------------------------------------------------------------------------------------------+ | SPI2 +---------------------------------------------------------------------------------------------------------------------*/ namespace { /** * \brief Low-level chip initializer for SPI2 * * This function is called before constructors for global and static objects via BIND_LOW_LEVEL_INITIALIZER(). */ void spi2LowLevelInitializer() { #if defined(RCC_APB1ENR_SPI2EN) RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; #elif defined(RCC_APB1ENR1_SPI2EN) RCC->APB1ENR1 |= RCC_APB1ENR1_SPI2EN; #elif defined(RCC_APB2ENR_SPI2EN) RCC->APB2ENR |= RCC_APB2ENR_SPI2EN; #else #error "Unsupported bus for SPI2!" #endif } BIND_LOW_LEVEL_INITIALIZER(50, spi2LowLevelInitializer); /// raw SPI2 peripheral const SpiPeripheral spi2Peripheral {SPI2_BASE}; } // namespace #ifdef DISTORTOS_CHIP_SPI2_DMA_BASED SpiMasterLowLevelDmaBased spi2 { spi2Peripheral, DMA_CHANNEL(DISTORTOS_CHIP_SPI2_RX_DMA, DISTORTOS_CHIP_SPI2_RX_DMA_CHANNEL), DISTORTOS_CHIP_SPI2_RX_DMA_REQUEST, DMA_CHANNEL(DISTORTOS_CHIP_SPI2_TX_DMA, DISTORTOS_CHIP_SPI2_TX_DMA_CHANNEL), DISTORTOS_CHIP_SPI2_TX_DMA_REQUEST }; #else // !def DISTORTOS_CHIP_SPI2_DMA_BASED SpiMasterLowLevelInterruptBased spi2 {spi2Peripheral}; /** * \brief SPI2 interrupt handler */ extern "C" void SPI2_IRQHandler() { spi2.interruptHandler(); } #endif // !def DISTORTOS_CHIP_SPI2_DMA_BASED #endif // def DISTORTOS_CHIP_SPI2_ENABLE #ifdef DISTORTOS_CHIP_SPI3_ENABLE /*---------------------------------------------------------------------------------------------------------------------+ | SPI3 +---------------------------------------------------------------------------------------------------------------------*/ namespace { /** * \brief Low-level chip initializer for SPI3 * * This function is called before constructors for global and static objects via BIND_LOW_LEVEL_INITIALIZER(). */ void spi3LowLevelInitializer() { #if defined(RCC_APB1ENR_SPI3EN) RCC->APB1ENR |= RCC_APB1ENR_SPI3EN; #elif defined(RCC_APB1ENR1_SPI3EN) RCC->APB1ENR1 |= RCC_APB1ENR1_SPI3EN; #elif defined(RCC_APB2ENR_SPI3EN) RCC->APB2ENR |= RCC_APB2ENR_SPI3EN; #else #error "Unsupported bus for SPI3!" #endif } BIND_LOW_LEVEL_INITIALIZER(50, spi3LowLevelInitializer); /// raw SPI3 peripheral const SpiPeripheral spi3Peripheral {SPI3_BASE}; } // namespace #ifdef DISTORTOS_CHIP_SPI3_DMA_BASED SpiMasterLowLevelDmaBased spi3 { spi3Peripheral, DMA_CHANNEL(DISTORTOS_CHIP_SPI3_RX_DMA, DISTORTOS_CHIP_SPI3_RX_DMA_CHANNEL), DISTORTOS_CHIP_SPI3_RX_DMA_REQUEST, DMA_CHANNEL(DISTORTOS_CHIP_SPI3_TX_DMA, DISTORTOS_CHIP_SPI3_TX_DMA_CHANNEL), DISTORTOS_CHIP_SPI3_TX_DMA_REQUEST }; #else // !def DISTORTOS_CHIP_SPI3_DMA_BASED SpiMasterLowLevelInterruptBased spi3 {spi3Peripheral}; /** * \brief SPI3 interrupt handler */ extern "C" void SPI3_IRQHandler() { spi3.interruptHandler(); } #endif // !def DISTORTOS_CHIP_SPI3_DMA_BASED #endif // def DISTORTOS_CHIP_SPI3_ENABLE #ifdef DISTORTOS_CHIP_SPI4_ENABLE /*---------------------------------------------------------------------------------------------------------------------+ | SPI4 +---------------------------------------------------------------------------------------------------------------------*/ namespace { /** * \brief Low-level chip initializer for SPI4 * * This function is called before constructors for global and static objects via BIND_LOW_LEVEL_INITIALIZER(). */ void spi4LowLevelInitializer() { #if defined(RCC_APB1ENR_SPI4EN) RCC->APB1ENR |= RCC_APB1ENR_SPI4EN; #elif defined(RCC_APB1ENR1_SPI4EN) RCC->APB1ENR1 |= RCC_APB1ENR1_SPI4EN; #elif defined(RCC_APB2ENR_SPI4EN) RCC->APB2ENR |= RCC_APB2ENR_SPI4EN; #else #error "Unsupported bus for SPI4!" #endif } BIND_LOW_LEVEL_INITIALIZER(50, spi4LowLevelInitializer); /// raw SPI4 peripheral const SpiPeripheral spi4Peripheral {SPI4_BASE}; } // namespace #ifdef DISTORTOS_CHIP_SPI4_DMA_BASED SpiMasterLowLevelDmaBased spi4 { spi4Peripheral, DMA_CHANNEL(DISTORTOS_CHIP_SPI4_RX_DMA, DISTORTOS_CHIP_SPI4_RX_DMA_CHANNEL), DISTORTOS_CHIP_SPI4_RX_DMA_REQUEST, DMA_CHANNEL(DISTORTOS_CHIP_SPI4_TX_DMA, DISTORTOS_CHIP_SPI4_TX_DMA_CHANNEL), DISTORTOS_CHIP_SPI4_TX_DMA_REQUEST }; #else // !def DISTORTOS_CHIP_SPI4_DMA_BASED SpiMasterLowLevelInterruptBased spi4 {spi4Peripheral}; /** * \brief SPI4 interrupt handler */ extern "C" void SPI4_IRQHandler() { spi4.interruptHandler(); } #endif // !def DISTORTOS_CHIP_SPI4_DMA_BASED #endif // def DISTORTOS_CHIP_SPI4_ENABLE #ifdef DISTORTOS_CHIP_SPI5_ENABLE /*---------------------------------------------------------------------------------------------------------------------+ | SPI5 +---------------------------------------------------------------------------------------------------------------------*/ namespace { /** * \brief Low-level chip initializer for SPI5 * * This function is called before constructors for global and static objects via BIND_LOW_LEVEL_INITIALIZER(). */ void spi5LowLevelInitializer() { #if defined(RCC_APB1ENR_SPI5EN) RCC->APB1ENR |= RCC_APB1ENR_SPI5EN; #elif defined(RCC_APB1ENR1_SPI5EN) RCC->APB1ENR1 |= RCC_APB1ENR1_SPI5EN; #elif defined(RCC_APB2ENR_SPI5EN) RCC->APB2ENR |= RCC_APB2ENR_SPI5EN; #else #error "Unsupported bus for SPI5!" #endif } BIND_LOW_LEVEL_INITIALIZER(50, spi5LowLevelInitializer); /// raw SPI5 peripheral const SpiPeripheral spi5Peripheral {SPI5_BASE}; } // namespace #ifdef DISTORTOS_CHIP_SPI5_DMA_BASED SpiMasterLowLevelDmaBased spi5 { spi5Peripheral, DMA_CHANNEL(DISTORTOS_CHIP_SPI5_RX_DMA, DISTORTOS_CHIP_SPI5_RX_DMA_CHANNEL), DISTORTOS_CHIP_SPI5_RX_DMA_REQUEST, DMA_CHANNEL(DISTORTOS_CHIP_SPI5_TX_DMA, DISTORTOS_CHIP_SPI5_TX_DMA_CHANNEL), DISTORTOS_CHIP_SPI5_TX_DMA_REQUEST }; #else // !def DISTORTOS_CHIP_SPI5_DMA_BASED SpiMasterLowLevelInterruptBased spi5 {spi5Peripheral}; /** * \brief SPI5 interrupt handler */ extern "C" void SPI5_IRQHandler() { spi5.interruptHandler(); } #endif // !def DISTORTOS_CHIP_SPI5_DMA_BASED #endif // def DISTORTOS_CHIP_SPI5_ENABLE #ifdef DISTORTOS_CHIP_SPI6_ENABLE /*---------------------------------------------------------------------------------------------------------------------+ | SPI6 +---------------------------------------------------------------------------------------------------------------------*/ namespace { /** * \brief Low-level chip initializer for SPI6 * * This function is called before constructors for global and static objects via BIND_LOW_LEVEL_INITIALIZER(). */ void spi6LowLevelInitializer() { #if defined(RCC_APB1ENR_SPI6EN) RCC->APB1ENR |= RCC_APB1ENR_SPI6EN; #elif defined(RCC_APB1ENR1_SPI6EN) RCC->APB1ENR1 |= RCC_APB1ENR1_SPI6EN; #elif defined(RCC_APB2ENR_SPI6EN) RCC->APB2ENR |= RCC_APB2ENR_SPI6EN; #else #error "Unsupported bus for SPI6!" #endif } BIND_LOW_LEVEL_INITIALIZER(50, spi6LowLevelInitializer); /// raw SPI6 peripheral const SpiPeripheral spi6Peripheral {SPI6_BASE}; } // namespace #ifdef DISTORTOS_CHIP_SPI6_DMA_BASED SpiMasterLowLevelDmaBased spi6 { spi6Peripheral, DMA_CHANNEL(DISTORTOS_CHIP_SPI6_RX_DMA, DISTORTOS_CHIP_SPI6_RX_DMA_CHANNEL), DISTORTOS_CHIP_SPI6_RX_DMA_REQUEST, DMA_CHANNEL(DISTORTOS_CHIP_SPI6_TX_DMA, DISTORTOS_CHIP_SPI6_TX_DMA_CHANNEL), DISTORTOS_CHIP_SPI6_TX_DMA_REQUEST }; #else // !def DISTORTOS_CHIP_SPI6_DMA_BASED SpiMasterLowLevelInterruptBased spi6 {spi6Peripheral}; /** * \brief SPI6 interrupt handler */ extern "C" void SPI6_IRQHandler() { spi6.interruptHandler(); } #endif // !def DISTORTOS_CHIP_SPI6_DMA_BASED #endif // def DISTORTOS_CHIP_SPI6_ENABLE } // namespace chip
* DMA M2P channels. * * On the EP93xx chip the following peripherals my be allocated to the 10 * Memory to Internal Peripheral (M2P) channels (5 transmit + 5 receive). * * I2S contains 3 Tx and 3 Rx DMA Channels * AAC contains 3 Tx and 3 Rx DMA Channels * UART1 contains 1 Tx and 1 Rx DMA Channels * UART2 contains 1 Tx and 1 Rx DMA Channels * UART3 contains 1 Tx and 1 Rx DMA Channels * IrDA contains 1 Tx and 1 Rx DMA Channels * * Registers are mapped statically in ep93xx_map_io(). */ static struct ep93xx_dma_chan_data ep93xx_dma_m2p_channels[] = { DMA_CHANNEL("m2p0", EP93XX_DMA_BASE + 0x0000, IRQ_EP93XX_DMAM2P0), DMA_CHANNEL("m2p1", EP93XX_DMA_BASE + 0x0040, IRQ_EP93XX_DMAM2P1), DMA_CHANNEL("m2p2", EP93XX_DMA_BASE + 0x0080, IRQ_EP93XX_DMAM2P2), DMA_CHANNEL("m2p3", EP93XX_DMA_BASE + 0x00c0, IRQ_EP93XX_DMAM2P3), DMA_CHANNEL("m2p4", EP93XX_DMA_BASE + 0x0240, IRQ_EP93XX_DMAM2P4), DMA_CHANNEL("m2p5", EP93XX_DMA_BASE + 0x0200, IRQ_EP93XX_DMAM2P5), DMA_CHANNEL("m2p6", EP93XX_DMA_BASE + 0x02c0, IRQ_EP93XX_DMAM2P6), DMA_CHANNEL("m2p7", EP93XX_DMA_BASE + 0x0280, IRQ_EP93XX_DMAM2P7), DMA_CHANNEL("m2p8", EP93XX_DMA_BASE + 0x0340, IRQ_EP93XX_DMAM2P8), DMA_CHANNEL("m2p9", EP93XX_DMA_BASE + 0x0300, IRQ_EP93XX_DMAM2P9), }; static struct ep93xx_dma_platform_data ep93xx_dma_m2p_data = { .channels = ep93xx_dma_m2p_channels, .num_channels = ARRAY_SIZE(ep93xx_dma_m2p_channels), };
static irqreturn_t dma_dwc_interrupt(int irq, void *hsdev_instance) { int chan; u32 tfr_reg, err_reg; unsigned long flags; struct sata_dwc_device *hsdev = (struct sata_dwc_device *)hsdev_instance; struct ata_host *host = (struct ata_host *)hsdev->host; struct ata_port *ap; struct sata_dwc_device_port *hsdevp; u8 tag = 0; unsigned int port = 0; spin_lock_irqsave(&host->lock, flags); ap = host->ports[port]; hsdevp = HSDEVP_FROM_AP(ap); tag = ap->link.active_tag; tfr_reg = in_le32(&(host_pvt.sata_dma_regs->interrupt_status.tfr\ .low)); err_reg = in_le32(&(host_pvt.sata_dma_regs->interrupt_status.error\ .low)); dev_dbg(ap->dev, "eot=0x%08x err=0x%08x pending=%d active port=%d\n", tfr_reg, err_reg, hsdevp->dma_pending[tag], port); for (chan = 0; chan < DMA_NUM_CHANS; chan++) { if (tfr_reg & DMA_CHANNEL(chan)) { host_pvt.dma_interrupt_count++; sata_dwc_clear_dmacr(hsdevp, tag); if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_NONE) { dev_err(ap->dev, "DMA not pending eot=0x%08x " "err=0x%08x tag=0x%02x pending=%d\n", tfr_reg, err_reg, tag, hsdevp->dma_pending[tag]); } if ((host_pvt.dma_interrupt_count % 2) == 0) sata_dwc_dma_xfer_complete(ap, 1); out_le32(&(host_pvt.sata_dma_regs->interrupt_clear\ .tfr.low), DMA_CHANNEL(chan)); } if (err_reg & DMA_CHANNEL(chan)) { dev_err(ap->dev, "error interrupt err_reg=0x%08x\n", err_reg); out_le32(&(host_pvt.sata_dma_regs->interrupt_clear\ .error.low), DMA_CHANNEL(chan)); } } spin_unlock_irqrestore(&host->lock, flags); return IRQ_HANDLED; }
/* * Function: dma_dwc_interrupt * arguments: irq, dev_id, pt_regs * returns channel number if available else -1 * Interrupt Handler for DW AHB SATA DMA */ static irqreturn_t dma_dwc_interrupt(int irq, void *hsdev_instance) { int chan; u32 tfr_reg, err_reg; unsigned long flags; struct sata_dwc_device *hsdev = hsdev_instance; struct ata_host *host = (struct ata_host *)hsdev->host; struct ata_port *ap; struct sata_dwc_device_port *hsdevp; u8 tag = 0; unsigned int port = 0; spin_lock_irqsave(&host->lock, flags); ap = host->ports[port]; hsdevp = HSDEVP_FROM_AP(ap); tag = ap->link.active_tag; tfr_reg = in_le32(&(host_pvt.sata_dma_regs->interrupt_status.tfr\ .low)); err_reg = in_le32(&(host_pvt.sata_dma_regs->interrupt_status.error\ .low)); dev_dbg(ap->dev, "eot=0x%08x err=0x%08x pending=%d active port=%d\n", tfr_reg, err_reg, hsdevp->dma_pending[tag], port); chan = host_pvt.dma_channel; if (chan >= 0) { /* Check for end-of-transfer interrupt. */ if (tfr_reg & DMA_CHANNEL(chan)) { /* * Each DMA command produces 2 interrupts. Only * complete the command after both interrupts have been * seen. (See sata_dwc_isr()) */ host_pvt.dma_interrupt_count++; sata_dwc_clear_dmacr(hsdevp, tag); if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_NONE) { dev_err(ap->dev, "DMA not pending eot=0x%08x " "err=0x%08x tag=0x%02x pending=%d\n", tfr_reg, err_reg, tag, hsdevp->dma_pending[tag]); } if ((host_pvt.dma_interrupt_count % 2) == 0) sata_dwc_dma_xfer_complete(ap, 1); /* Clear the interrupt */ out_le32(&(host_pvt.sata_dma_regs->interrupt_clear\ .tfr.low), DMA_CHANNEL(chan)); } /* Check for error interrupt. */ if (err_reg & DMA_CHANNEL(chan)) { /* TODO Need error handler ! */ dev_err(ap->dev, "error interrupt err_reg=0x%08x\n", err_reg); /* Clear the interrupt. */ out_le32(&(host_pvt.sata_dma_regs->interrupt_clear\ .error.low), DMA_CHANNEL(chan)); } } spin_unlock_irqrestore(&host->lock, flags); return IRQ_HANDLED; }