📄 ep93xx_irda.c
字号:
}#endif /* MODULE *//* * ep93xx_get_PLL_frequency * * Given a value for ClkSet1 or ClkSet2, calculate the PLL1 or PLL2 frequency. */static unsigned long ep93xx_get_PLL_frequency( unsigned long ulCLKSET ){ ulong ulX1FBD, ulX2FBD, ulX2IPD, ulPS, ulPLL_Freq; ulPS = (ulCLKSET & SYSCON_CLKSET1_PLL1_PS_MASK) >> SYSCON_CLKSET1_PLL1_PS_SHIFT; ulX1FBD = (ulCLKSET & SYSCON_CLKSET1_PLL1_X1FBD1_MASK) >> SYSCON_CLKSET1_PLL1_X1FBD1_SHIFT; ulX2FBD = (ulCLKSET & SYSCON_CLKSET1_PLL1_X2FBD2_MASK) >> SYSCON_CLKSET1_PLL1_X2FBD2_SHIFT; ulX2IPD = (ulCLKSET & SYSCON_CLKSET1_PLL1_X2IPD_MASK) >> SYSCON_CLKSET1_PLL1_X2IPD_SHIFT; /* * This may be off by a very small fraction of a percent. */ ulPLL_Freq = (((0x00e10000 * (ulX1FBD+1)) / (ulX2IPD+1)) * (ulX2FBD+1)) >> ulPS; return ulPLL_Freq;}/* * Function ep93xx_irda_init_9312 (chip) * * Identify the EP9312 SOC's IrDA capabilities * as it is currently configured. */static int ep93xx_irda_init_9312(ep93xx_chip_t *chip) { unsigned int uiMIRDiv = 0, uiUSBDiv = 0; unsigned long ulPLL1, ulPLL2; #define MIRCLK 18432000 /* * Identify the what modes the clocks will support. * - SIR will always be supported. * - MIR depends on processor speed. * - FIR should be supported. */ /* * Dedicated clocks for UARTs, which is what SIR uses. */ g_iClkSupport = CLK_SIR; /* * Get the frequency of the two PLLs. */ ulPLL1 = ep93xx_get_PLL_frequency( inl(SYSCON_CLKSET1) ); ulPLL2 = ep93xx_get_PLL_frequency( inl(SYSCON_CLKSET2) ); /* * MIR: Check PLL1 clock for one of our supported * settings and setup MIR clock, if the processor speed is * MIR friendly. * * 0xC000 sets MIR_CLK div on, internal clock * source and PLL1 as the source. * * Need to find pre-clk divisor(2,2.5,3) and 7bit divisor. */ if(!((ulPLL1 / 3) % MIRCLK) && (((ulPLL1 / 3) / MIRCLK) < 0x7f)) { uiMIRDiv = (0x3 << 9) | (unsigned int)((ulPLL1 / 3) / MIRCLK); } else if(!((unsigned long)((ulPLL1 * 5) / 2) % MIRCLK) && ((((ulPLL1 * 5) / 2) / MIRCLK) < 0x7f)) { uiMIRDiv = (0x2 << 9) | (unsigned int)(((ulPLL1 * 5) / 2) / MIRCLK); } else if(!((ulPLL1 / 2) % MIRCLK) && (((ulPLL1 / 2) / MIRCLK) < 0x7f)) { uiMIRDiv = (0x1 << 9) | (unsigned int)((ulPLL1 / 2) / MIRCLK); } if(uiMIRDiv > 0) { /* * Setup the MIR clock register and flag the * driver to report MIR support. */ uiMIRDiv |= 0xC000; outl(uiMIRDiv, SYSCON_MIRDIV); g_iClkSupport = CLK_MIR; } /* * FIR: Check PLL2 and make sure it's giving * a CLK that the USBDiv can convert to 48mhz */ uiUSBDiv = (inl(SYSCON_CLKSET2) >> 28) + 1; if((uiUSBDiv == 0) || (uiUSBDiv == 16)) { uiUSBDiv = 1; } if((ulPLL2 / uiUSBDiv) == 48000000) { g_iClkSupport |= CLK_FIR; } return(0);}/* * Function ep93xx_irda_setup (info) * * Attempts to take ownership of UART2, configures for SIR * usage (lowest speed IrDA). * * Returns non-negative on success. */static int ep93xx_irda_setup(ep93xx_chip_t *info){ unsigned int uiRegVal; char *cptrSupport = NULL; EP93XX_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__); /* * Set UART2 to be an IrDA interface. */ uiRegVal = inl(SYSCON_DEVCFG); SysconSetLocked(SYSCON_DEVCFG, (uiRegVal | (SYSCON_DEVCFG_IonU2 | SYSCON_DEVCFG_U2EN))); uiRegVal = inl(SYSCON_DEVCFG); /* * Set the pulse width. */ outl(3, UART2ILPR); /* * Set SIREN bit in UART2 - this enables the SIR encoder/decoder. */ uiRegVal = inl(UART2CR); outl((uiRegVal | (U2CR_SIR|U2CR_UART)), UART2CR); uiRegVal = 0; /* * Enable Ir in SIR mode. */ outl(IrENABLE_SIR, IrEnable); uiRegVal = inl(IrEnable); switch(g_iClkSupport & (CLK_SIR|CLK_MIR|CLK_FIR)) { case 3:cptrSupport = SIRMIR_str; break; case 5:cptrSupport = SIRFIR_str; break; case 7: cptrSupport = SIRMFIR_str; break; default:cptrSupport = SIR_str; break; } MESSAGE("%s, driver loaded supporting %s (Cirrus Logic, Inc.).\n", driver_name, cptrSupport); EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__); return(0);}/* * Function ep93xx_irda_interrupt (irq, dev_id, regs) * * An interrupt from the chip has arrived. Time to do some work. * */static void ep93xx_irda_interrupt(int irq, void *dev_id, struct pt_regs *regs){ struct net_device *dev = (struct net_device *) dev_id; struct ep93xx_irda_cb *self; EP93XX_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__); if(!dev) { WARNING("%s: irq %d for unknown device.\n", driver_name, irq); return; } EP93XX_DEBUG(2, "%s(), for IRQ %d\n", __FUNCTION__, irq); self = (struct ep93xx_irda_cb *) dev->priv; spin_lock(&self->lock); /* * Dispatch interrupt handler for the IRQ signaled. */ if(irq == IRQ_IRDA) { ep93xx_irda_mfir_interrupt(irq, self, regs); } else if(irq == IRQ_UART2) { ep93xx_irda_sir_interrupt(irq, self, regs); } else { WARNING("%s: IRQ%d signaled but not recognized\n", driver_name, irq); } spin_unlock(&self->lock); EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__);}/* * Function ep93xx_irda_mfir_interrupt(irq, struct ep93xx_irda_cb *self, regs) * * Handle MIR/FIR interrupt. * */static void ep93xx_irda_mfir_interrupt(int irq, struct ep93xx_irda_cb *self, struct pt_regs *regs){ __u8 irqID; int iLen, iVal, iWriteBack, iStatus; EP93XX_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__); /* * Identify the IRQ signal for MIR/FIR. Branch on speed to * determine which register to check. */ if(self->speed < 4000000) { /* * Should be a MIR interrupt. */ irqID = inl(MIIR); } else { /* * Should be a FIR interrupt. */ irqID = inl(FIIR); } /* * Disable Interrupts */ SetInterrupts(self, FALSE); if(!irqID) { EP93XX_DEBUG(1,"MFIR IRQ signalled, but no flag set? (speed = %d)\n", self->speed); } /* * Determine why the interrupt (TX/RX?). */ if(irqID & (MFIIR_RXFL|MFIIR_RXIL|MFIIR_RXFC|MFIIR_RXFS)) { /* * Service the Rx related interrupt. */ /* * Clear our write back value variable. */ iWriteBack = 0; if(irqID & MFIIR_RXFL) { EP93XX_DEBUG(1, "%s(), ******* Frame lost (RX) *******\n", __FUNCTION__); /* * Receive Frame Lost. A ROR occurred at the start of a new frame, * before any data for the frame could be placed into the rx FIFO. * The last entry in the FIFO already contains a valid EOF bit from * the previous frame and a FIFO overrun has occurred. The frame is * lost. */ iWriteBack |= MFISR_RXFL; } if(irqID & MFIIR_RXIL) { EP93XX_DEBUG(1, "%s(), ******* Info buffer lost (RX) *******\n", __FUNCTION__); /* * Receive Information Buffer Lost. The last data for the frame * has been read from the RX FIFO and the RFC bit is still set * from the previous EOF. The IrRIB register data for the previous * frame has therefore been lost. * */ iWriteBack |= MFISR_RXIL; } if(irqID & MFIIR_RXFC) { EP93XX_DEBUG(1, "%s(), ******* Frame complete (RX) *******\n", __FUNCTION__); /* * Received Frame Complete. The last data for frame has been * read from the FIFO. IrRIB now has IrFlag and byte count. * */ iVal = inw(IrRIB); iLen = (iVal&IrRIB_ByteCt) >> 4; iStatus = (iVal & (IrRIB_BUFFE | IrRIB_BUFOR | IrRIB_BUFCRCERR | IrRIB_BUFRXABORT)); EP93XX_DEBUG(1, "%s(), RX Length = 0x%.2x\n", __FUNCTION__, iLen); EP93XX_DEBUG(1, "%s(), RX Status = 0x%.2x (IrRIB = 0x%x)\n", __FUNCTION__, iStatus, iVal); /* * Check for errors - the lower 4 bits signal errors. However, * we ignore Buffered Framing errors, so only check the lower * 3 bits. */ if((iStatus & 0x7) ||(iLen==0)) { EP93XX_DEBUG(1, "%s(), ************ RX Errors *********** \n", __FUNCTION__); /* * If there was errors, skip the frame. */ self->stats.rx_errors++; self->rx_buff.data += iLen; if(iStatus & IrRIB_BUFRXABORT) { self->stats.rx_frame_errors++; EP93XX_DEBUG(1, "%s(), ************* ABORT Condition ************ \n", __FUNCTION__); } if(iStatus & IrRIB_BUFFE) { self->stats.rx_frame_errors++; EP93XX_DEBUG(1, "%s(), ************* FRAME Errors ************ \n", __FUNCTION__); } if(iStatus & IrRIB_BUFCRCERR) { self->stats.rx_crc_errors++; EP93XX_DEBUG(1, "%s(), ************* CRC Errors ************ \n", __FUNCTION__); } if(iStatus & IrRIB_BUFOR) { self->stats.rx_frame_errors++; EP93XX_DEBUG(1, "%s(), *********** Overran DMA buffer ********** \n", __FUNCTION__); } if(iLen == 0) { self->stats.rx_frame_errors++; EP93XX_DEBUG(1, "%s(), ********* Receive Frame Size = 0 ******** \n", __FUNCTION__); } } else { /* * Looks okay, call handler. */ ep93xx_irda_dma_receive_complete(self, iLen); } } if(irqID & MFIIR_RXFS) { EP93XX_DEBUG(1, "%s(), ******* Buffer SR (RX) *******\n", __FUNCTION__); /* * Receive Buffer Service Request (RO). Buffer is not empty and * the receiver is enabled, DMA service request signaled. * */ } if(self->speed < 4000000) { outb(iWriteBack, MISR); } else { outb(iWriteBack, FISR); } } if(irqID & (MFIIR_TXABORT|MFIIR_TXFC|MFIIR_TXFS)) { /* * Service the Tx related interrupt. */ if(irqID & MFIIR_TXABORT) { EP93XX_DEBUG(1, "%s(), ******* Frame abort (TX) *******\n", __FUNCTION__); /* * Transmit Frame Abort. Transmitted frame has been terminated * with an abort. * */ } if(irqID & MFIIR_TXFC) { EP93XX_DEBUG(1, "%s(), ******* Frame complete (TX) *******\n", __FUNCTION__); /* * Transmitted Frame Complete. The frame has been transmitted and * terminated (possibly with an error). */ if(ep93xx_irda_dma_xmit_complete(self, irqID)) { /* * Prepare for receive */ ep93xx_irda_dma_receive(self); } } if(irqID & MFIIR_TXFS) { EP93XX_DEBUG(1, "%s(), ******* Buffer SR (TX) *******\n", __FUNCTION__); /* * Transmit Buffer Service Request (RO). TX buffer is not full and * transmit is enabled, DMA service is signaled. */ } } /* * Restore Interupt */ SetInterrupts(self, TRUE); EP93XX_DEBUG(1, "ISR(), IrEnable = 0x%x, IrCtrl = 0x%x, IrFlag = 0x%x, FIMR = 0x%x\n", inb(IrEnable), inb(IrCtrl), inw(IrFlag), inb(FIMR)); EP93XX_DEBUG(2, "%s(), ----------------- End ---------------\n", __FUNCTION__);}/* * Function ep93xx_irda_sir_interrupt(irq, self, eir) * * Handle SIR interrupt. * */static void ep93xx_irda_sir_interrupt(int irq, struct ep93xx_irda_cb *self, struct pt_regs *regs){ int iIrq, iLSR, iVal; EP93XX_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__); iIrq = (char)inl(UART2IIR); if(iIrq) { /* * Clear interrupt flags */ outl(0, UART2ICR); EP93XX_DEBUG(2, "%s(), SIR IRQ (flag=0x%x)\n", __FUNCTION__, iIrq); if(iIrq & U2IICR_RXTOIRQ) { EP93XX_DEBUG(1, "%s(), Receive Timeout IRQ\n", __FUNCTION__); /* * Check RSR for OE, BE & FE error conditions * (and clear flags). */ iLSR = inl(UART2RSR); outl(0, UART2ECR); if(iLSR & U2RSR_OvnErr) { EP93XX_DEBUG(1, "%s(), Overrun Error\n", __FUNCTION__); /* * Make certain we service the RX FIFO. */ iIrq |= U2IICR_RXIRQ; } else if(iLSR & U2RSR_BrkErr) { EP93XX_DEBUG(1, "%s(), Break Error\n", __FUNCTION__); /* * Clear the bad byte. */ inb(UART2DR); } else if(iLSR & U2RSR_FrmErr) { EP93XX_DEBUG(1, "%s(), Frame Error\n", __FUNCTION__); /* * Clear the bad byte. */ inb(UART2DR); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -