cy7c67200_300_hcd.c

来自「linux嵌入式课程实践中的一个关于声卡驱动程序 。」· C语言 代码 · 共 2,356 行 · 第 1/4 页

C
2,356
字号
    if( hci == 0 )    {        return;    }    sh_schedule_trans (cy_priv, SIE1);}/******************************************************************/void hcd_irq_mb_in(cy_priv_t *cy_priv){    // currently not used}/******************************************************************/void hcd_irq_mb_out(unsigned int message, int sie, cy_priv_t *cy_priv){    hci_t *hci = cy_priv->hci;    sie_t * sie_struct = &hci->sie[sie];    if( hci == NULL )    {        return;    }	if (message & HUSB_TDListDone)	{        // cy_dbg(":  TD_LIST_DONE_MSG_ID RECEIVED.");                            /* HOST: Lyberty has finished transfer of the TD */                /* Check the status of the TDs */        sh_td_list_check_stat (cy_priv, sie);  		sie_struct->td_active = FALSE;        /* shedule the next set of TDs */        sh_schedule_trans (cy_priv, sie);                }}/******************************************************************/void hcd_irq_resume1(cy_priv_t *cy_priv){    unsigned short usb_stats;    hci_t *hci = cy_priv->hci;    unsigned short usb_stat_sie = 0;    otg_t *otg = cy_priv->otg;    if( hci == 0 )    {        return;    }    HWTrace (0x2090);    /* Read the USB Interrupt Status Register for SIE 1*/    lcd_read_reg(SIE1_INT_STATUS_REG, &usb_stats, cy_priv);	cy_dbg("SIE1_INT_STATUS_REG = 0x%X", usb_stats);    if (otg != NULL)    {        /* Are we in the USB OTG States to detect HNP Accept? */        if (usb_stats & A_CHG_IRQ_FLG)        {            HWTrace (0x2091);            if( reset_in_progress[PORT0] != 0 )            {                usb_stat_sie =  A_CHG_IRQ_FLG | A_SE0_STAT | A_WAKE_IRQ_FLG |                                  B_CHG_IRQ_FLG | B_SE0_STAT | B_WAKE_IRQ_FLG;                lcd_write_reg(HOST1_STAT_REG, usb_stat_sie, cy_priv);                 return;            }            /* determine if the HNP has been accepted by the device */                        if (usb_stats & A_SE0_STAT)            {                HWTrace (0x209A);                otg->b_conn = FALSE;                otg->a_conn = FALSE;                //cy_err("ACON4:0");	            usb_stat_sie |= A_SE0_STAT;             }            else            {                if(otg->id == A_DEV)                {                    otg->b_conn = TRUE;                }                else                {                    otg->a_conn = TRUE;                    //cy_err("ACON5:1");                }            }                         if (!otg->a_vbus_vld && otg->state == a_idle)            {                HWTrace (0x2092);                /* OTG SRP Functionality:                 * SRP request has been detected.                 */                                 otg->b_conn = FALSE;                otg->a_srp_det = TRUE;                               otg->a_bus_req = TRUE;                           }            else            {                otg->a_srp_det = FALSE;            }            usb_stat_sie |= A_CHG_IRQ_FLG;         }                /* Detect Remote Wakeup */        if (usb_stats & A_WAKE_IRQ_FLG)        {            HWTrace (0x2096);            /* Detected Remote Wakeup on port A */            /* Set the HCD to be active and start SOF */                        otg->b_bus_resume = TRUE;            usb_stat_sie |= A_WAKE_IRQ_FLG;         }        update_otg_state(otg);		/* Clear the B port interrupts just in case */        usb_stat_sie |= B_SE0_STAT | B_CHG_IRQ_FLG | B_WAKE_IRQ_FLG;    }    else    {        if (usb_stats & A_CHG_IRQ_FLG)        {			if (reset_in_progress[PORT0] == 0)			{	            HWTrace (0x20C0);	            /* USB Insert/Remove Interrupt on port B*/	            /* qualify with the USB Reset */	            /* Determine if a device has connected or disconnected by	             * reading the USB Reset bit of the USB status register */	            if (hci->valid_host_port[PORT0] != 1)	            {	                cy_err("invalid host port 0");	            }	            else	            {	                if (usb_stats & A_SE0_STAT)	                {						cy_err("Device removed on PORT0");	                    HWTrace (0x20C1);	                    /* Device has been disconnected */	                    handle_device_removal(cy_priv, PORT0);	                }	                else	                {						cy_err("Device inserted on PORT0");	                    HWTrace (0x20C2);	                    /* Device has been connected */	                    handle_device_insertion(cy_priv, PORT0);	                }	            }			}		    usb_stat_sie |= A_CHG_IRQ_FLG;        }        if (usb_stats & B_CHG_IRQ_FLG)		{                	if (reset_in_progress[PORT1] == 0)        	{	            HWTrace (0x2093);	            /* USB Insert/Remove Interrupt on port B*/	            /* qualify with the USB Reset */	            /* Determine if a device has connected or disconnected by	             * reading the USB Reset bit of the USB status register */	            	            if (hci->valid_host_port[PORT1] != 1)	            {               	 	cy_err("invalid host port 1");	            }	            else	            {	                if (usb_stats & B_SE0_STAT)	                {						cy_err("Device removed on PORT1");	                    HWTrace (0x2094);	                    /* Device has been disconnected */	                    handle_device_removal(cy_priv, PORT1);	                }	                else	                {						cy_err("Device inserted on PORT1");	                    HWTrace (0x2095);	                    /* Device has been connected */	                    handle_device_insertion(cy_priv, PORT1);	                }	            }			}		    usb_stat_sie |= B_CHG_IRQ_FLG;        }        if (usb_stats & A_WAKE_IRQ_FLG)        {            HWTrace (0x2010);                     /* Detected Remote Wakeup on port A */            handle_remote_wakeup(cy_priv, PORT0);					    usb_stat_sie |= A_WAKE_IRQ_FLG;        }        if (usb_stats & B_WAKE_IRQ_FLG)        {            HWTrace (0x2011);            /* Detected Remote Wakeup on port B */            handle_remote_wakeup(cy_priv, PORT1);		    usb_stat_sie |= B_WAKE_IRQ_FLG;        }    }    /* Detect Remote Wakeup */                   HWTrace (0x2099);    /* clear the associated interrupt(s) */    lcd_write_reg(HOST1_STAT_REG, usb_stat_sie, cy_priv); }/******************************************************************/void hcd_irq_resume2(cy_priv_t *cy_priv){    unsigned short usb_stats;    hci_t *hci = cy_priv->hci;    unsigned short usb_stat_sie = 0;    otg_t *otg = cy_priv->otg;    if( hci == 0 )    {        return;    }    HWTrace (0x2080);    /* Read the USB Interrupt Status Register for SIE 1*/    lcd_read_reg(HOST2_STAT_REG, &usb_stats, cy_priv);	cy_dbg("HOST2_STAT_REG = 0x%X", usb_stats);    if (usb_stats & A_CHG_IRQ_FLG)	{    	if (reset_in_progress[PORT2] == 0)    	{	        HWTrace (0x2081);	        /* USB Insert/Remove Interrupt on port A*/	        	        /* Determine if a device has connected or disconnected by	         * reading the USB Reset bit of the USB status register */	        if (hci->valid_host_port[PORT2] != 1)	        {	            cy_err("invalid host port 2");	        }	        else	        {	            if (usb_stats & A_SE0_STAT)	            {					cy_err("Device removed on PORT2");	                HWTrace (0x2082);	                /* device has been removed */	                handle_device_removal(cy_priv, PORT2);	                	            }	            else	            {					cy_err("Device inserted on PORT2");	                HWTrace (0x2083);	                /* device has been inserted */	                handle_device_insertion(cy_priv, PORT2);	            } 	        }		}	    usb_stat_sie |= A_CHG_IRQ_FLG;    }    if (usb_stats & B_CHG_IRQ_FLG)	{    	if (reset_in_progress[PORT3] == 0)	    {	        /* USB Insert/Remove Interrupt on port B*/	        /* qualify with the USB Reset */	        /* Determine if a device has connected or disconnected by	         * reading the USB Reset bit of the USB status register */	        HWTrace (0x2084);	        if (hci->valid_host_port[PORT3] != 1)	        {	            cy_err("invalid host port 3");	        }	        else	        {	            if (usb_stats & B_SE0_STAT)	            {					cy_err("Device removed on PORT3");	                HWTrace (0x2085);	                /* device has been removed */	                handle_device_removal(cy_priv, PORT3);	            }	            else	            {					cy_err("Device inserted on PORT3");	                HWTrace (0x2086);	                /* Device has been connected */	                handle_device_insertion(cy_priv, PORT3);	            }	        }		}	    usb_stat_sie |= B_CHG_IRQ_FLG;    }    /* Detect Remote Wakeup */    if (usb_stats & A_WAKE_IRQ_FLG)    {        HWTrace (0x2087);        /* Detected Remote Wakeup on port A */        handle_remote_wakeup(cy_priv, PORT2);	    usb_stat_sie |= A_WAKE_IRQ_FLG;    }    if (usb_stats & B_WAKE_IRQ_FLG)    {        HWTrace (0x2088);        /* Detected Remote Wakeup on port B */        handle_remote_wakeup(cy_priv, PORT3);	    usb_stat_sie |= B_WAKE_IRQ_FLG;    }    /* clear the associated interrupt */    lcd_write_reg(HOST2_STAT_REG, usb_stat_sie, cy_priv); }    /*****************************************************************/void hcd_irq_enable_host_periph_ints(cy_priv_t *cy_priv){    hci_t *hci = cy_priv->hci;    if( hci == 0 )    {        return;    }	/* enable the interrupt: 	 * At this point, the host may become a peripheral or vise versa	 * It is necessary to setup Interrupt Enable based on the "hostship" 	 * of the current SIE.	 */    cy_dbg("hcd_irq_enable_host_periph_ints enter: cy_priv = %p", cy_priv);	if (is_host_enable(hci, PORT0))	{		HWTrace (0x20A0);		lcd_write_reg(SIE1_INT_EN_REG, DFLT_HOST1_IRQ_ENBL, cy_priv);	}	else	{		lcd_write_reg(SIE1_INT_EN_REG, DFLT_PERIPHERAL1_IRQ_ENBL, cy_priv);	}	if (is_host_enable(hci, PORT2))	{	 	HWTrace (0x20B0);		lcd_write_reg(SIE2_INT_EN_REG, DFLT_HOST2_IRQ_ENBL, cy_priv);	}	else	{		lcd_write_reg(SIE2_INT_EN_REG, DFLT_PERIPHERAL2_IRQ_ENBL, cy_priv);	}}/****************************************************************** * THE FOLLOWING FUNCTIONS ARE BOARD SPECIFIC *  * MODIFIED FOR YOUR OWN BOARD!! *  *******************************************************************/ /***************************************************************** * * Function Name: cy67x00_get_hw_config * * This function is board specific.  It reads the DIP switch from * Lyberty to determine the HW operating mode * * Input: n/a * * Return:	 *			DIP switch value * *****************************************************************/static int cy67x00_get_hw_config (){    unsigned short val;//    val = inw(SBC_DIP_REG);	return val;}/***************************************************************** * * Function Name: cy67x00_get_current_frame_number * * This function is board specific.  It reads the frame number * from Lyberty for the specified sie. * * Input:  * 			cy_priv 	cy67x00 private data  *			sie			sie number * * Return:	 *			Current Frame Number * *****************************************************************/int cy67x00_get_current_frame_number (cy_priv_t * cy_priv, int port_num){    unsigned short temp_val = 0;	if ((port_num == PORT0) || (port_num == PORT1))		{		lcd_read_reg(SIE1_USB_FRAME_NO, &temp_val, cy_priv);		}	else		{		lcd_read_reg(SIE2_USB_FRAME_NO, &temp_val, cy_priv);		}	temp_val &= HOST_FRAME_NUM;	if (temp_val == 0)		temp_val = HOST_FRAME_NUM;	else		temp_val -= 1;	HWTrace(0x1111);	HWData(temp_val);	return temp_val;}/***************************************************************** * * Function Name: cy67x00_get_next_frame_number * * This function is board specific.  It reads the frame number * from Lyberty for the specified sie. * * Input:  * 			cy_priv 	cy67x00 private data  *			sie			sie number * * Return:	 *			Next Frame Number * *****************************************************************/int cy67x00_get_next_frame_number (cy_priv_t * cy_priv, int port_num){    unsigned short temp_val = 0;	if ((port_num == PORT0) || (port_num == PORT1))		{		lcd_read_reg(SIE1_USB_FRAME_NO, &temp_val, cy_priv);		}	else		{		lcd_read_reg(SIE2_USB_FRAME_NO, &temp_val, cy_priv);		}	temp_val &= HOST_FRAME_NUM;	HWTrace(0x1112);	HWData(temp_val);	return temp_val;}/***************************************************************** * * Function Name: init_irq * * This function is board specific.  It sets up the interrupt to  * be an edge trigger and trigger on the rising edge   * * Input: none  * * Return value  : none  *                 *****************************************************************/void init_irq(void){	GPDR0 &= ~GPIO_bit(7);	set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(IRQ_GPIO_EZHOST), GPIO_RISING_EDGE);  }/******************************************************************/static int cy67x00_hw_reset (){    int val;   #if 0	    /* read the expansion card present reg */	val = inw(SBC_EXP_PORT_PRESENT_REG);    if (val == CP_PRESENT)	{	    /* Enable Lyberty.  By default, Lyberty will hold in reset mode.  	       This will take Lyberty out of reset */    		writew (0x1, SBC_EXP_PORT_RESET);		/* Set the reset to settle.  This requires about 500 ms */		mdelay(500);		return SUCCESS;	}	else	{        cy_err("no Lyberty card present");	    return ERROR;	}#endif	 return SUCCESS;}module_init (hci_hcd_init);module_exit (hci_hcd_cleanup);MODULE_AUTHOR ("<usbapps@cypress.com>");MODULE_DESCRIPTION ("CY7C67200/300 USB Host/Peripheral Embedded Controller Driver");

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?