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

📄 usb_phci.c

📁 philips公司ISP1362 USB OTG控制芯片的驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
/*************************************************************
 * Philips HCD (Host Controller Driver) for USB.
 *
 *	Original Host Controller driver code from Linux OS 2.4.5 Kernel and 
 *  modified for Philips ISP1362 HCD
 * 
 * File Name:	usb_phci.c
 *
 * History:	
 *
 *	Version	Date		Author		Comments
 * -------------------------------------------------
 * 	1.0		09/23/02	SYARRA		Initial Release
 *  1.1		11/22/02	SYARRA		Waiting in while loop for IsoTx
 *									start of frame is changed (ISO_WAIT_FIX)
 *  1.20	04/01//03	SYARRA		clearing tds for sphci_free_dev when 
 * 									devnum == -1 (enumeration failed in usbcore)
 * 									Removed td, dev structure starting address 
 * 									16 byte alignment
 * 	1.21	08/04/03	SYARRA		Adding Break statement in infiniteloop of ProcessIstlInt()
 * 	
 *************************************************************/
 
#include <linux/config.h>
#define MODULE
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/interrupt.h>  /* for in_interrupt() */
#undef DEBUG
#include <linux/usb.h>

#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/unaligned.h>
#include <asm/dma.h>

#include "usb_phci.h"


struct isp1362_dev	*isp1362_device = NULL;
__u32			g_buff_sts = 0;

static 		LIST_HEAD (phci_hcd_list);
static 		spinlock_t 				usb_ed_lock = SPIN_LOCK_UNLOCKED;
static int cc_to_error[16] = { 

/* mapping of the OHCI CC status to error codes */ 
	/* No  Error  */               USB_ST_NOERROR,
	/* CRC Error  */               USB_ST_CRC,
	/* Bit Stuff  */               USB_ST_BITSTUFF,
	/* Data Togg  */               USB_ST_CRC,
	/* Stall      */               USB_ST_STALL,
	/* DevNotResp */               USB_ST_NORESPONSE,
	/* PIDCheck   */               USB_ST_BITSTUFF,
	/* UnExpPID   */               USB_ST_BITSTUFF,
	/* DataOver   */               USB_ST_DATAOVERRUN,
	/* DataUnder  */               USB_ST_DATAUNDERRUN,
	/* reservd    */               USB_ST_NORESPONSE,
	/* reservd    */               USB_ST_NORESPONSE,
	/* BufferOver */               USB_ST_BUFFEROVERRUN,
	/* BuffUnder  */               USB_ST_BUFFERUNDERRUN,
	/* Not Access */               USB_ST_NORESPONSE,
	/* Not Access */               USB_ST_NORESPONSE 
};

__u8		ptd_test_header[HC_PTD_HEADER_SIZE] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF};

#define		phc_name					"PHCI-HC"	
#define		PHCI_UNLINK_TIMEOUT			(HZ / 10)
#define		DRIVER_AUTHOR	"Linux kernel 2.4.5 usb-ohci.c modified for Philips Semiconductors"
#define		DRIVER_DESC	"USB Philips ISP1362 Host Controller Driver"

/* Trace functions */
#ifdef DEBUG
void 	print_int_ed_list(phci_t	*phci);
#endif

#ifdef __PHCI_DEBUG_DETAIL__
static	void 	phci_print_map_buffers(__u8	index);
static	void 	phci_print_ptd_header(__u8	*header, __u32	pipe);
static	void 	phci_print_hex_data(__u8	*data, __u32	length);
static	void 	phci_print_hc_regs(phci_t	*phci, __u8	buff_type);
static 	void 	phci_urb_print (struct urb * urb, char * str, int small);
#endif /* __detail_debug__ */

/* HC Register accessing functions decleration */
void 	fnvPhciHcorWrite	(phci_t 	*phci,__u32 	uReg, __u32 	uRegData);
void 	fnvPhciHcorRead	(phci_t 	*phci,__u32 	uReg, __u32 	*puRegData);
void 	phci_reg_read16	(__u32	uReg, __u32 	*puRegData);
void 	phci_reg_write16	(__u32 	uReg, __u32 	uRegData);

/* HC RAM accessing functions decleration */
void	fnvPhciRamRead(phci_t	*phci, __u32	length, __u32	direction, __u32	addr, __u8	*byte_data);
void	fnvPhciRamWrite(phci_t	*phci, __u32	length, __u32	direction, __u32	addr, __u8	*byte_data);

/* HC Initialization functions decleration */
static	__u32 	fnvPhciHostReset	(phci_t 	*phci);
static	void 	fnvHcIntEnable	(phci_t 	*phci);
static	void 	fnvHcControlInit	(phci_t 	*phci);
static	void 	fnvHcInterruptInit	(phci_t 	*phci);
static	void 	fnvHcFmIntervalInit	(phci_t 	*phci);
static	void 	fnvHcRhPower	(phci_t 	*phci);
static	int	 	fnuPhciHostInit	(phci_t 	*phci);
static	void	fnvHcRamBufferInit( phci_t	*phci) ;
static	phci_t * __devinit 	hc_alloc_phci (struct isp1362_dev *dev);
int __devinit 		hc_found_phci (struct isp1362_dev *dev) ;
void 	hc_release_phci (phci_t * phci);

/* HC Interrupt Functions */
void 	phci_isr(struct isp1362_dev *dev, void *isr_data);

static void 	fnvProcessAtlInt(phci_t	*phci);
static void 	fnvProcessIntlInt(phci_t	*phci);
static void 	fnvProcessIstlInt(phci_t	*phci);

/* TD-PTD map function declerations */
static	void 	phci_init_map_buffers(phci_t	*phci) ;
static	void 	phci_get_td_ptd_index(ed_t	*ed);
static	void 	phci_release_td_ptd_index(ed_t		*ed);
static	void phci_move_pending_td_ptds(td_ptd_map_buff_t   *ptd_map_buff);
static	void 	phci_fill_send_ptd(phci_t	*phci, __u32	send_ptd_bitmap,td_ptd_map_buff_t *ptd_map_buff);
static	void 	phci_fill_send_isoc_ptd(phci_t	*phci, __u32	send_ptd_bitmap,td_ptd_map_buff_t *ptd_map_buff);
static	void 	phci_submit_ed(phci_t	*phci,	ed_t	*ed) ;



/* TD functions decleration */
static 	void 	td_fill (unsigned int info, void * data, int len, struct urb * urb, int index);
static 	void 	td_submit_urb (struct urb * urb);

/* EP handling functions */
static int 		ep_int_ballance (phci_t * phci, int interval, int load);
static int 		ep_2_n_interval (int inter);
static int 		ep_rev (int num_bits, int word);
static int 		ep_link (phci_t * phci, ed_t * edi);
static int 		ep_unlink (phci_t * phci, ed_t * ed);
static void	 	ep_rm_ed (struct usb_device * usb_dev, ed_t * ed);
static ed_t*	ep_add_ed (struct usb_device * usb_dev, unsigned int pipe, int interval, int load);

/* Done List handling functions */
static void 	dl_transfer_length(td_t * td);
static void 	dl_del_urb (struct urb * urb);
static void 	dl_del_list (phci_t  * phci, unsigned int frame);
static td_t * 	dl_reverse_done_list (phci_t * phci, td_t *td_list);
static void 	dl_done_list (phci_t * phci, td_t * td_list);

/* Root Hub function declerations */
int 			rh_send_irq (phci_t * phci, void * rh_data, int rh_len);
static void 	rh_int_timer_do (unsigned long ptr);
static int 		rh_init_int_timer (struct urb * urb);
static int 		rh_submit_urb (struct urb * urb);
static int 		rh_unlink_urb (struct urb * urb);

/* URB support functions */
static void 	urb_free_priv( struct phci	*hc, urb_priv_t	*urb_priv);
static void 	urb_rm_priv_locked (struct urb	*urb);
static void 	urb_rm_priv (struct urb	*urb);

/* USB core (usb.c) interface functions */
static int 		sphci_alloc_dev (struct usb_device *usb_dev);
static int 		sphci_free_dev (struct usb_device *usb_dev);
static int 		sphci_get_current_frame_number (struct usb_device *usb_dev);
static int 		sphci_return_urb (struct urb * urb);
static int 		sphci_submit_urb (struct urb	*urb);
static int 		sphci_unlink_urb (struct urb	*urb);

#ifdef CONFIG_USB_OTG
/* otg function declerations for OTG driver interface */
int		phci_register_otg(phci_otg_data_t	*otg_data);
void	phci_unregister_otg(phci_otg_data_t	*otg_data);
void	phci_otg_port_control(void *priv, __u8	cmd, __u32 *data);
#endif /* CONFIG_USB_OTG */

/* Global Variable decleration */
static td_ptd_map_buff_t	td_ptd_map_buff[TD_PTD_TOTAL_BUFF_TYPES];	/* td-ptd map buffer for all 1362 buffers */
static	__u8				td_ptd_pipe_x_buff_type[PIPE_BULK+1] = {	/* Pipe vs buffer type data structure */
								TD_PTD_BUFF_TYPE_ISTL0, 					/* ISOC for ISTL0 */
								TD_PTD_BUFF_TYPE_INTL,					/* INT	for INTL */
								TD_PTD_BUFF_TYPE_ATL,					/* CONTROL for ATL */
								TD_PTD_BUFF_TYPE_ATL					/* BULK for ATL */
};

#ifdef CONFIG_USB_OTG
extern int usb_otg_hub_new_device(struct usb_device *otg_dev, int port);
#define phci_hub_new_device(x)	otg_hub_new_device(x,0)
#else
#define phci_hub_new_device(x)	usb_new_device(x)
#endif


#define		phci_spin_lock_irqsave(p,f)	if(!(in_interrupt())) spin_lock_irqsave(p, f)
#define		phci_spin_unlock_irqrestore(p,f)	if(!(in_interrupt())) spin_unlock_irqrestore (p, f)

/*--------------------------------------------------------------*
 * Host Controller operational registers write
 *--------------------------------------------------------------*/
void fnvPhciHcorWrite(phci_t *phci,__u32 uReg, __u32 uRegData) {

	detail_debug(("fnvPhciHcorWrite(phci = 0x%p, uReg = 0x%x, uRegData = 0x%x)\n",phci, uReg, uRegData))

	/* Check if the registers are controlled by software */
	if ((uReg == uHcHcdControl ) || (uReg == (uHcHcdControl | 0x80))) {
		phci->uHcHcdControl_hcd = uRegData;
		return;
	}

	if ((uReg == uHcHcdCommandStatus) || (uReg == (uHcHcdCommandStatus | 0x80))) {
		phci->uHcHcdCommandStatus_hcd = uRegData;
		return;
	}

#ifdef CONFIG_USB_OTG

	/* In OTG mode, clear the internal connect status change bit */
	if((uReg == (uHcRhPort1Status+OTG_HC_PORT_NO)) || (uReg == ((uHcRhPort1Status+OTG_HC_PORT_NO)|0x80))) {
		if(uRegData & RH_PS_CSC) phci->otg_port_status &= ~(RH_PS_CSC);
	}

#endif /* CONFIG_USB_OTG */

	isp1362_reg_write32(isp1362_device, (uReg|0x80), uRegData);

} /* fnvPhciHcorWrite() */


/*--------------------------------------------------------------*
 * Host Controller operational registers read
 *--------------------------------------------------------------*/
void fnvPhciHcorRead(phci_t *phci,__u32 uReg, __u32 *puRegData) {

	detail_debug(("fnvPhciHcorRead(phci = 0x%p, uReg = 0x%x, puRegData = 0x%p)\n",phci, uReg, puRegData))

	/* Service the HCD HC transfer control registers first */
	if (uReg == uHcHcdControl ) {
		*puRegData = phci->uHcHcdControl_hcd;
		return;
	}

	if (uReg == uHcHcdCommandStatus) {
		*puRegData = phci->uHcHcdCommandStatus_hcd;
		return;
	}

	isp1362_reg_read32(isp1362_device, uReg, (*puRegData));

#ifdef CONFIG_USB_OTG

	/* In OTG mode mask the Connect status, connect status change bits from HC and give
	 * internal values which are controlled by OTG module */

	if(uReg == (uHcRhPort1Status+OTG_HC_PORT_NO)) {
		*puRegData &= ~(RH_PS_CSC|RH_PS_CCS);
		*puRegData |= (phci->otg_port_status & (RH_PS_CSC|RH_PS_CCS));
	}

#endif /* CONFIG_USB_OTG */

} /* fnvPhciHcorRead() */


/*--------------------------------------------------------------*
 * Host Controller registers read
 *--------------------------------------------------------------*/
void phci_reg_read16(__u32 uReg, __u32 *puRegData) {

	detail_debug(("phci_reg_read16(uReg = 0x%x, puRegData = 0x%p)\n",uReg, puRegData))

	isp1362_reg_read16(isp1362_device, uReg, (*puRegData));


} /* phci_reg_read16() */


/*--------------------------------------------------------------*
 * Host Controller registers write
 *--------------------------------------------------------------*/
void phci_reg_write16(__u32 uReg, __u32 uRegData) {

	detail_debug(("phci_reg_write16(uReg = 0x%x, uRegData = 0x%x)\n",uReg, uRegData))

	isp1362_reg_write16(isp1362_device, (uReg|0x80), uRegData);

} /* phci_reg_write16() */



/*--------------------------------------------------------------*
 * Host Controller registers read 32 bit 
 *--------------------------------------------------------------*/
void phci_reg_read32(__u32 uReg, __u32 *puRegData) {

	detail_debug(("phci_reg_read32(uReg = 0x%x, puRegData = 0x%p)\n",uReg, puRegData))

	isp1362_reg_read32(isp1362_device, uReg, (*puRegData));

} /* phci_reg_read32() */


/*--------------------------------------------------------------*
 * Host Controller registers write 32 bit 
 *--------------------------------------------------------------*/
void phci_reg_write32(__u32 uReg, __u32 uRegData) {

	detail_debug(("phci_reg_write32(uReg = 0x%x, uRegData = 0x%x)\n",uReg, uRegData))
    
	isp1362_reg_write32(isp1362_device, (uReg|0x80), uRegData);
	
} /* phci_reg_write32() */


/*--------------------------------------------------------------*
 * Host Controller ATL/INTL/ISTL buffer Write
 *--------------------------------------------------------------*/
void	fnvPhciRamWrite(phci_t	*phci, __u32	length, __u32	direction, __u32	addr, __u8	*byte_data) {

	__u32		direct_addr_len;
	__u32		original_length;

	detail_debug(("fnvPhciRamWrite(length = %d, direction = %d, addr = 0x%x, byte_data = 0x%p)\n",length, direction, addr, byte_data))

	if(!length || !byte_data) return;				/* If there is nothing to write , return back */

	original_length = length;

	if(length%2)	length++;

	/* fill the direct address length register with len+dir+addr */
	direct_addr_len = addr & 0x7FFF;
	direct_addr_len |= direction;
	direct_addr_len |= (length << 16);

	phci_reg_write32(REG_DIRECT_ADDR_LEN  ,direct_addr_len);  // writing the direct address length 

	isp1362_buff_write(isp1362_device, (REG_DIRECT_ADDR_DATA|0x80), byte_data,original_length);

	return;

⌨️ 快捷键说明

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