📄 usb_ctl.c
字号:
/* * S3C24x0 USB controller core driver. * 2004 (C) Samsung Electronics * SW.LEE : Added "ud" interface to Linux (S3C2440,S3C24A0) * Sree : Added DNW interface * * This program is derived from Extenex Corporation's SA-1100 usb * controller core driver by MIZI. :Seungbum Lim <shawn@mizi.com> * *//* * ep0 - register * ep2~4 - dual port async. RAM (interrupt or DMA) * * config: * ep0. * ep2 : input - DMA_CH0 ? * ep1 : output - DMA_CH3 ? */#include <common.h>#include <command.h>#include <asm/errno.h>#include "usb_ctl.h"#include <s3c24x0_usb.h>#include <s3c2440.h>#include <asm/arch/irqs.h>#include <config.h>#define EINVAL 22 /* Invalid argument *///////////////////////////////////////////////////////////////////////////////// Prototypes//////////////////////////////////////////////////////////////////////////////int usbctl_next_state_on_event(int event);//static void udc_int_hndlr(int, void *, struct pt_regs *);void udc_int_hndlr(void);static void initialize_descriptors(void);void ChangeUPllValue(int mdiv, int pdiv, int sdiv);void reset_usbd(void);void reconfig_usbd(void);unsigned int usbd_dn_cnt;unsigned int usbd_dn_addr;int DNW;//#define USB_DEBUG 1#ifdef USB_DEBUG#define LOG(arg...) printf(__FILE__":"__FUNCTION__"(): " ##arg)#else#define LOG(arg...) (void)(0)#endif#if CONFIG_PROC_FS#define PROC_NODE_NAME "usb"static int usbctl_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data);#endif//////////////////////////////////////////////////////////////////////////////// Globals//////////////////////////////////////////////////////////////////////////////static const char pszMe[] = "usbctl: ";struct usb_info_t usbd_info; /* global to ep0, usb_recv, usb_send *///static int cnt=0;/* device descriptors */static desc_t desc;#define MAX_STRING_DESC 8static string_desc_t *string_desc_array[MAX_STRING_DESC];static string_desc_t sd_zero; /* special sd_zero holds language codes */// called when configuredstatic usb_notify_t configured_callback = NULL;enum { kStateZombie = 0, kStateZombieSuspend = 1, kStateDefault = 2, kStateDefaultSuspend = 3, kStateAddr = 4, kStateAddrSuspend = 5, kStateConfig = 6, kStateConfigSuspend = 7};#if 0static int device_state_machine[8][6] = {// suspend reset resume adddr config deconfig/* zombie */ {kStateZombieSuspend, kStateDefault, kError, kError, kError, kError},/* zom sus */ {kError, kStateDefault, kStateZombie, kError, kError, kError},/* default */ {kStateDefaultSuspend, kError, kStateDefault, kStateAddr, kError, kError},/* def sus */ {kError, kStateDefault, kStateDefault, kError, kError, kError},/* addr */ {kStateAddrSuspend, kStateDefault, kError, kError, kStateConfig, kError},/* addr sus */ {kError, kStateDefault, kStateAddr, kError, kError, kError},/* config */ {kStateConfigSuspend, kStateDefault, kError, kError, kError, kStateAddr},/* cfg sus */ {kError, kStateDefault, kStateConfig, kError, kError, kError}};/* "device state" is the usb device framework state, as opposed to the "state machine state" which is whatever the driver needs and is much more fine grained*/static int sm_state_to_device_state[8] =// zombie zom suspend default default sus{ USB_STATE_POWERED, USB_STATE_SUSPENDED, USB_STATE_DEFAULT, USB_STATE_SUSPENDED,// addr addr sus config config sus USB_STATE_ADDRESS, USB_STATE_SUSPENDED, USB_STATE_CONFIGURED, USB_STATE_SUSPENDED};static char *state_names[8] = { "zombie", "zombie suspended", "default", "default suspended", "address", "address suspended", "configured", "config suspended"};static char *event_names[6] = { "suspend", "reset", "resume", "address assigned", "configure", "de-configure"};static char *device_state_names[] = { "not attached", "attached", "powered", "default", "address", "configured", "suspended"};static int sm_state = kStateZombie;#endif//////////////////////////////////////////////////////////////////////////////// Reset Fucntions//////////////////////////////////////////////////////////////////////////////void reset_usbd(void){ int i; UD_PWR = UD_PWR_DEFAULT | UD_PWR_RESET; /* UD_PWR default value, MCU_RESET */ UD_PWR; UD_PWR = UD_PWR_DEFAULT; LOG("UD_PWR = 0x%08x\n", UD_PWR); for (i = 0; i < 0x100; i++);}void reconfig_usbd(void){ LOG("\n"); /* sec like, shawn */ ep0_state = EP0_STATE_IDLE; set_configuration = 1; set_interface = 1; device_status = 0; ep0_status = 0; ep_bulk_in_status = 0; ep_bulk_out_status = 0; UD_PWR = UD_PWR_DEFAULT; /* EP0 */ UD_INDEX = UD_INDEX_EP0; UD_MAXP = UD_MAXP_8; // 8 byte UD_INDEX = UD_INDEX_EP0; UD_ICSR1 = EP0_CSR_SOPKTRDY | EP0_CSR_SSE; if (DNW) { UD_INDEX = UD_INDEX_EP3; } else { /* EP2 */ UD_INDEX = UD_INDEX_EP2; } UD_MAXP = UD_MAXP_64; // 64 byte if (DNW) { UD_INDEX = UD_INDEX_EP3; } else { UD_INDEX = UD_INDEX_EP2; } UD_ICSR1 = UD_ICSR1_FFLUSH | UD_ICSR1_CLRDT; // fifo flush, data toggle if (DNW) { UD_INDEX = UD_INDEX_EP3; } else { UD_INDEX = UD_INDEX_EP2; } if (DNW) { UD_ICSR2 = UD_ICSR2_DMAIEN; } else { UD_ICSR2 = UD_ICSR2_MODEIN | UD_ICSR2_DMAIEN; /* input mode, IN_PKT_RDY dis */ }#ifdef USE_USBD_DMA UD_ICSR2 &= ~UD_ICSR2_DMAIEN;#endif /* EP1 */ UD_INDEX = UD_INDEX_EP1; UD_MAXP = UD_MAXP_64; // 64 byte UD_INDEX = UD_INDEX_EP1; UD_ICSR1 = UD_ICSR1_FFLUSH | UD_ICSR1_CLRDT; // fifo flush, data toggle UD_INDEX = UD_INDEX_EP1; UD_ICSR2 = 0x0; // output mode UD_INDEX = UD_INDEX_EP1; UD_OCSR1 = UD_OCSR1_FFLUSH | UD_OCSR1_CLRDT; // fifo flush UD_INDEX = UD_INDEX_EP1; UD_OCSR2 = UD_OCSR2_DMAIEN; // OUT_PKT_RDY interrupt disable#ifdef USE_USBD_DMA UD_OCSR2 &= ~UD_OCSR2_DMAIEN; // OUT_PKT_RDY interrupt disable#endif if (DNW) { UD_INTE = UD_INTE_EP0 | UD_INTE_EP3 | UD_INTE_EP1; } else { UD_INTE = UD_INTE_EP0 | UD_INTE_EP2 | UD_INTE_EP1; } UD_USBINTE = UD_USBINTE_RESET | UD_USBINTE_SUSPND; initialize_descriptors(); INTMSK &= ~(BIT_USBD);}void udc_int_hndlr(void){ __u8 saveIdx = UD_INDEX; __u8 usb_status = UD_USBINT; __u8 usbd_status = UD_INT; LOG("usb_status = 0x%02x, usbd_status = 0x%02x\n", usb_status, usbd_status); if (usb_status & UD_USBINT_RESET) { LOG("\n[%d]RESET interrupt\n", sb_debug_cnt++); if (usbctl_next_state_on_event(kEvReset) != kError) { LOG("%s Resetting\n", pszMe); ep0_reset(); ep1_reset(); /* output */ ep2_reset(); /* input */ } // reset_usbd(); reconfig_usbd(); UD_USBINT = UD_USBINT_RESET; //RESET_INT should be cleared after reconfig_usbd().- by samsung src ep0_state = EP0_STATE_IDLE; } /* RESume Interrupt Request */ if (usb_status & UD_USBINT_RESUM) { LOG("[%d]RESUME interrupt\n", sb_debug_cnt++); UD_USBINT = UD_USBINT_RESUM; /* clear */ usbctl_next_state_on_event(kEvResume); } /* SUSpend Interrupt Request */ if (usb_status & UD_USBINT_SUSPND) { LOG("[%d]SUSPEND interrupt\n", sb_debug_cnt++); UD_USBINT = UD_USBINT_SUSPND; /* clear */ usbctl_next_state_on_event(kEvSuspend); } if (usbd_status & UD_INT_EP0) { LOG("\n[%d]EP0 interrupt\n", sb_debug_cnt++); UD_INT = UD_INT_EP0; /* clear */ ep0_int_hndlr(); } /* output */ if (usbd_status & UD_INT_EP1) { LOG("[%d]EP1 interrupt\n", sb_debug_cnt++); UD_INT = UD_INT_EP1; /* clear */ if (DNW) { ep1_int_hndlr(usbd_status); } else { ep1_int_hndlr(usbd_status); } } if (DNW) { /* input */ if (usbd_status & UD_INT_EP3) { LOG("[%d]EP2 interrupt\n", sb_debug_cnt++); UD_INT = UD_INT_EP3; /* clear */ ep1_int_hndlr(usbd_status); } } else { /* input */ if (usbd_status & UD_INT_EP2) { LOG("[%d]EP2 interrupt\n", sb_debug_cnt++); UD_INT = UD_INT_EP2; /* clear */ ep2_int_hndlr(usbd_status); } } if (usbd_status & UD_INT_EP3) UD_INT = UD_INT_EP3; if (usbd_status & UD_INT_EP4) UD_INT = UD_INT_EP4; //Clear_pending(IRQ_USBD); UD_INDEX = saveIdx; LOG("end of usb irq \n");}//////////////////////////////////////////////////////////////////////////////// Public Interface///////////////////////////////////////////////////////////////////////////////* Open S3C24x0 usb core on behalf of a client, but don't start running */int s3c24x0_usb_open(const char *client){ LOG("\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -