static irqreturn_t str8100_i2s_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs) { u32 interrupt_status; DEBUG_PRINT("%s: this_irq=%d, I2S_INTERRUPT_STATUS_REG=0x%.8x\n",__FUNCTION__,this_irq,I2S_INTERRUPT_STATUS_REG); HAL_INTC_DISABLE_INTERRUPT_SOURCE(this_irq); //todo: interrupt_status = I2S_INTERRUPT_STATUS_REG; I2S_RIGHT_TRANSMIT_DATA_REG=0; if ((interrupt_status & (I2S_RXBF_R_FULL_FLAG | I2S_RXBF_L_FULL_FLAG | I2S_TXBF_R_EMPTY_FLAG | I2S_TXBF_L_EMPTY_FLAG))){ printk("%s: Error! wrong i2s empty/full flag\n",__FUNCTION__); } if ((interrupt_status & (I2S_RXBF_R_OR_FLAG | I2S_RXBF_L_OR_FLAG |I2S_TXBF_R_UR_FLAG | I2S_TXBF_L_UR_FLAG))){ // Clear I2S interrupt status i2s_err_lur++; if(i2s_err_lur>10) I2S_INTERRUPT_ENABLE_REG &= ~(I2S_TXBF_L_UR_FLAG); // HAL_I2S_DISABLE_I2S(); printk("%s: Left Channel Tx Underrun!, interrupt_status=%.8x,i2s_err_lur=%d\n",__FUNCTION__,interrupt_status,i2s_err_lur); } I2S_INTERRUPT_STATUS_REG &= 0xf0; HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(this_irq); HAL_INTC_ENABLE_INTERRUPT_SOURCE(this_irq); return IRQ_HANDLED; }
static irqreturn_t str8100_gpio_irq_handler(int this_irq, void *dev_id/*, struct pt_regs *regs*/) { unsigned int volatile statusA,statusB; int i; if(debug) printk("%s: this_irq=%d\n",__FUNCTION__,this_irq); HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_GPIO_EXTERNAL_INT_BIT_INDEX); HAL_GPIOA_READ_INTERRUPT_MASKED_STATUS(statusA); HAL_GPIOB_READ_INTERRUPT_MASKED_STATUS(statusB); //printk("%s: %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x \n",__FUNCTION__,GPIOA_DATA_OUTPUT_REG,GPIOA_DATA_INPUT_REG,GPIOA_DIRECTION_REG,GPIOA_INTERRUPT_ENABLE_REG,GPIOA_INTERRUPT_RAW_STATUS_REG,GPIOA_INTERRUPT_MASKED_STATUS_REG,GPIOA_INTERRUPT_MASKED_STATUS_REG,GPIOA_INTERRUPT_MASK_REG,GPIOA_INTERRUPT_TRIGGER_METHOD_REG,GPIOA_INTERRUPT_TRIGGER_BOTH_EDGES_REG,GPIOA_INTERRUPT_TRIGGER_TYPE_REG,GPIOA_BOUNCE_ENABLE_REG,GPIOA_BOUNCE_CLOCK_PRESCALE_REG); for (i = 0; i < 32; i++) { if (statusA & (1 << i)){ if(debug) printk("%s: GPIOA Int %d\n",__FUNCTION__,i); if(gpioA_irq_handler){ gpioA_irq_handler(i,dev_id,NULL/*regs*/); } } if (statusB & (1 << i)){ if(debug) printk("%s: GPIOB Int %d\n",__FUNCTION__,i); if(gpioB_irq_handler){ gpioB_irq_handler(i,dev_id,NULL/*regs*/); } } } HAL_GPIOA_CLEAR_INTERRUPT(statusA); HAL_GPIOB_CLEAR_INTERRUPT(statusB); HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GPIO_EXTERNAL_INT_BIT_INDEX); HAL_INTC_ENABLE_INTERRUPT_SOURCE(INTC_GPIO_EXTERNAL_INT_BIT_INDEX); return IRQ_HANDLED; }
static irqreturn_t str8100_ext_irq_handler(int this_irq, void *dev_id/*, struct pt_regs *regs*/) { if(debug) printk("%s: this_irq=%d\n",__FUNCTION__,this_irq); HAL_INTC_DISABLE_INTERRUPT_SOURCE(this_irq); if(ext_irq_handler){ ext_irq_handler(this_irq,dev_id,NULL/*regs*/); } HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(this_irq); HAL_INTC_ENABLE_INTERRUPT_SOURCE(this_irq); return IRQ_HANDLED; }
static irqreturn_t str8100_ext_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs) { void (*fnptr)(void)=NULL; printk("%s: this_irq=%d\n",__FUNCTION__,this_irq); HAL_INTC_DISABLE_INTERRUPT_SOURCE(this_irq); if(mode==1) while(1); else fnptr(); HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(this_irq); HAL_INTC_ENABLE_INTERRUPT_SOURCE(this_irq); return IRQ_HANDLED; }
static irqreturn_t str8100_dma_tc_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs) { u32 dma_tc_status,tot_size; u32 len; //printk("%s: this_irq=%d\n",__FUNCTION__,this_irq); HAL_INTC_DISABLE_INTERRUPT_SOURCE(this_irq); //todo: HAL_DMAC_READ_TERMINAL_COUNT_INTERRUPT_STATUS(dma_tc_status); printk("%s: this_irq=%d, dma_tc_status=%.8x\n",__FUNCTION__,this_irq,dma_tc_status); #ifdef I2S_WM8772_DMAC_LLP_RING_TEST u32 i; /* * For LLP ring test, the TC interrupt shoule not happen!! */ for(i=0;i<8;i++) if (dma_tc_status & DMAC_CH_ID(i)){ HAL_DMAC_CLEAR_TERMINAL_COUNT_INTERRUPT_STATUS(DMAC_CH_ID(i)); printk("%s: channel %d: Error!! there should be no tc irq happened!!\n",__FUNCTION__,i); } #else /* * For this case, it's recommended to set I2S_WM8772_DMAC_LLP_NUM = 1 */ /* * For DMA's Tx for I2S Left Channel */ if (dma_tc_status & DMAC_CH_ID(i2s_wm8772_dma_left_tx_channel)) { HAL_DMAC_DISABLE_CHANNEL(i2s_wm8772_dma_left_tx_channel); HAL_DMAC_CLEAR_TERMINAL_COUNT_INTERRUPT_STATUS(DMAC_CH_ID(i2s_wm8772_dma_left_tx_channel)); /* * Re-initialize DMA's channel for Left_Tx */ DMAC_CH_SRC_ADDR(i2s_wm8772_dma_left_tx_channel) = i2s_left_tx_channel_dma_llp_desc[0].SrcAddr; DMAC_CH_DST_ADDR(i2s_wm8772_dma_left_tx_channel) = i2s_left_tx_channel_dma_llp_desc[0].DstAddr; /* * Note this macro DMAC_CH_SIZE is to configure TOT_SIZE field which is the total transfer * number of source transfer width! */ tot_size = Hal_Dmac_Get_Channel_Transfer_Unit_Number(I2S_WM8772_BUFFER_SIZE * 4, DMAC_CH_SRC_WIDTH_32_BITS); DMAC_CH_SIZE(i2s_wm8772_dma_left_tx_channel) = tot_size & 0x0FFF; HAL_DMAC_ENABLE_CHANNEL(i2s_wm8772_dma_left_tx_channel); } /* * For DMA's Tx for I2S Right Channel */ if (dma_tc_status & DMAC_CH_ID(i2s_wm8772_dma_right_tx_channel)) { HAL_DMAC_DISABLE_CHANNEL(i2s_wm8772_dma_right_tx_channel); HAL_DMAC_CLEAR_TERMINAL_COUNT_INTERRUPT_STATUS(DMAC_CH_ID(i2s_wm8772_dma_right_tx_channel)); /* * Re-initialize DMA's channel for Right_Tx */ DMAC_CH_SRC_ADDR(i2s_wm8772_dma_right_tx_channel) = i2s_right_tx_channel_dma_llp_desc[0].SrcAddr; DMAC_CH_DST_ADDR(i2s_wm8772_dma_right_tx_channel) = i2s_right_tx_channel_dma_llp_desc[0].DstAddr; /* * Note this macro DMAC_CH_SIZE is to configure TOT_SIZE field which is the total transfer * number of source transfer width! */ tot_size = Hal_Dmac_Get_Channel_Transfer_Unit_Number(I2S_WM8772_BUFFER_SIZE * 4, DMAC_CH_SRC_WIDTH_32_BITS); DMAC_CH_SIZE(i2s_wm8772_dma_right_tx_channel) = tot_size & 0x0FFF; HAL_DMAC_ENABLE_CHANNEL(i2s_wm8772_dma_right_tx_channel); } /* * For DMA's Rx for I2S Left Channel */ if (dma_tc_status & DMAC_CH_ID(i2s_wm8772_dma_left_rx_channel)) { HAL_DMAC_DISABLE_CHANNEL(i2s_wm8772_dma_left_rx_channel); HAL_DMAC_CLEAR_TERMINAL_COUNT_INTERRUPT_STATUS(DMAC_CH_ID(i2s_wm8772_dma_left_rx_channel)); /* * Re-initialize DMA's channel for Left_Rx */ DMAC_CH_SRC_ADDR(i2s_wm8772_dma_left_rx_channel) = i2s_left_rx_channel_dma_llp_desc[0].SrcAddr; DMAC_CH_DST_ADDR(i2s_wm8772_dma_left_rx_channel) = i2s_left_rx_channel_dma_llp_desc[0].DstAddr; /* * Note this macro DMAC_CH_SIZE is to configure TOT_SIZE field which is the total transfer * number of source transfer width! */ tot_size = Hal_Dmac_Get_Channel_Transfer_Unit_Number(I2S_WM8772_BUFFER_SIZE * 4, DMAC_CH_SRC_WIDTH_32_BITS); DMAC_CH_SIZE(i2s_wm8772_dma_left_rx_channel) = tot_size & 0x0FFF; HAL_DMAC_ENABLE_CHANNEL(i2s_wm8772_dma_left_rx_channel); } /* * For DMA's Rx for I2S Right Channel */ if (dma_tc_status & DMAC_CH_ID(i2s_wm8772_dma_right_rx_channel)) { HAL_DMAC_DISABLE_CHANNEL(i2s_wm8772_dma_right_rx_channel); HAL_DMAC_CLEAR_TERMINAL_COUNT_INTERRUPT_STATUS(DMAC_CH_ID(i2s_wm8772_dma_right_rx_channel)); /* * Re-initialize DMA's channel for Right_Rx */ DMAC_CH_SRC_ADDR(i2s_wm8772_dma_right_rx_channel) = i2s_right_rx_channel_dma_llp_desc[0].SrcAddr; DMAC_CH_DST_ADDR(i2s_wm8772_dma_right_rx_channel) = i2s_right_rx_channel_dma_llp_desc[0].DstAddr; /* * Note this macro DMAC_CH_SIZE is to configure TOT_SIZE field which is the total transfer * number of source transfer width! */ tot_size = Hal_Dmac_Get_Channel_Transfer_Unit_Number(I2S_WM8772_BUFFER_SIZE * 4, DMAC_CH_SRC_WIDTH_32_BITS); DMAC_CH_SIZE(i2s_wm8772_dma_right_rx_channel) = tot_size & 0x0FFF; HAL_DMAC_ENABLE_CHANNEL(i2s_wm8772_dma_right_rx_channel); } #endif HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(this_irq); HAL_INTC_ENABLE_INTERRUPT_SOURCE(this_irq); return IRQ_HANDLED; }