📄 usb_phci.c
字号:
/************************************************************* * 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) * *************************************************************/ #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;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 };#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 DEBUGvoid 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 (urb_t * 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, urb_t * urb, int index);static void td_submit_urb (urb_t * 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 (urb_t * 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 (urb_t * urb);static int rh_submit_urb (urb_t * urb);static int rh_unlink_urb (urb_t * urb);/* URB support functions */static void urb_free_priv( struct phci *hc, urb_priv_t *urb_priv);static void urb_rm_priv_locked (urb_t *urb);static void urb_rm_priv (urb_t *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 (urb_t * urb);static int sphci_submit_urb (urb_t *urb);static int sphci_unlink_urb (urb_t *urb);#ifdef CONFIG_USB_HCDC_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_HCDC_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 */};static __u8 atl_active_ptd_X_threshold_ptd[17] = {0,1,2,2,3,3,4,5,6,6,7,8,9,9,10,11,12};#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) { __u32 uData; 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_HCDC_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_HCDC_OTG */ isp1362_command((uReg|0x80), isp1362_device); uData = uRegData & 0x0000FFFF; isp1362_write16(uData,isp1362_device); uData = (uRegData & 0xFFFF0000) >> 16; isp1362_write16(uData,isp1362_device);} /* fnvPhciHcorWrite() *//*--------------------------------------------------------------* * Host Controller operational registers read *--------------------------------------------------------------*/void fnvPhciHcorRead(phci_t *phci,__u32 uReg, __u32 *puRegData) { __u32 uData; 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_command(uReg, isp1362_device); uData = isp1362_read16(isp1362_device); *puRegData = uData & 0x0000FFFF; uData = isp1362_read16(isp1362_device); *puRegData |= (uData & 0x0000FFFF) << 16;#ifdef CONFIG_USB_HCDC_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_HCDC_OTG */} /* fnvPhciHcorRead() *//*--------------------------------------------------------------* * Host Controller registers read *--------------------------------------------------------------*/void phci_reg_read16(__u32 uReg, __u32 *puRegData) { __u32 uData; detail_debug(("phci_reg_read16(uReg = 0x%x, puRegData = 0x%p)\n",uReg, puRegData)) isp1362_command(uReg,isp1362_device); uData = isp1362_read16(isp1362_device); *puRegData = uData;} /* 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_command((uReg|0x80), isp1362_device); isp1362_write16(uRegData, isp1362_device);} /* phci_reg_write16() *//*--------------------------------------------------------------* * Host Controller registers read 32 bit *--------------------------------------------------------------*/void phci_reg_read32(__u32 uReg, __u32 *puRegData) { __u32 uData; detail_debug(("phci_reg_read32(uReg = 0x%x, puRegData = 0x%p)\n",uReg, puRegData)) isp1362_command(uReg, isp1362_device); uData = isp1362_read16(isp1362_device); *puRegData = uData & 0x0000FFFF; uData = isp1362_read16(isp1362_device); *puRegData |= (uData & 0x0000FFFF) << 16;} /* phci_reg_read32() *//*--------------------------------------------------------------* * Host Controller registers write 32 bit *--------------------------------------------------------------*/void phci_reg_write32(__u32 uReg, __u32 uRegData) { __u32 uData; detail_debug(("phci_reg_write32(uReg = 0x%x, uRegData = 0x%x)\n",uReg, uRegData)) isp1362_command((uReg|0x80), isp1362_device); uData = uRegData & 0x0000FFFF; isp1362_write16(uData,isp1362_device); uData = (uRegData & 0xFFFF0000) >> 16; isp1362_write16(uData,isp1362_device); } /* phci_reg_write32() */#ifdef CONFIG_USB_PHCD_DMAvoid fnvPhciRamWrite(phci_t *phci, __u32 length, __u32 direction, __u32 addr, __u8 *byte_data) { __u32 direct_addr_len; __u16 dma_cnfg = 0; __u32 int_reg; unsigned int flags; __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 & 0x01) length++; /* Align length to even number */ /* 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 memcpy(phci->dma_buff, byte_data, original_length); dma_cnfg = (DMA_BUFF_TYPE_DIR_ADDR | DMA_1CYCLE_BURST_LEN | DMA_COUNTER_ENABLE); /* Disable DMA */ phci_reg_write16(REG_DMA_CNFG, dma_cnfg); /* Clear EOT bit inthe interrupt register */ phci_reg_write16(REG_IRQ, EOT_INT); save_flags(flags); disable_dma(DMA4HC_CHNNL); clear_dma_ff(DMA4HC_CHNNL); set_dma_mode(DMA4HC_CHNNL,DMA_MODE_WRITE); set_dma_addr(DMA4HC_CHNNL,virt_to_bus(phci->dma_buff)); set_dma_count(DMA4HC_CHNNL, length); /* Enable PC DMA */ enable_dma(DMA4HC_CHNNL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -