⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ep93xx_irda.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 5 页
字号:
}#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 + -