summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcharles.park <charles.park@hardkernel.com>2017-07-31 04:47:40 +0300
committercharles.park <charles.park@hardkernel.com>2017-07-31 04:47:40 +0300
commitff2835dac9b2fde047d9db59458d496a98b4a635 (patch)
treebe442516d7bc4df2274c35e94b38476604384e0e
parent631efb2c1d11b3bd6c2283ba55b8bcc8acfda670 (diff)
downloadu-boot-ff2835dac9b2fde047d9db59458d496a98b4a635.tar.xz
ODROID-XU4 : add usb3.0 driver for fastboot.
Change-Id: I7936f9f7fbd6eda1976eb31475300021164ea9fd
-rwxr-xr-x[-rw-r--r--]arch/arm/mach-exynos/clock.c34
-rwxr-xr-x[-rw-r--r--]arch/arm/mach-exynos/include/mach/clk.h2
-rwxr-xr-xarch/arm/mach-exynos/include/mach/usb.h133
-rwxr-xr-x[-rw-r--r--]drivers/usb/gadget/Makefile4
-rwxr-xr-xdrivers/usb/gadget/fastboot-ss.c507
-rwxr-xr-xdrivers/usb/gadget/usbd3-ss.c2557
-rwxr-xr-xdrivers/usb/gadget/usbd3-ss.h1178
-rwxr-xr-xinclude/configs/odroid_xu4.h24
-rwxr-xr-x[-rw-r--r--]include/fastboot.h288
9 files changed, 4727 insertions, 0 deletions
diff --git a/arch/arm/mach-exynos/clock.c b/arch/arm/mach-exynos/clock.c
index 3d31f9d524..5ad6a297ec 100644..100755
--- a/arch/arm/mach-exynos/clock.c
+++ b/arch/arm/mach-exynos/clock.c
@@ -951,6 +951,40 @@ static unsigned long exynos4_get_lcd_clk(void)
return pclk;
}
+/* exynos5: get the usbdrd clock */
+static unsigned long exynos5_get_usbdrd_clk(void)
+{
+ struct exynos5_clock *clk =
+ (struct exynos5_clock *)samsung_get_base_clock();
+ unsigned int addr;
+ unsigned int sel;
+ unsigned int ratio;
+ unsigned long sclk;
+
+ sel = readl(&clk->src_fsys);
+ sel = (sel >> 28) & 0xf;
+
+ sclk = 24000000;
+ /*
+ * CLK_DIV_FSYS0
+ * USBDRD30_RATIO[27:24], SATA_RATIO[23:20]
+ */
+ addr = (unsigned int)&clk->div_fsys0;
+ ratio = readl(addr);
+
+ ratio = (ratio >> 24) & 0xff;
+
+ return (sclk / (ratio + 1));
+}
+
+unsigned long get_usbdrd_clk(void)
+{
+ if (cpu_is_exynos5())
+ return exynos5_get_usbdrd_clk();
+
+ return 0;
+}
+
/* get_lcd_clk: return lcd clock frequency */
static unsigned long exynos5_get_lcd_clk(void)
{
diff --git a/arch/arm/mach-exynos/include/mach/clk.h b/arch/arm/mach-exynos/include/mach/clk.h
index d20b7d2ae3..aa04325a24 100644..100755
--- a/arch/arm/mach-exynos/include/mach/clk.h
+++ b/arch/arm/mach-exynos/include/mach/clk.h
@@ -60,4 +60,6 @@ int set_spi_clk(int periph_id, unsigned int rate);
*/
unsigned long clock_get_periph_rate(int peripheral);
+unsigned long get_usbdrd_clk(void);
+
#endif
diff --git a/arch/arm/mach-exynos/include/mach/usb.h b/arch/arm/mach-exynos/include/mach/usb.h
new file mode 100755
index 0000000000..4e1e1ab093
--- /dev/null
+++ b/arch/arm/mach-exynos/include/mach/usb.h
@@ -0,0 +1,133 @@
+/*
+ * (C) Copyright 2011 Samsung Electronics Co. Ltd
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _EXYNOS_USB_H
+#define _EXYNOS_USB_H
+
+/*
+ * SYSREG
+ */
+#define USB_CFG_OFFSET 0x230
+#define USB_CFG_REG (EXYNOS_SYSREG_BASE + USB_CFG_OFFSET)
+
+/* PHY CONTROL */
+#define USB_DEVICE_PHY_CONTROL_OFFSET 0x0704
+#define USB_DEVICE1_PHY_CONTROL_OFFSET 0x0708
+#define USB_PHY_CONTROL_OFFSET 0x070C
+
+#define USB_DEVICE_PHY_CONTROL (EXYNOS_POWER_BASE+USB_DEVICE_PHY_CONTROL_OFFSET)
+#define USB_DEVICE1_PHY_CONTROL (EXYNOS_POWER_BASE+USB_DEVICE1_PHY_CONTROL_OFFSET)
+#define USB_PHY_CONTROL (EXYNOS_POWER_BASE+USB_PHY_CONTROL_OFFSET)
+
+//==========================
+// Global Registers (Gxxxx)
+//==========================
+// Global Common Registers
+#define rGSBUSCFG0 (USBDEVICE3_LINK_BASE + 0xc100)
+#define rGSBUSCFG1 (USBDEVICE3_LINK_BASE + 0xc104)
+#define rGTXTHRCFG (USBDEVICE3_LINK_BASE + 0xc108)
+#define rGRXTHRCFG (USBDEVICE3_LINK_BASE + 0xc10c)
+#define rGCTL (USBDEVICE3_LINK_BASE + 0xc110)
+#define rGEVTEN (USBDEVICE3_LINK_BASE + 0xc114)
+#define rGSTS (USBDEVICE3_LINK_BASE + 0xc118)
+#define rGSNPSID (USBDEVICE3_LINK_BASE + 0xc120)
+#define rGGPIO (USBDEVICE3_LINK_BASE + 0xc124)
+#define rGUID (USBDEVICE3_LINK_BASE + 0xc128)
+#define rGUCTL (USBDEVICE3_LINK_BASE + 0xc12c)
+#define rGBUSERRADDR_LO (USBDEVICE3_LINK_BASE + 0xc130)
+#define rGBUSERRADDR_HI (USBDEVICE3_LINK_BASE + 0xc134)
+
+// Global Port to USB Instance Mapping Registers
+#define rGPRTBIMAP_LO (USBDEVICE3_LINK_BASE + 0xc138)
+#define rGPRTBIMAP_HI (USBDEVICE3_LINK_BASE + 0xc13c)
+#define rGPRTBIMAP_HS_LO (USBDEVICE3_LINK_BASE + 0xc180)
+#define rGPRTBIMAP_HS_HI (USBDEVICE3_LINK_BASE + 0xc184)
+#define rGPRTBIMAP_FS_LO (USBDEVICE3_LINK_BASE + 0xc188)
+#define rGPRTBIMAP_FS_HI (USBDEVICE3_LINK_BASE + 0xc18c)
+
+// Global Hardware Parameter Registers
+#define rGHWPARAMS0 (USBDEVICE3_LINK_BASE + 0xc140) // 0x20204000 @c510
+#define rGHWPARAMS1 (USBDEVICE3_LINK_BASE + 0xc144) // 0x0060c93b @c510
+#define rGHWPARAMS2 (USBDEVICE3_LINK_BASE + 0xc148) // 0x12345678 @c510
+#define rGHWPARAMS3 (USBDEVICE3_LINK_BASE + 0xc14c) // 0x10420085 @c510
+#define rGHWPARAMS4 (USBDEVICE3_LINK_BASE + 0xc150) // 0x48820004 @c510
+#define rGHWPARAMS5 (USBDEVICE3_LINK_BASE + 0xc154) // 0x04204108 @c510
+#define rGHWPARAMS6 (USBDEVICE3_LINK_BASE + 0xc158) // 0x04008020 @c510
+#define rGHWPARAMS7 (USBDEVICE3_LINK_BASE + 0xc15c) // 0x018516fe @c510
+#define rGHWPARAMS8 (USBDEVICE3_LINK_BASE + 0xc600) // 0x00000386 @c510
+
+// Global Debug Registers
+#define rGDBGFIFOSPACE (USBDEVICE3_LINK_BASE + 0xc160)
+#define rGDBGLTSSM (USBDEVICE3_LINK_BASE + 0xc164)
+#define rGDBGLSPMUX (USBDEVICE3_LINK_BASE + 0xc170)
+#define rGDBGLSP (USBDEVICE3_LINK_BASE + 0xc174)
+#define rGDBGEPINFO0 (USBDEVICE3_LINK_BASE + 0xc178)
+#define rGDBGEPINFO1 (USBDEVICE3_LINK_BASE + 0xc17c)
+
+// Global PHY Registers
+#define rGUSB2PHYCFG (USBDEVICE3_LINK_BASE + 0xc200)
+#define rGUSB2I2CCTL (USBDEVICE3_LINK_BASE + 0xc240)
+#define rGUSB2PHYACC (USBDEVICE3_LINK_BASE + 0xc280)
+#define rGUSB3PIPECTL (USBDEVICE3_LINK_BASE + 0xc2c0)
+
+// Global FIFO Size Registers (0 <= num <= 15 @510)
+#define rGTXFIFOSIZ(num) ((USBDEVICE3_LINK_BASE + 0xc300) + 0x04*num)
+#define rGRXFIFOSIZ0 (USBDEVICE3_LINK_BASE + 0xc380)
+
+// Global Event Buffer Registers (DWC_USB3_DEVICE_NUM_INT = 1 @C510, GHWPARAMS1[20:15])
+#define rGEVNTADR_LO0 (USBDEVICE3_LINK_BASE + 0xc400)
+#define rGEVNTADR_HI0 (USBDEVICE3_LINK_BASE + 0xc404)
+#define rGEVNTSIZ0 (USBDEVICE3_LINK_BASE + 0xc408)
+#define rGEVNTCOUNT0 (USBDEVICE3_LINK_BASE + 0xc40c)
+
+//==========================
+// Device Registers (Dxxxx)
+//==========================
+// Device Common Registers
+#define rDCFG (USBDEVICE3_LINK_BASE + 0xc700)
+#define rDCTL (USBDEVICE3_LINK_BASE + 0xc704)
+#define rDEVTEN (USBDEVICE3_LINK_BASE + 0xc708)
+#define rDSTS (USBDEVICE3_LINK_BASE + 0xc70c)
+#define rDGCMDPAR (USBDEVICE3_LINK_BASE + 0xc710)
+#define rDGCMD (USBDEVICE3_LINK_BASE + 0xc714)
+#define rDALEPENA (USBDEVICE3_LINK_BASE + 0xc720)
+
+// Device Endpoint Registers (0 <= ep <= 15)
+#define rDOEPCMDPAR2(ep) ((USBDEVICE3_LINK_BASE + 0xc800) + 0x20*ep)
+#define rDOEPCMDPAR1(ep) ((USBDEVICE3_LINK_BASE + 0xc804) + 0x20*ep)
+#define rDOEPCMDPAR0(ep) ((USBDEVICE3_LINK_BASE + 0xc808) + 0x20*ep)
+#define rDOEPCMD(ep) ((USBDEVICE3_LINK_BASE + 0xc80c) + 0x20*ep)
+
+#define rDIEPCMDPAR2(ep) ((USBDEVICE3_LINK_BASE + 0xc810) + 0x20*ep)
+#define rDIEPCMDPAR1(ep) ((USBDEVICE3_LINK_BASE + 0xc814) + 0x20*ep)
+#define rDIEPCMDPAR0(ep) ((USBDEVICE3_LINK_BASE + 0xc818) + 0x20*ep)
+#define rDIEPCMD(ep) ((USBDEVICE3_LINK_BASE + 0xc81c) + 0x20*ep)
+
+//==========================
+// USB DEVICE PHY CONTROL REGISTERS
+//==========================
+#define EXYNOS_PHY_LINKSYSTEM (USBDEVICE3_PHYCTRL_BASE + 0x04)
+#define EXYNOS_PHY_UTMI (USBDEVICE3_PHYCTRL_BASE + 0x08)
+#define EXYNOS_PHY_PIPE (USBDEVICE3_PHYCTRL_BASE + 0x0C)
+#define EXYNOS_PHY_CLKPWR (USBDEVICE3_PHYCTRL_BASE + 0x10)
+#define EXYNOS_PHY_REG0 (USBDEVICE3_PHYCTRL_BASE + 0x14)
+#define EXYNOS_PHY_REG1 (USBDEVICE3_PHYCTRL_BASE + 0x18)
+#define EXYNOS_PHY_PARAM0 (USBDEVICE3_PHYCTRL_BASE + 0x1C)
+#define EXYNOS_PHY_PARAM1 (USBDEVICE3_PHYCTRL_BASE + 0x20)
+#define EXYNOS_PHY_TERM (USBDEVICE3_PHYCTRL_BASE + 0x24)
+#define EXYNOS_PHY_TEST (USBDEVICE3_PHYCTRL_BASE + 0x28)
+#define EXYNOS_PHY_ADP (USBDEVICE3_PHYCTRL_BASE + 0x2C)
+#define EXYNOS_PHY_BATCHG (USBDEVICE3_PHYCTRL_BASE + 0x30)
+#define EXYNOS_PHY_RESUME (USBDEVICE3_PHYCTRL_BASE + 0x34)
+#define EXYNOS_PHY_LINK_PORT (USBDEVICE3_PHYCTRL_BASE + 0x44)
+
+#endif
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 0fbbb7c82c..21d7ed70de 100644..100755
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -43,5 +43,9 @@ obj-y += ep0.o
obj-$(CONFIG_DW_UDC) += designware_udc.o
obj-$(CONFIG_MPC885_FAMILY) += mpc8xx_udc.o
obj-$(CONFIG_CPU_PXA27X) += pxa27x_udc.o
+else
+ifdef CONFIG_TARGET_ODROID_XU4
+obj-y += usbd3-ss.o
+endif
endif
endif
diff --git a/drivers/usb/gadget/fastboot-ss.c b/drivers/usb/gadget/fastboot-ss.c
new file mode 100755
index 0000000000..11382eef2a
--- /dev/null
+++ b/drivers/usb/gadget/fastboot-ss.c
@@ -0,0 +1,507 @@
+/*
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Platform dependant code for Fastboot
+ *
+ * Base code of USB connection part is usbd-ss.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <fastboot.h>
+
+#if defined(CONFIG_FASTBOOT)
+
+#define FBOOT_USBD_IS_CONNECTED() (1)
+#define FBOOT_USBD_DETECT_IRQ() EXYNOS_USBD_DETECT_IRQ()
+#define FBOOT_USBD_CLEAR_IRQ() EXYNOS_USBD_CLEAR_IRQ()
+#define VENDOR_ID 0x18D1
+#define PRODUCT_ID 0x0002
+#define FB_PKT_SZ 64 // full-speed mode
+#define OK 0
+#define ERROR -1
+
+/* In high speed mode packets are 512
+ In full speed mode packets are 64 */
+#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0 (0x0200)//512
+#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1 (0x0040)// 64
+#define TX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0 (0x0200)
+#define TX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1 (0x0040)
+
+/* String 0 is the language id */
+#define DEVICE_STRING_MANUFACTURER_INDEX 1
+#define DEVICE_STRING_PRODUCT_INDEX 2
+#define DEVICE_STRING_SERIAL_NUMBER_INDEX 3
+#define DEVICE_STRING_CONFIG_INDEX 4
+#define DEVICE_STRING_INTERFACE_INDEX 5
+#define DEVICE_STRING_MAX_INDEX DEVICE_STRING_INTERFACE_INDEX
+#define DEVICE_STRING_LANGUAGE_ID 0x0409 /* English (United States) */
+
+//static char *device_strings[DEVICE_STRING_MANUFACTURER_INDEX+1];
+static char *device_strings[DEVICE_STRING_MAX_INDEX+1];
+static struct cmd_fastboot_interface *fastboot_interface = NULL;
+/* The packet size is dependend of the speed mode
+ In high speed mode packets are 512
+ In full speed mode packets are 64
+ Set to maximum of 512 */
+
+/* Note: The start address must be double word aligned */
+char* reply_msg;
+unsigned int transfer_size;
+u32 fboot_response_flag=0;
+
+/* codes representing languages */
+const u8 fboot_string_desc1[] = /* Manufacturer */
+{
+ (0x16+2), STRING_DESCRIPTOR,
+ 'G', 0x0, 'o', 0x0, 'o', 0x0, 'g', 0x0, 'l', 0x0,
+ 'e', 0x0, ',', 0x0, ' ', 0x0, 'I', 0x0, 'n', 0x0,
+ 'c', 0x0
+};
+
+const u8 fboot_string_desc2[] = /* Product */
+{
+ (0x16+2), STRING_DESCRIPTOR,
+ 'A', 0x0, 'n', 0x0, 'd', 0x0, 'r', 0x0, 'o', 0x0,
+ 'i', 0x0, 'd', 0x0, ' ', 0x0, '1', 0x0, '.', 0x0,
+ '0', 0x0
+};
+
+const u8 fboot_string_desc3[] = /* Test Serial ID */
+{
+ (0x16+2), STRING_DESCRIPTOR,
+ 'S', 0x0, 'M', 0x0, 'D', 0x0, 'K', 0x0,
+ 'E', 0x0,'X', 0x0, 'Y', 0x0, 'N', 0x0, 'O', 0x0, 'S', 0x0, '-', 0x0, '0', 0x0, '1', 0x0
+};
+
+/* setting the device qualifier descriptor and a string descriptor */
+const u8 fboot_qualifier_desc[] =
+{
+ 0x0a, /* 0 desc size */
+ 0x06, /* 1 desc type (DEVICE_QUALIFIER)*/
+ 0x00, /* 2 USB release */
+ 0x02, /* 3 => 2.00*/
+ 0xFF, /* 4 class */
+ 0x42, /* 5 subclass */
+ 0x03, /* 6 protocol */
+ 64, /* 7 max pack size */
+ 0x01, /* 8 number of other-speed configuration */
+ 0x00, /* 9 reserved */
+};
+
+volatile usbdev3_trb_ptr_t g_pBulkInTrb;
+
+/* extern function from usbd3-ss.c */
+void exynos_usb_phy_on(void);
+int exynos_usb_wait_cable_insert(void);
+
+void fboot_usbctl_init(void)
+{
+ exynos_usb_phy_on();
+}
+
+int fboot_usb_int_bulkin(const char *buffer, unsigned int buffer_size)
+{
+ usbdev3_trb_ctrl_t usbdev3_trb_ctrl;
+ usbdev3_trb_ptr_t pBulkInTrb;
+ u32 usCapTrbBufSiz, uLastBufSize;
+ u32 i;
+
+ // Set TRB for multiple Bulk IN Packet
+ usCapTrbBufSiz = TRB_BUF_SIZ_LIMIT/oUsbDev3.m_uBulkEPMaxPktSize*oUsbDev3.m_uBulkEPMaxPktSize;
+ g_uCntOfBulkInTrb = buffer_size/usCapTrbBufSiz;
+
+ if ((buffer_size%usCapTrbBufSiz) != 0)
+ g_uCntOfBulkInTrb++;
+
+ g_pBulkInTrb = (usbdev3_trb_ptr_t)exynos_usb_malloc(g_uCntOfBulkInTrb*sizeof(usbdev3_trb_t), USBDEV3_MDWIDTH/8);
+
+ if (g_pBulkInTrb == NULL)
+ Assert(0);
+
+ pBulkInTrb = g_pBulkInTrb;
+ // Fill the Trbs
+ usbdev3_trb_ctrl.data = 0;
+ usbdev3_trb_ctrl.b.lst = 0;
+ usbdev3_trb_ctrl.b.chn = 1;
+ usbdev3_trb_ctrl.b.csp = 0;
+ usbdev3_trb_ctrl.b.trb_ctrl = (u32)TRB_CTRL_NORMAL;
+ usbdev3_trb_ctrl.b.isp_imi = 1;
+ usbdev3_trb_ctrl.b.ioc = 0;
+ usbdev3_trb_ctrl.b.strmid_sofn = 0;
+
+ for(i=0;i<(g_uCntOfBulkInTrb-1);i++, pBulkInTrb++)
+ exynos_usb_fill_trb(pBulkInTrb, (u32)(buffer+usCapTrbBufSiz*i), usCapTrbBufSiz, usbdev3_trb_ctrl.data, 1);
+
+ usbdev3_trb_ctrl.b.lst = 1;
+ usbdev3_trb_ctrl.b.chn = 0;
+ usbdev3_trb_ctrl.b.ioc = 1;
+ uLastBufSize = buffer_size-usCapTrbBufSiz*i;
+ exynos_usb_fill_trb(pBulkInTrb, (u32)(buffer+usCapTrbBufSiz*i), uLastBufSize, usbdev3_trb_ctrl.data, 1);
+
+ // . Issue Start Xfer for multiple Bulk IN Packet
+ //------------------------------------
+ if (!exynos_usb_start_ep_xfer(USBDEV3_EP_DIR_IN, BULK_IN_EP, (u32)g_pBulkInTrb, 0, &oUsbDev3.m_uTriIn[BULK_IN_EP]))
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+void fboot_usb_handle_ep_in_xfer_complete(void)
+{
+ if (fboot_response_flag) {
+ exynos_usb_free((u32)g_pBulkInTrb);
+ fboot_response_flag=0;
+ }
+
+ return;
+}
+
+int fboot_usb_handle_ep_out_xfer_complete(void)
+{
+ u32 usRxCnt;
+ usbdev3_trb_ctrl_t usbdev3_trb_ctrl;
+
+ // Check whether TRB was finished successfully or not
+ if ((g_pBulkOutTrb0->control.b.hwo != 0)||(g_pBulkOutTrb0->status.b.trb_sts != 0))
+ {
+ Assert(0);
+ }
+
+ usRxCnt = oUsbDev3.m_uBulkEPMaxPktSize - g_pBulkOutTrb0->status.b.buf_siz;
+
+ if (usRxCnt < oUsbDev3.m_uBulkEPMaxPktSize)
+ g_ucTempDownBuf[usRxCnt] = 0;
+
+ /* Pass this up to the interface's handler */
+ if (fastboot_interface && fastboot_interface->rx_handler) {
+ /* Call rx_handler at common/cmd_fastboot.c */
+ if (!fastboot_interface->rx_handler(g_ucTempDownBuf, usRxCnt))
+ ;//OK
+ }
+
+ // . Set TRB for 1st Bulk Out Packet
+ //-----------------------------
+ usbdev3_trb_ctrl.data = 0;
+ usbdev3_trb_ctrl.b.lst = 1;
+ usbdev3_trb_ctrl.b.trb_ctrl = (u32)TRB_CTRL_NORMAL;
+ usbdev3_trb_ctrl.b.isp_imi = 1;
+ usbdev3_trb_ctrl.b.ioc = 1;
+ usbdev3_trb_ctrl.b.strmid_sofn = 0;
+
+ exynos_usb_fill_trb(g_pBulkOutTrb0, (u32)g_ucTempDownBuf, oUsbDev3.m_uBulkEPMaxPktSize, usbdev3_trb_ctrl.data, 1);
+
+ // . Issue Start Xfer for 1st Bulk Out Packet
+ //------------------------------------
+ if (!exynos_usb_start_ep_xfer(USBDEV3_EP_DIR_OUT, BULK_OUT_EP, (u32)g_pBulkOutTrb0, 0, &oUsbDev3.m_uTriOut[BULK_OUT_EP]))
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+void fboot_usb_set_descriptors_tlb(void)
+{
+ /* Standard device descriptor */
+ oUsbDev3.m_oDesc.oDescDevice.bLength=DEVICE_DESC_SIZE; /*0x12*/
+ oUsbDev3.m_oDesc.oDescDevice.bDescriptorType=DEVICE_DESCRIPTOR;
+ if (oUsbDev3.m_eSpeed == USBDEV3_SPEED_SUPER) {
+ oUsbDev3.m_oDesc.oDescDevice.bMaxPacketSize0=SUPER_SPEED_CONTROL_PKT_EXP_SZ;
+ } else {
+ oUsbDev3.m_oDesc.oDescDevice.bMaxPacketSize0=oUsbDev3.m_uControlEPMaxPktSize;
+ }
+ oUsbDev3.m_oDesc.oDescDevice.bDeviceClass=0x0; /* 0x0*/
+ oUsbDev3.m_oDesc.oDescDevice.bDeviceSubClass=0x0;
+ oUsbDev3.m_oDesc.oDescDevice.bDeviceProtocol=0x0;
+ oUsbDev3.m_oDesc.oDescDevice.idVendorL=VENDOR_ID&0xff;//0xB4; /**/
+ oUsbDev3.m_oDesc.oDescDevice.idVendorH=VENDOR_ID>>8;//0x0B; /**/
+ oUsbDev3.m_oDesc.oDescDevice.idProductL=PRODUCT_ID&0xff;//0xFF; /**/
+ oUsbDev3.m_oDesc.oDescDevice.idProductH=PRODUCT_ID>>8;//0x0F; /**/
+ oUsbDev3.m_oDesc.oDescDevice.bcdDeviceL=0x00;
+ oUsbDev3.m_oDesc.oDescDevice.bcdDeviceH=0x01;
+ oUsbDev3.m_oDesc.oDescDevice.iManufacturer=DEVICE_STRING_MANUFACTURER_INDEX; /* index of string descriptor */
+ oUsbDev3.m_oDesc.oDescDevice.iProduct=DEVICE_STRING_PRODUCT_INDEX; /* index of string descriptor */
+ oUsbDev3.m_oDesc.oDescDevice.iSerialNumber=DEVICE_STRING_SERIAL_NUMBER_INDEX;
+ oUsbDev3.m_oDesc.oDescDevice.bNumConfigurations=0x1;
+ if (oUsbDev3.m_eSpeed == USBDEV3_SPEED_SUPER) {
+ oUsbDev3.m_oDesc.oDescDevice.bcdUSBL=0x00;
+ oUsbDev3.m_oDesc.oDescDevice.bcdUSBH=0x03; // Ver 3.0
+ } else if (oUsbDev3.m_eSpeed == USBDEV3_SPEED_HIGH) {
+ oUsbDev3.m_oDesc.oDescDevice.bcdUSBL=0x00;
+ oUsbDev3.m_oDesc.oDescDevice.bcdUSBH=0x02; // Ver 2.0
+ } else if (oUsbDev3.m_eSpeed == USBDEV3_SPEED_FULL) {
+ oUsbDev3.m_oDesc.oDescDevice.bcdUSBL=0x10;
+ oUsbDev3.m_oDesc.oDescDevice.bcdUSBH=0x01; // Ver 2.0
+ }
+
+ /* Standard configuration descriptor */
+ oUsbDev3.m_oDesc.oDescConfig.bLength=CONFIG_DESC_SIZE; /* 0x9 bytes */
+ oUsbDev3.m_oDesc.oDescConfig.bDescriptorType=CONFIGURATION_DESCRIPTOR;
+ if (oUsbDev3.m_eSpeed == USBDEV3_SPEED_SUPER)
+ oUsbDev3.m_oDesc.oDescConfig.wTotalLengthL=CONFIG_SS_DESC_TOTAL_SIZE;
+ else
+ oUsbDev3.m_oDesc.oDescConfig.wTotalLengthL=CONFIG_DESC_TOTAL_SIZE;
+ oUsbDev3.m_oDesc.oDescConfig.wTotalLengthH=0;
+ oUsbDev3.m_oDesc.oDescConfig.bNumInterfaces=1;
+ /* dbg descConf.bConfigurationValue=2; // why 2? There's no reason.*/
+ oUsbDev3.m_oDesc.oDescConfig.bConfigurationValue=1;
+ oUsbDev3.m_oDesc.oDescConfig.iConfiguration=0;
+ oUsbDev3.m_oDesc.oDescConfig.bmAttributes=CONF_ATTR_DEFAULT|CONF_ATTR_SELFPOWERED; /* bus powered only.*/
+ oUsbDev3.m_oDesc.oDescConfig.maxPower=25; /* draws 50mA current from the USB bus.*/
+
+ /* Standard interface descriptor */
+ oUsbDev3.m_oDesc.oDescInterface.bLength=INTERFACE_DESC_SIZE; /* 9*/
+ oUsbDev3.m_oDesc.oDescInterface.bDescriptorType=INTERFACE_DESCRIPTOR;
+ oUsbDev3.m_oDesc.oDescInterface.bInterfaceNumber=0x0;
+ oUsbDev3.m_oDesc.oDescInterface.bAlternateSetting=0x0; /* ?*/
+ oUsbDev3.m_oDesc.oDescInterface.bNumEndpoints = 2; /* # of endpoints except EP0*/
+ oUsbDev3.m_oDesc.oDescInterface.bInterfaceClass= FASTBOOT_INTERFACE_CLASS;// 0xff; /* 0x0 ?*/
+ oUsbDev3.m_oDesc.oDescInterface.bInterfaceSubClass= FASTBOOT_INTERFACE_SUB_CLASS;// 0x42;
+ oUsbDev3.m_oDesc.oDescInterface.bInterfaceProtocol= FASTBOOT_INTERFACE_PROTOCOL;//0x03;
+ oUsbDev3.m_oDesc.oDescInterface.iInterface=0x0;
+
+ if (oUsbDev3.m_eSpeed == USBDEV3_SPEED_SUPER) {
+ /* Standard endpoint0 descriptor */
+ oUsbDev3.m_oSSDesc.oDescEp0.bLength=ENDPOINT_DESC_SIZE;
+ oUsbDev3.m_oSSDesc.oDescEp0.bDescriptorType=ENDPOINT_DESCRIPTOR;
+ oUsbDev3.m_oSSDesc.oDescEp0.bEndpointAddress=BULK_IN_EP|EP_ADDR_IN;
+ oUsbDev3.m_oSSDesc.oDescEp0.bmAttributes=EP_ATTR_BULK;
+ oUsbDev3.m_oSSDesc.oDescEp0.wMaxPacketSizeL=(u8)oUsbDev3.m_uBulkEPMaxPktSize; /* 64*/
+ oUsbDev3.m_oSSDesc.oDescEp0.wMaxPacketSizeH=(u8)(oUsbDev3.m_uBulkEPMaxPktSize>>8);
+ oUsbDev3.m_oSSDesc.oDescEp0.bInterval=0x0; /* not used */
+
+ oUsbDev3.m_oSSDesc.oDescEp0Comp.bLength=6;
+ oUsbDev3.m_oSSDesc.oDescEp0Comp.bDescriptorType=0x30;
+ oUsbDev3.m_oSSDesc.oDescEp0Comp.bMaxBurst=15;
+ oUsbDev3.m_oSSDesc.oDescEp0Comp.bmAttributes=0;
+ oUsbDev3.m_oSSDesc.oDescEp0Comp.wBytesPerInterval=0;
+
+ /* Standard endpoint1 descriptor */
+ oUsbDev3.m_oSSDesc.oDescEp1.bLength=ENDPOINT_DESC_SIZE;
+ oUsbDev3.m_oSSDesc.oDescEp1.bDescriptorType=ENDPOINT_DESCRIPTOR;
+ oUsbDev3.m_oSSDesc.oDescEp1.bEndpointAddress=BULK_OUT_EP|EP_ADDR_OUT;
+ oUsbDev3.m_oSSDesc.oDescEp1.bmAttributes=EP_ATTR_BULK;
+ oUsbDev3.m_oSSDesc.oDescEp1.wMaxPacketSizeL=(u8)oUsbDev3.m_uBulkEPMaxPktSize; /* 64*/
+ oUsbDev3.m_oSSDesc.oDescEp1.wMaxPacketSizeH=(u8)(oUsbDev3.m_uBulkEPMaxPktSize>>8);
+ oUsbDev3.m_oSSDesc.oDescEp1.bInterval=0x0; /* not used */
+
+ oUsbDev3.m_oSSDesc.oDescEp1Comp.bLength=6;
+ oUsbDev3.m_oSSDesc.oDescEp1Comp.bDescriptorType=0x30;
+ oUsbDev3.m_oSSDesc.oDescEp1Comp.bMaxBurst=15;
+ oUsbDev3.m_oSSDesc.oDescEp1Comp.bmAttributes=0;
+ oUsbDev3.m_oSSDesc.oDescEp1Comp.wBytesPerInterval=0;
+
+ // Standard BOS(Binary Object Store) descriptor
+ oUsbDev3.m_oSSDesc.oDescBos.bLength = BOS_DESC_SIZE;
+ oUsbDev3.m_oSSDesc.oDescBos.bDescriptorType = 0x0F;
+ oUsbDev3.m_oSSDesc.oDescBos.wTotalLength = BOS_DESC_TOTAL_SIZE;
+ oUsbDev3.m_oSSDesc.oDescBos.bNumDeviceCaps = 3;
+
+ oUsbDev3.m_oSSDesc.oDescUsb20Ext.bLength = USB20_EXT_CAP_DESC_SIZE;
+ oUsbDev3.m_oSSDesc.oDescUsb20Ext.bDescriptorType = 0x10;
+ oUsbDev3.m_oSSDesc.oDescUsb20Ext.bDevCapabilityType = USB_CAP_20_EXT;
+ oUsbDev3.m_oSSDesc.oDescUsb20Ext.bmAttributes = 0x2;
+
+ oUsbDev3.m_oSSDesc.oDescSuperCap.bLength = SUPER_CAP_DESC_SIZE;
+ oUsbDev3.m_oSSDesc.oDescSuperCap.bDescriptorType = 0x10;
+ oUsbDev3.m_oSSDesc.oDescSuperCap.bDevCapabilityType = USB_CAP_SS;
+ oUsbDev3.m_oSSDesc.oDescSuperCap.bmAttributes = 0x0;
+ oUsbDev3.m_oSSDesc.oDescSuperCap.wSpeedsSupported = 0xC;
+ oUsbDev3.m_oSSDesc.oDescSuperCap.bFunctionalitySupport = 2;
+ /* TODO: set correct value */
+ oUsbDev3.m_oSSDesc.oDescSuperCap.bU1DevExitLat = 0x4;
+ oUsbDev3.m_oSSDesc.oDescSuperCap.wU2DevExitLat = 0x4;
+
+ oUsbDev3.m_oSSDesc.oDescContainCap.bLength = CONTAIN_CAP_DESC_SIZE;
+ oUsbDev3.m_oSSDesc.oDescContainCap.bDescriptorType = 0x10;
+ oUsbDev3.m_oSSDesc.oDescContainCap.bDevCapabilityType = USB_CAP_CID;
+ oUsbDev3.m_oSSDesc.oDescContainCap.bReserved = 0x0;
+ memset(oUsbDev3.m_oSSDesc.oDescContainCap.containerID, 0x0, 16);
+ }
+ else {
+ /* Standard endpoint0 descriptor */
+ oUsbDev3.m_oDesc.oDescEp0.bLength=ENDPOINT_DESC_SIZE;
+ oUsbDev3.m_oDesc.oDescEp0.bDescriptorType=ENDPOINT_DESCRIPTOR;
+ oUsbDev3.m_oDesc.oDescEp0.bEndpointAddress=BULK_IN_EP|EP_ADDR_IN;
+ oUsbDev3.m_oDesc.oDescEp0.bmAttributes=EP_ATTR_BULK;
+ oUsbDev3.m_oDesc.oDescEp0.wMaxPacketSizeL=(u8)oUsbDev3.m_uBulkEPMaxPktSize; /* 64*/
+ oUsbDev3.m_oDesc.oDescEp0.wMaxPacketSizeH=(u8)(oUsbDev3.m_uBulkEPMaxPktSize>>8);
+ oUsbDev3.m_oDesc.oDescEp0.bInterval=0x0; /* not used */
+
+ /* Standard endpoint1 descriptor */
+ oUsbDev3.m_oDesc.oDescEp1.bLength=ENDPOINT_DESC_SIZE;
+ oUsbDev3.m_oDesc.oDescEp1.bDescriptorType=ENDPOINT_DESCRIPTOR;
+ oUsbDev3.m_oDesc.oDescEp1.bEndpointAddress=BULK_OUT_EP|EP_ADDR_OUT;
+ oUsbDev3.m_oDesc.oDescEp1.bmAttributes=EP_ATTR_BULK;
+ oUsbDev3.m_oDesc.oDescEp1.wMaxPacketSizeL=(u8)oUsbDev3.m_uBulkEPMaxPktSize; /* 64*/
+ oUsbDev3.m_oDesc.oDescEp1.wMaxPacketSizeH=(u8)(oUsbDev3.m_uBulkEPMaxPktSize>>8);
+ oUsbDev3.m_oDesc.oDescEp1.bInterval=0x0; /* not used */
+ }
+}
+
+int fboot_usb_int_hndlr(void)
+{
+ return exynos_udc_int_hndlr();
+}
+
+//-----------------------------------------------------------------------------------
+// FASTBOOT codes
+//-----------------------------------------------------------------------------------
+
+static void set_serial_number(void)
+{
+ char *dieid = getenv("dieid#");
+ if (dieid == NULL) {
+ device_strings[DEVICE_STRING_SERIAL_NUMBER_INDEX] = "SLSI0123";
+ } else {
+ static char serial_number[32];
+ int len;
+
+ memset(&serial_number[0], 0, 32);
+ len = strlen(dieid);
+ if (len > 30)
+ len = 30;
+
+ strncpy(&serial_number[0], dieid, len);
+
+ device_strings[DEVICE_STRING_SERIAL_NUMBER_INDEX] =
+ &serial_number[0];
+ }
+}
+
+/* Initizes the board specific fastboot
+ Returns 0 on success
+ Returns 1 on failure */
+int fastboot_init(struct cmd_fastboot_interface *interface)
+{
+ int ret = 1;
+
+ // usbd init
+ fboot_usbctl_init();
+
+ device_strings[DEVICE_STRING_MANUFACTURER_INDEX] = "Samsung S.LSI";
+ device_strings[DEVICE_STRING_PRODUCT_INDEX] = "smdk";
+ set_serial_number();
+ /* These are just made up */
+ device_strings[DEVICE_STRING_CONFIG_INDEX] = "Android Fastboot";
+ device_strings[DEVICE_STRING_INTERFACE_INDEX] = "Android Fastboot";
+
+ /* The interface structure */
+ fastboot_interface = interface;
+ fastboot_interface->product_name = device_strings[DEVICE_STRING_PRODUCT_INDEX];
+ fastboot_interface->serial_no = device_strings[DEVICE_STRING_SERIAL_NUMBER_INDEX];
+ fastboot_interface->nand_block_size = CFG_FASTBOOT_PAGESIZE * 64;
+ fastboot_interface->transfer_buffer = (unsigned char *) CFG_FASTBOOT_TRANSFER_BUFFER;
+ fastboot_interface->transfer_buffer_size = CFG_FASTBOOT_TRANSFER_BUFFER_SIZE;
+
+ memset((unsigned char *) CFG_FASTBOOT_TRANSFER_BUFFER, 0x0, FASTBOOT_REBOOT_MAGIC_SIZE);
+
+ reply_msg = (char *)exynos_usb_malloc(512, USBDEV3_MDWIDTH/8);
+
+ ret = 0; // This is a fake return value, because we do not initialize USB yet!
+
+ return ret;
+}
+
+/* Cleans up the board specific fastboot */
+void fastboot_shutdown(void)
+{
+ /* when operation is done, usbd must be stopped */
+ exynos_usb_stop();
+ is_fastboot = 0;
+}
+
+int fastboot_fifo_size(void)
+{
+ return (oUsbDev3.m_eSpeed == USBDEV3_SPEED_HIGH) ? RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0 : RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1;
+}
+
+/*
+ * Handles board specific usb protocol exchanges
+ * Returns 0 on success
+ * Returns 1 on disconnects, break out of loop
+ * Returns 2 if no USB activity detected
+ * Returns -1 on failure, unhandled usb requests and other error conditions
+*/
+int fastboot_poll(void)
+{
+ //printf("DEBUG: %s is called.\n", __FUNCTION__);
+ /* No activity */
+ int ret = FASTBOOT_INACTIVE;
+
+ if (!exynos_usb_wait_cable_insert() && !is_fastboot) {
+ exynos_usbctl_init();
+ exynos_usbc_activate();
+ is_fastboot = 1;
+ }
+
+ /* A disconnect happended, this signals that the cable
+ has been disconnected, return immediately */
+ if (!FBOOT_USBD_IS_CONNECTED()) {
+ return FASTBOOT_DISCONNECT;
+ } else if (FBOOT_USBD_DETECT_IRQ()) {
+ if (!fboot_usb_int_hndlr())
+ ret = FASTBOOT_OK;
+ else
+ ret = FASTBOOT_ERROR;
+ FBOOT_USBD_CLEAR_IRQ();
+ }
+
+ return ret;
+}
+
+
+/* Send a status reply to the client app
+ buffer does not have to be null terminated.
+ buffer_size must be not be larger than what is returned by
+ fastboot_fifo_size
+ Returns 0 on success
+ Returns 1 on failure */
+int fastboot_tx_status(const char *buffer, unsigned int buffer_size, const u32 need_sync_flag)
+{
+ /* fastboot client only reads back at most 64 */
+ transfer_size = 64 < buffer_size ? 64 : buffer_size;
+
+ if (fboot_response_flag)
+ printf(" Response tx Warnning\n");
+
+ memcpy(reply_msg, buffer, transfer_size);
+ fboot_response_flag=1;
+ fboot_usb_int_bulkin(reply_msg, transfer_size);
+
+ if (need_sync_flag)
+ {
+ while(fboot_response_flag)
+ fastboot_poll();
+ }
+ return 1;
+}
+
+/* Returns 0 on success
+ Returns 1 on failure */
+int fastboot_tx_mem(const char *buffer, unsigned int buffer_size)
+{
+ if (!fboot_usb_int_bulkin(buffer, buffer_size))
+ return 0;
+ return 1;
+}
+
+/* A board specific variable handler.
+ The size of the buffers is governed by the fastboot spec.
+ rx_buffer is at most 57 bytes
+ tx_buffer is at most 60 bytes
+ Returns 0 on success
+ Returns 1 on failure */
+int fastboot_getvar(const char *rx_buffer, char *tx_buffer)
+{
+ /* Place board specific variables here */
+ return 1;
+}
+
+#endif /* CONFIG_FASTBOOT */
diff --git a/drivers/usb/gadget/usbd3-ss.c b/drivers/usb/gadget/usbd3-ss.c
new file mode 100755
index 0000000000..9c971e60c4
--- /dev/null
+++ b/drivers/usb/gadget/usbd3-ss.c
@@ -0,0 +1,2557 @@
+/*
+ * drivers/usb/gadget/usbd3-ss.c
+ *
+ * (C) Copyright 2011
+ * Yulgon Kim, Samsung Erectronics, yulgon.kim@samsung.com.
+ * - only support for EXYNOS5210
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+
+#if defined(CONFIG_ARCH_EXYNOS5)
+#include <command.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/clk.h>
+#include "usbd3-ss.h"
+
+#undef USBD3_DBG
+#ifdef USBD3_DBG
+#define DBG_USBD3(fmt, args...) DBG_USBD3("[%s:%d] " fmt, __FUNCTION__, __LINE__, ##args)
+#else
+#define DBG_USBD3(fmt, args...) do { } while (0)
+#endif
+
+#define Assert(value) value ? : printf("[%s:%d] Assert(%d) \n", __func__, __LINE__, value)
+
+#define USBDEVICE3_LINK_BASE (oUsbDev3.m_uLinkBaseRegs)
+#define USBDEVICE3_PHYCTRL_BASE (oUsbDev3.m_uPhyBaseRegs)
+
+/* codes representing languages */
+const u8 string_desc0[] =
+{
+ 4, STRING_DESCRIPTOR, LANGID_US_L, LANGID_US_H,
+};
+
+const u8 dnw_string_desc1[] = /* Manufacturer */
+{
+ (0x14+2), STRING_DESCRIPTOR,
+ 'S', 0x0, 'y', 0x0, 's', 0x0, 't', 0x0, 'e', 0x0,
+ 'm', 0x0, ' ', 0x0, 'M', 0x0, 'C', 0x0, 'U', 0x0,
+};
+
+const u8 dnw_string_desc2[] = /* Product */
+{
+ (0x2a+2), STRING_DESCRIPTOR,
+ 'S', 0x0, 'E', 0x0, 'C', 0x0, ' ', 0x0, 'S', 0x0,
+ '3', 0x0, 'C', 0x0, '6', 0x0, '4', 0x0, '0', 0x0,
+ '0', 0x0, 'X', 0x0, ' ', 0x0, 'T', 0x0, 'e', 0x0,
+ 's', 0x0, 't', 0x0, ' ', 0x0, 'B', 0x0, '/', 0x0,
+ 'D', 0x0
+};
+
+/* setting the device qualifier descriptor and a string descriptor */
+const u8 qualifier_desc[] =
+{
+ 0x0a, /* 0 desc size */
+ 0x06, /* 1 desc type (DEVICE_QUALIFIER)*/
+ 0x00, /* 2 USB release */
+ 0x02, /* 3 => 2.00*/
+ 0xFF, /* 4 class */
+ 0x00, /* 5 subclass */
+ 0x00, /* 6 protocol */
+ 64, /* 7 max pack size */
+ 0x01, /* 8 number of other-speed configuration */
+ 0x00, /* 9 reserved */
+};
+
+const u8 config_full[] =
+{
+ 0x09, /* 0 desc size */
+ 0x07, /* 1 desc type (other speed)*/
+ 0x20, /* 2 Total length of data returned */
+ 0x00, /* 3 */
+ 0x01, /* 4 Number of interfaces supported by this speed configuration */
+ 0x01, /* 5 value to use to select configuration */
+ 0x00, /* 6 index of string desc */
+ /* 7 same as configuration desc */
+ CONF_ATTR_DEFAULT|CONF_ATTR_SELFPOWERED,
+ 0x19, /* 8 same as configuration desc */
+
+};
+
+const u8 config_full_total[] =
+{
+ 0x09, 0x07 ,0x20 ,0x00 ,0x01 ,0x01 ,0x00 ,0xC0 ,0x19,
+ 0x09 ,0x04 ,0x00 ,0x00 ,0x02 ,0xff ,0x00 ,0x00 ,0x00,
+ 0x07 ,0x05 ,0x83 ,0x02 ,0x40 ,0x00 ,0x00,
+ 0x07 ,0x05 ,0x04 ,0x02 ,0x40 ,0x00 ,0x00
+};
+
+const u8 config_high[] =
+{
+ 0x09, /* 0 desc size */
+ 0x07, /* 1 desc type (other speed)*/
+ 0x20, /* 2 Total length of data returned */
+ 0x00, /* 3 */
+ 0x01, /* 4 Number of interfaces supported by this speed configuration */
+ 0x01, /* 5 value to use to select configuration */
+ 0x00, /* 6 index of string desc */
+ /* 7 same as configuration desc */
+ CONF_ATTR_DEFAULT|CONF_ATTR_SELFPOWERED,
+ 0x19, /* 8 same as configuration desc */
+
+};
+
+const u8 config_high_total[] =
+{
+ 0x09, 0x07 ,0x20 ,0x00 ,0x01 ,0x01 ,0x00 ,0xC0 ,0x19,
+ 0x09 ,0x04 ,0x00 ,0x00 ,0x02 ,0xff ,0x00 ,0x00 ,0x00,
+ 0x07 ,0x05 ,0x81 ,0x02 ,0x00 ,0x02 ,0x00,
+ 0x07 ,0x05 ,0x02 ,0x02 ,0x00 ,0x02 ,0x00
+};
+
+const u8 set_sel[6];
+
+/*32 <cfg desc>+<if desc>+<endp0 desc>+<endp1 desc>*/
+#define CONFIG_DESC_TOTAL_SIZE \
+ (CONFIG_DESC_SIZE+INTERFACE_DESC_SIZE+ENDPOINT_DESC_SIZE*2)
+#define CONFIG_SS_DESC_TOTAL_SIZE \
+ (CONFIG_DESC_SIZE+INTERFACE_DESC_SIZE+ENDPOINT_DESC_SIZE*2+ENDPOINT_COMP_DESC_SIZE*2)
+#define BOS_DESC_TOTAL_SIZE \
+ (BOS_DESC_SIZE+USB20_EXT_CAP_DESC_SIZE+SUPER_CAP_DESC_SIZE+CONTAIN_CAP_DESC_SIZE)
+#define TEST_PKT_SIZE 53
+
+#define USB_CAP_20_EXT 0x2
+#define USB_CAP_SS 0x3
+#define USB_CAP_CID 0x4
+
+#define USB_PHY_REF_CLK (EXTREF_24MHz)
+
+#define CONFIG_PHY_CRPORT
+
+u8 test_pkt [TEST_PKT_SIZE] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*JKJKJKJK x 9*/
+ 0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA, /*JJKKJJKK x 8*/
+ 0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE, /*JJJJKKKK x 8*/
+ 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /*JJJJJJJKKKKKKK x8 - '1'*/
+ 0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD, /*'1' + JJJJJJJK x 8*/
+ 0xFC,0x7E,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0x7E /*{JKKKKKKK x 10},JK*/
+};
+
+//=====================================================================
+// global varibles used in several functions
+USBDEV3 oUsbDev3;
+USB_GET_STATUS oStatusGet;
+USB_INTERFACE_GET oInterfaceGet;
+
+u16 g_usConfig;
+u16 g_usUploadPktLength=0;
+u8 g_bTransferEp0 = 0;
+
+u8 g_bSuspendResumeDBG_USBD3;
+
+u8 g_bUsingUsbDownAddr = 0;
+u32 g_uUsbDownAddr = 0;
+
+u32 *g_uUsbDevCtrlInBufferPtr=NULL;
+u32 *g_uUsbDevCtrlOutBufferPtr=NULL;
+u32 *g_uUsbDevBulkOutTmpBufferPtr=NULL;
+u32 *g_uUsbDevBulkOutBufferPtr=NULL;
+u8 bCalled_SetEndPoint = 0;
+
+volatile usbdev3_trb_ptr_t g_pBulkOutTrb0;
+
+volatile usbdev3_trb_ptr_t g_pBulkOutTrbArray_Base;
+volatile usbdev3_trb_ptr_t g_pBulkInTrbArray_Base;
+
+u8 *g_ucTempDownBuf;
+u32 g_uCntOfDescOutComplete = 0;
+u32 g_uCntOfBulkOutTrb, g_uCntOfBulkInTrb;
+u8 g_bIsBulkOutXferDone = 0;
+u8 g_bIsBulkInXferDone = 0;
+
+//=====================================================================
+// For usb download
+
+unsigned int exynos_usbd_dn_addr = 0;
+unsigned int exynos_usbd_dn_cnt = 0;
+int is_fastboot = 0;
+int DNW;
+int exynos_got_header = 0;
+int exynos_receive_done = 0;
+
+extern ulong virt_to_phy_exynos5210(ulong addr);
+static u32 exynos_usb_malloc(u32 uSize, u32 uAlign);
+static void exynos_usb_free(u32 uAddr);
+static void exynos_usb_fill_trb(usbdev3_trb_ptr_t pTrb, u32 uBufAddr, u32 uLen, u32 uTrbCtrl, u32 uHwo);
+static int exynos_usb_start_ep_xfer(USBDEV3_EP_DIR_e eEpDir, u8 ucEpNum, u32 uTrbAddr, u32 uStrmidSofn, u32 *uTri);
+
+u32 EXYNOS_USBD_DETECT_IRQ(void)
+{
+ if (oUsbDev3.m_cable != CONNECTED)
+ return 0;
+
+ return readl(rGEVNTCOUNT0);
+}
+
+void EXYNOS_USBD_CLEAR_IRQ(void)
+{
+ do {
+ ;
+ } while (0);
+}
+
+#include "fastboot-ss.c"
+
+void exynos_usb_phy_on(void)
+{
+ writel(0x1, USB_DEVICE_PHY_CONTROL);
+ writel(0x1, USB_DEVICE1_PHY_CONTROL);
+}
+
+static void exynoy_usb_phy_off(void)
+{
+ usb3_phy_utmi_t usbdev3_phy_utmi;
+
+ usbdev3_phy_utmi.data = 0x0;
+ usbdev3_phy_utmi.b.otg_disable = 0x1;
+ usbdev3_phy_utmi.b.force_sleep = 0x1;
+ usbdev3_phy_utmi.b.force_suspend = 0x1;
+
+ oUsbDev3.m_uPhyBaseRegs = USBDEVICE3_PHYCTRL_CH0_BASE;
+ writel(usbdev3_phy_utmi.data, EXYNOS_PHY_UTMI);
+ oUsbDev3.m_uPhyBaseRegs = USBDEVICE3_PHYCTRL_CH1_BASE;
+ writel(usbdev3_phy_utmi.data, EXYNOS_PHY_UTMI);
+
+ writel(0x0, USB_DEVICE_PHY_CONTROL);
+ writel(0x0, USB_DEVICE1_PHY_CONTROL);
+}
+
+static void exynos_usb_init_phy(void)
+{
+ usb3_phy_utmi_t usbdev3_phy_utmi;
+ usbdev3_phy_clkpwr_t usbdev3_phy_clkpwr;
+ u32 eClkFreq = USB_PHY_REF_CLK;
+
+ /* Reset PHY configuration */
+ writel(0x00000000, EXYNOS_PHY_REG0);
+ writel(0x24d466e4, EXYNOS_PHY_PARAM0); //must
+ writel(0x00000000, EXYNOS_PHY_RESUME);
+
+ writel(0x08000000, EXYNOS_PHY_LINKSYSTEM); // clear [8] : force_vbusvalid bit, [7] : force_bvalid
+ writel(0x03fff818, EXYNOS_PHY_PARAM1); //must
+ writel(0x00000004, EXYNOS_PHY_BATCHG); // PHY CLK Mux. (1<<2) : w_FREECLK, (0<<2) : w_PHYCLK
+ if (eClkFreq == DIFF_100MHz)
+ writel(readl(EXYNOS_PHY_PARAM0) | (0x1<<31), EXYNOS_PHY_PARAM0); // use 100MHz clk
+ usbdev3_phy_utmi.data = 0x0;
+ usbdev3_phy_utmi.b.otg_disable = 0x1;
+
+ writel(usbdev3_phy_utmi.data, EXYNOS_PHY_UTMI);
+
+ usbdev3_phy_clkpwr.data = 0;
+
+ switch(eClkFreq){
+ case DIFF_100MHz:
+ usbdev3_phy_clkpwr.b.fsel = 0x27;
+ usbdev3_phy_clkpwr.b.refclksel = 2; // DIFF PAD
+ usbdev3_phy_clkpwr.b.mpll_multiplier = 0x19;
+ usbdev3_phy_clkpwr.b.ref_clkdiv2 = 0;
+ usbdev3_phy_clkpwr.b.ssc_ref_clk_sel = 0x00;
+ break;
+ case EXTREF_50MHz:
+ usbdev3_phy_clkpwr.b.fsel = 0x7;
+ usbdev3_phy_clkpwr.b.refclksel = 3; // REFCLK_SINGLE
+ usbdev3_phy_clkpwr.b.mpll_multiplier = 0x32;
+ usbdev3_phy_clkpwr.b.ref_clkdiv2 = 0;
+ usbdev3_phy_clkpwr.b.ssc_ref_clk_sel = 0x00;
+ break;
+ case EXTREF_20MHz:
+ usbdev3_phy_clkpwr.b.fsel = 0x4;
+ usbdev3_phy_clkpwr.b.refclksel = 3; // REFCLK_SINGLE
+ usbdev3_phy_clkpwr.b.mpll_multiplier = 0x7d;
+ usbdev3_phy_clkpwr.b.ref_clkdiv2 = 0;
+ usbdev3_phy_clkpwr.b.ssc_ref_clk_sel = 0x00;
+ break;
+ case EXTREF_19_2MHz:
+ usbdev3_phy_clkpwr.b.fsel = 0x3;
+ usbdev3_phy_clkpwr.b.refclksel = 3; // REFCLK_SINGLE
+ usbdev3_phy_clkpwr.b.mpll_multiplier = 0x02;
+ usbdev3_phy_clkpwr.b.ref_clkdiv2 = 0;
+ usbdev3_phy_clkpwr.b.ssc_ref_clk_sel = 0x88;
+ break;
+ case EXTREF_24MHz:
+ default:
+ usbdev3_phy_clkpwr.b.fsel = 0x5;
+ usbdev3_phy_clkpwr.b.refclksel = 3; // REFCLK_SINGLE
+ usbdev3_phy_clkpwr.b.mpll_multiplier = 0x68;
+ usbdev3_phy_clkpwr.b.ref_clkdiv2 = 0;
+ usbdev3_phy_clkpwr.b.ssc_ref_clk_sel = 0x88;
+ break;
+ }
+
+ usbdev3_phy_clkpwr.b.commononn = 1; // pll blocks are powered in suspend or sleep mode
+ usbdev3_phy_clkpwr.b.portreset = 1; // assert port_reset
+ usbdev3_phy_clkpwr.b.retenablen = 1; // normal operating mode
+ usbdev3_phy_clkpwr.b.ref_clkdiv2 = 0;
+ usbdev3_phy_clkpwr.b.ref_ssp_en = 1;
+ usbdev3_phy_clkpwr.b.ssc_en = 1;
+ usbdev3_phy_clkpwr.b.ssc_range = 0;
+ usbdev3_phy_clkpwr.b.ssc_ref_clk_sel = 0x0;
+
+ writel(usbdev3_phy_clkpwr.data, EXYNOS_PHY_CLKPWR);
+ usbdev3_phy_clkpwr.b.portreset = 0;
+ udelay(10);
+ writel(usbdev3_phy_clkpwr.data, EXYNOS_PHY_CLKPWR);
+}
+
+static void exynos_usb_phy_crport_handshake(usb3_phy_reg0_t *phy_reg0)
+{
+ usb3_phy_reg1_t phy_reg1;
+ u32 usec = 100;
+
+ writel(phy_reg0->data, EXYNOS_PHY_REG0);
+
+ do {
+ phy_reg1.data = readl(EXYNOS_PHY_REG1);
+ if (phy_reg1.b.cr_ack)
+ break;
+ } while (usec-- > 0);
+
+ if (!usec)
+ printf("CRPORT handshake timeout (0x%08x)\n", phy_reg0->data);
+}
+
+static void exynos_phy_crport_ctrl(u16 addr, u16 data)
+{
+ usb3_phy_reg0_t phy_reg0;
+
+ /* Write Address */
+ phy_reg0.data = 0;
+ phy_reg0.b.cr_data_in = addr;
+ phy_reg0.b.cr_cap_addr = 1;
+ exynos_usb_phy_crport_handshake(&phy_reg0);
+ phy_reg0.b.cr_cap_addr = 0;
+ exynos_usb_phy_crport_handshake(&phy_reg0);
+
+ /* Write Data */
+ phy_reg0.data = 0;
+ phy_reg0.b.cr_data_in = data;
+ phy_reg0.b.cr_cap_data = 1;
+ exynos_usb_phy_crport_handshake(&phy_reg0);
+ phy_reg0.b.cr_cap_data = 0;
+ exynos_usb_phy_crport_handshake(&phy_reg0);
+
+ /* Execute write operation */
+ phy_reg0.data = 0;
+ phy_reg0.b.cr_data_in = data;
+ phy_reg0.b.cr_write = 1;
+ exynos_usb_phy_crport_handshake(&phy_reg0);
+ phy_reg0.b.cr_write = 0;
+ exynos_usb_phy_crport_handshake(&phy_reg0);
+}
+
+static void exynos_usb_crport_config(void)
+{
+ exynos_phy_crport_ctrl(0x15, 0xA409);
+ exynos_phy_crport_ctrl(0x12, 0xA000);
+}
+
+static u32 exynos_usb_malloc(u32 uSize, u32 uAlign)
+{
+ u32 uAddr, uTemp1, uTemp2, uTemp3;
+ u32 uAddr_aligned;
+ u32 uAllocHwMem_AlignConstraint = 64;
+
+ // get the GCD(Great Common Divider)
+ uTemp2 = uAlign;
+ uTemp3 = uAllocHwMem_AlignConstraint;
+ while(uTemp3)
+ {
+ uTemp1 = uTemp2%uTemp3;
+ uTemp2 = uTemp3;
+ uTemp3 = uTemp1;
+ }
+
+ // get the LCM(Least Common Multiple)
+ uAlign = uAlign*uAllocHwMem_AlignConstraint/uTemp2;
+ //TODO : check align
+ uAddr = (u32)malloc(uSize + uAlign);
+ uTemp2 = uAddr % uAlign;
+
+ uAddr_aligned = uAddr + (uAlign - uTemp2);
+ *(u32 *)(uAddr_aligned-4) = uAddr;
+
+ memset((void *)uAddr, 0, uSize);
+ DBG_USBD3("exynos_usb_malloc:Addr=0x%08x[0x%08x], Size=%d, Align=%d\n\n", uAddr, uAddr_aligned, uSize, uAlign);
+
+ return uAddr_aligned;
+}
+
+static void exynos_usb_free(u32 uAddr)
+{
+ u32 uFree_addr;
+ if (uAddr != 0)
+ {
+ uFree_addr = *(u32 *)(uAddr - 4);
+ free((u8 *)uFree_addr);
+ }
+ DBG_USBD3("\n\nexynos_usb_free:0x%08x[0x%8x]\n\n", uAddr, uFree_addr);
+}
+
+static void exynos_usb_print_ep0_pkt(u8 *pt, u8 count)
+{
+ int i;
+ DBG_USBD3("[DBG:");
+ for(i=0;i<count;i++)
+ DBG_USBD3("%x,", pt[i]);
+ DBG_USBD3("]\n");
+}
+
+static void exynos_usb_set_descriptor_tlb(void)
+{
+ // Standard device descriptor
+ oUsbDev3.m_oDesc.oDescDevice.bLength=DEVICE_DESC_SIZE;
+ oUsbDev3.m_oDesc.oDescDevice.bDescriptorType=DEVICE_DESCRIPTOR;
+ oUsbDev3.m_oDesc.oDescDevice.bDeviceClass=0xFF;
+ oUsbDev3.m_oDesc.oDescDevice.bDeviceSubClass=0x0;
+ oUsbDev3.m_oDesc.oDescDevice.bDeviceProtocol=0x0;
+ if (oUsbDev3.m_eSpeed == USBDEV3_SPEED_SUPER) {
+ oUsbDev3.m_oDesc.oDescDevice.bMaxPacketSize0=SUPER_SPEED_CONTROL_PKT_EXP_SZ;
+ } else {
+ oUsbDev3.m_oDesc.oDescDevice.bMaxPacketSize0=oUsbDev3.m_uControlEPMaxPktSize;
+ }
+ oUsbDev3.m_oDesc.oDescDevice.idVendorL=0xE8;
+ oUsbDev3.m_oDesc.oDescDevice.idVendorH=0x04;
+ oUsbDev3.m_oDesc.oDescDevice.idProductL=0x34;
+ oUsbDev3.m_oDesc.oDescDevice.idProductH=0x12;
+ oUsbDev3.m_oDesc.oDescDevice.bcdDeviceL=0x00;
+ oUsbDev3.m_oDesc.oDescDevice.bcdDeviceH=0x01;
+ oUsbDev3.m_oDesc.oDescDevice.iManufacturer=0x1; // index of string descriptor
+ oUsbDev3.m_oDesc.oDescDevice.iProduct=0x2; // index of string descriptor
+ oUsbDev3.m_oDesc.oDescDevice.iSerialNumber=0x0;
+ oUsbDev3.m_oDesc.oDescDevice.bNumConfigurations=0x1;
+
+ // khs. this should be changed, and also other descriptors should be changed
+ if (oUsbDev3.m_eSpeed == USBDEV3_SPEED_SUPER) {
+ oUsbDev3.m_oDesc.oDescDevice.bcdUSBL=0x00;
+ oUsbDev3.m_oDesc.oDescDevice.bcdUSBH=0x03; // Ver 3.0
+ } else if (oUsbDev3.m_eSpeed == USBDEV3_SPEED_HIGH) {
+ oUsbDev3.m_oDesc.oDescDevice.bcdUSBL=0x00;
+ oUsbDev3.m_oDesc.oDescDevice.bcdUSBH=0x02; // Ver 2.0
+ } else if (oUsbDev3.m_eSpeed == USBDEV3_SPEED_FULL) {
+ oUsbDev3.m_oDesc.oDescDevice.bcdUSBL=0x10;
+ oUsbDev3.m_oDesc.oDescDevice.bcdUSBH=0x01; // Ver 2.0
+ }
+
+ // Standard configuration descriptor
+ oUsbDev3.m_oDesc.oDescConfig.bLength=CONFIG_DESC_SIZE; // 0x9 bytes
+ oUsbDev3.m_oDesc.oDescConfig.bDescriptorType=CONFIGURATION_DESCRIPTOR;
+ if (oUsbDev3.m_eSpeed == USBDEV3_SPEED_SUPER)
+ oUsbDev3.m_oDesc.oDescConfig.wTotalLengthL=CONFIG_SS_DESC_TOTAL_SIZE;
+ else
+ oUsbDev3.m_oDesc.oDescConfig.wTotalLengthL=CONFIG_DESC_TOTAL_SIZE;
+ oUsbDev3.m_oDesc.oDescConfig.wTotalLengthH=0;
+ oUsbDev3.m_oDesc.oDescConfig.bNumInterfaces=1;
+ oUsbDev3.m_oDesc.oDescConfig.bConfigurationValue=1;
+ oUsbDev3.m_oDesc.oDescConfig.iConfiguration=0;
+ oUsbDev3.m_oDesc.oDescConfig.bmAttributes=CONF_ATTR_DEFAULT|CONF_ATTR_SELFPOWERED; // bus powered only.
+ oUsbDev3.m_oDesc.oDescConfig.maxPower=25; // draws 50mA current from the USB bus.
+
+ // Standard interface descriptor
+ oUsbDev3.m_oDesc.oDescInterface.bLength=INTERFACE_DESC_SIZE; // 9
+ oUsbDev3.m_oDesc.oDescInterface.bDescriptorType=INTERFACE_DESCRIPTOR;
+ oUsbDev3.m_oDesc.oDescInterface.bInterfaceNumber=0x0;
+ oUsbDev3.m_oDesc.oDescInterface.bAlternateSetting=0x0; // ?
+ oUsbDev3.m_oDesc.oDescInterface.bNumEndpoints = 2; // # of endpoints except EP0
+ oUsbDev3.m_oDesc.oDescInterface.bInterfaceClass=0xff; // 0x0 ?
+ oUsbDev3.m_oDesc.oDescInterface.bInterfaceSubClass=0x0;
+ oUsbDev3.m_oDesc.oDescInterface.bInterfaceProtocol=0x0;
+ oUsbDev3.m_oDesc.oDescInterface.iInterface=0x0;
+
+ if (oUsbDev3.m_eSpeed == USBDEV3_SPEED_SUPER) {
+ /* Standard endpoint0 descriptor */
+ oUsbDev3.m_oSSDesc.oDescEp0.bLength=ENDPOINT_DESC_SIZE;
+ oUsbDev3.m_oSSDesc.oDescEp0.bDescriptorType=ENDPOINT_DESCRIPTOR;
+ oUsbDev3.m_oSSDesc.oDescEp0.bEndpointAddress=BULK_IN_EP|EP_ADDR_IN;
+ oUsbDev3.m_oSSDesc.oDescEp0.bmAttributes=EP_ATTR_BULK;
+ oUsbDev3.m_oSSDesc.oDescEp0.wMaxPacketSizeL=(u8)oUsbDev3.m_uBulkEPMaxPktSize; /* 64*/
+ oUsbDev3.m_oSSDesc.oDescEp0.wMaxPacketSizeH=(u8)(oUsbDev3.m_uBulkEPMaxPktSize>>8);
+ oUsbDev3.m_oSSDesc.oDescEp0.bInterval=0x0; /* not used */
+
+ oUsbDev3.m_oSSDesc.oDescEp0Comp.bLength=6;
+ oUsbDev3.m_oSSDesc.oDescEp0Comp.bDescriptorType=0x30;
+ oUsbDev3.m_oSSDesc.oDescEp0Comp.bMaxBurst=15;
+ oUsbDev3.m_oSSDesc.oDescEp0Comp.bmAttributes=0;
+ oUsbDev3.m_oSSDesc.oDescEp0Comp.wBytesPerInterval=0;
+
+ /* Standard endpoint1 descriptor */
+ oUsbDev3.m_oSSDesc.oDescEp1.bLength=ENDPOINT_DESC_SIZE;
+ oUsbDev3.m_oSSDesc.oDescEp1.bDescriptorType=ENDPOINT_DESCRIPTOR;
+ oUsbDev3.m_oSSDesc.oDescEp1.bEndpointAddress=BULK_OUT_EP|EP_ADDR_OUT;
+ oUsbDev3.m_oSSDesc.oDescEp1.bmAttributes=EP_ATTR_BULK;
+ oUsbDev3.m_oSSDesc.oDescEp1.wMaxPacketSizeL=(u8)oUsbDev3.m_uBulkEPMaxPktSize; /* 64*/
+ oUsbDev3.m_oSSDesc.oDescEp1.wMaxPacketSizeH=(u8)(oUsbDev3.m_uBulkEPMaxPktSize>>8);
+ oUsbDev3.m_oSSDesc.oDescEp1.bInterval=0x0; /* not used */
+
+ oUsbDev3.m_oSSDesc.oDescEp1Comp.bLength=6;
+ oUsbDev3.m_oSSDesc.oDescEp1Comp.bDescriptorType=0x30;
+ oUsbDev3.m_oSSDesc.oDescEp1Comp.bMaxBurst=15;
+ oUsbDev3.m_oSSDesc.oDescEp1Comp.bmAttributes=0;
+ oUsbDev3.m_oSSDesc.oDescEp1Comp.wBytesPerInterval=0;
+
+ // Standard BOS(Binary Object Store) descriptor
+ oUsbDev3.m_oSSDesc.oDescBos.bLength = BOS_DESC_SIZE;
+ oUsbDev3.m_oSSDesc.oDescBos.bDescriptorType = 0x0F;
+ oUsbDev3.m_oSSDesc.oDescBos.wTotalLength = BOS_DESC_TOTAL_SIZE;
+ oUsbDev3.m_oSSDesc.oDescBos.bNumDeviceCaps = 3;
+
+ oUsbDev3.m_oSSDesc.oDescUsb20Ext.bLength = USB20_EXT_CAP_DESC_SIZE;
+ oUsbDev3.m_oSSDesc.oDescUsb20Ext.bDescriptorType = 0x10;
+ oUsbDev3.m_oSSDesc.oDescUsb20Ext.bDevCapabilityType = USB_CAP_20_EXT;
+ oUsbDev3.m_oSSDesc.oDescUsb20Ext.bmAttributes = 0x2;
+
+ oUsbDev3.m_oSSDesc.oDescSuperCap.bLength = SUPER_CAP_DESC_SIZE;
+ oUsbDev3.m_oSSDesc.oDescSuperCap.bDescriptorType = 0x10;
+ oUsbDev3.m_oSSDesc.oDescSuperCap.bDevCapabilityType = USB_CAP_SS;
+ oUsbDev3.m_oSSDesc.oDescSuperCap.bmAttributes = 0x0;
+ oUsbDev3.m_oSSDesc.oDescSuperCap.wSpeedsSupported = 0xC;
+ oUsbDev3.m_oSSDesc.oDescSuperCap.bFunctionalitySupport = 2;
+ /* TODO: set correct value */
+ oUsbDev3.m_oSSDesc.oDescSuperCap.bU1DevExitLat = 0x4;
+ oUsbDev3.m_oSSDesc.oDescSuperCap.wU2DevExitLat = 0x4;
+
+ oUsbDev3.m_oSSDesc.oDescContainCap.bLength = CONTAIN_CAP_DESC_SIZE;
+ oUsbDev3.m_oSSDesc.oDescContainCap.bDescriptorType = 0x10;
+ oUsbDev3.m_oSSDesc.oDescContainCap.bDevCapabilityType = USB_CAP_CID;
+ oUsbDev3.m_oSSDesc.oDescContainCap.bReserved = 0x0;
+ memset(oUsbDev3.m_oSSDesc.oDescContainCap.containerID, 0x0, 16);
+ }
+ else {
+ /* Standard endpoint0 descriptor */
+ oUsbDev3.m_oDesc.oDescEp0.bLength=ENDPOINT_DESC_SIZE;
+ oUsbDev3.m_oDesc.oDescEp0.bDescriptorType=ENDPOINT_DESCRIPTOR;
+ oUsbDev3.m_oDesc.oDescEp0.bEndpointAddress=BULK_IN_EP|EP_ADDR_IN;
+ oUsbDev3.m_oDesc.oDescEp0.bmAttributes=EP_ATTR_BULK;
+ oUsbDev3.m_oDesc.oDescEp0.wMaxPacketSizeL=(u8)oUsbDev3.m_uBulkEPMaxPktSize; /* 64*/
+ oUsbDev3.m_oDesc.oDescEp0.wMaxPacketSizeH=(u8)(oUsbDev3.m_uBulkEPMaxPktSize>>8);
+ oUsbDev3.m_oDesc.oDescEp0.bInterval=0x0; /* not used */
+
+ /* Standard endpoint1 descriptor */
+ oUsbDev3.m_oDesc.oDescEp1.bLength=ENDPOINT_DESC_SIZE;
+ oUsbDev3.m_oDesc.oDescEp1.bDescriptorType=ENDPOINT_DESCRIPTOR;
+ oUsbDev3.m_oDesc.oDescEp1.bEndpointAddress=BULK_OUT_EP|EP_ADDR_OUT;
+ oUsbDev3.m_oDesc.oDescEp1.bmAttributes=EP_ATTR_BULK;
+ oUsbDev3.m_oDesc.oDescEp1.wMaxPacketSizeL=(u8)oUsbDev3.m_uBulkEPMaxPktSize; /* 64*/
+ oUsbDev3.m_oDesc.oDescEp1.wMaxPacketSizeH=(u8)(oUsbDev3.m_uBulkEPMaxPktSize>>8);
+ oUsbDev3.m_oDesc.oDescEp1.bInterval=0x0; /* not used */
+ }
+}
+
+static void exynos_usb_softreset_phy(u8 ucSet)
+{
+ usbdev3_gusb2phycfg_t usbdev3_gusb2phycfg;
+ usbdev3_gusb3pipectl_t usbdev3_gusb3pipectl;
+
+ usbdev3_gusb2phycfg.data = readl(rGUSB2PHYCFG);
+ usbdev3_gusb2phycfg.b.phy_soft_reset = ucSet;
+ writel(usbdev3_gusb2phycfg.data, rGUSB2PHYCFG);
+
+ usbdev3_gusb3pipectl.data = readl(rGUSB3PIPECTL);
+ usbdev3_gusb3pipectl.b.phy_soft_reset = ucSet;
+ writel(usbdev3_gusb3pipectl.data, rGUSB3PIPECTL);
+}
+
+static void exynos_usb_softreset_core(void)
+{
+ usbdev3_dctl_t usbdev3_dctl;
+
+ usbdev3_dctl.data = readl(rDCTL);
+ usbdev3_dctl.b.core_soft_reset = 1;
+ //usbdev3_dctl.b.run_stop = 0;
+ writel(usbdev3_dctl.data, rDCTL);
+
+ do
+ {
+ udelay(10);
+ usbdev3_dctl.data = readl(rDCTL);
+ } while (usbdev3_dctl.b.core_soft_reset == 1);
+
+ udelay(10); // s/w must wait at least 3 phy clocks(1/60Mz * 3 = 48ns) before accessing the phy domain
+}
+
+static void exynos_usb_enable_eventinterrupt(void)
+{
+ usbdev3_gevntsiz_t usbdev3_gevntsiz;
+
+ usbdev3_gevntsiz.data = readl(rGEVNTSIZ0);
+ usbdev3_gevntsiz.b.event_int_mask = 0;
+ writel(usbdev3_gevntsiz.data, rGEVNTSIZ0);
+}
+
+static void exynos_usb_disable_eventinterrupt(void)
+{
+ usbdev3_gevntsiz_t usbdev3_gevntsiz;
+
+ usbdev3_gevntsiz.data = readl(rGEVNTSIZ0);
+ usbdev3_gevntsiz.b.event_int_mask = 1;
+ writel(usbdev3_gevntsiz.data, rGEVNTSIZ0);
+}
+
+static void exynos_usb_flush_eventbuffer(void)
+{
+ u32 uEventCount;
+
+ uEventCount = readl(rGEVNTCOUNT0) & 0xffff;
+
+ writel(uEventCount, rGEVNTCOUNT0);
+}
+
+static int exynos_usb_wait_ep_cmd_complete(USBDEV3_EP_DIR_e eEpDir, u8 ucEpNum, u32 uSec)
+{
+ usbdev3_depcmd_t usbdev3_depcmd;
+ u32 uEpCmdAddr = (eEpDir==USBDEV3_EP_DIR_IN)? rDIEPCMD(ucEpNum) : rDOEPCMD(ucEpNum);
+
+ do {
+ usbdev3_depcmd.data = readl(uEpCmdAddr);
+
+ if (!(usbdev3_depcmd.b.cmd_active))
+ {
+ DBG_USBD3("Complete: D%cEPCMD(%d)=0x%08x\n",
+ (eEpDir==USBDEV3_EP_DIR_IN)? 'I' : 'O', ucEpNum, usbdev3_depcmd.data);
+ return 1;
+ }
+
+ udelay(1);
+ uSec--;
+ } while (uSec > 0);
+
+ DBG_USBD3("TimeOver: D%cEPCMD(%d)=0x%08x\n",
+ (eEpDir==USBDEV3_EP_DIR_IN)? 'I' : 'O', ucEpNum, usbdev3_depcmd.data);
+ return 0;
+}
+
+static int exynos_usb_set_ep_cfg(USBDEV3_EP_DIR_e eEpDir, u8 ucEpNum, u32 uPar0, u32 uPar1)
+{
+ usbdev3_depcmd_t usbdev3_depcmd;
+ u32 uEpCmdAddr = (eEpDir==USBDEV3_EP_DIR_IN)? rDIEPCMD(ucEpNum) : rDOEPCMD(ucEpNum);
+ u32 uEpPar0Addr = (eEpDir==USBDEV3_EP_DIR_IN)? rDIEPCMDPAR0(ucEpNum) : rDOEPCMDPAR0(ucEpNum);
+ u32 uEpPar1Addr = (eEpDir==USBDEV3_EP_DIR_IN)? rDIEPCMDPAR1(ucEpNum) : rDOEPCMDPAR1(ucEpNum);
+
+
+ writel(uPar1, uEpPar1Addr);
+ writel(uPar0, uEpPar0Addr);
+
+ usbdev3_depcmd.data = 0;
+ usbdev3_depcmd.b.cmd_type = DEPCMD_CMD_SET_EP_CFG;
+ usbdev3_depcmd.b.cmd_active = 1;
+ writel(usbdev3_depcmd.data, uEpCmdAddr);
+
+ if (!exynos_usb_wait_ep_cmd_complete(eEpDir, ucEpNum, CMDCOMPLETEWAIT_UNIT))
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int exynos_usb_set_ep_xfer_rsrc_cfg(USBDEV3_EP_DIR_e eEpDir, u8 ucEpNum, u32 uPar0)
+{
+ usbdev3_depcmd_t usbdev3_depcmd;
+ u32 uEpCmdAddr = (eEpDir==USBDEV3_EP_DIR_IN)? rDIEPCMD(ucEpNum) : rDOEPCMD(ucEpNum);
+ u32 uEpPar0Addr = (eEpDir==USBDEV3_EP_DIR_IN)? rDIEPCMDPAR0(ucEpNum) : rDOEPCMDPAR0(ucEpNum);
+
+ writel(uPar0, uEpPar0Addr);
+
+ usbdev3_depcmd.data = 0;
+ usbdev3_depcmd.b.cmd_type = DEPCMD_CMD_SET_EP_XFER_RSRC_CFG;
+ usbdev3_depcmd.b.cmd_active = 1;
+ writel(usbdev3_depcmd.data, uEpCmdAddr);
+
+ if (!exynos_usb_wait_ep_cmd_complete(eEpDir, ucEpNum, CMDCOMPLETEWAIT_UNIT))
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+static void exynos_usb_enable_ep(USBDEV3_EP_DIR_e eEpDir, u8 ucEpNum)
+{
+ u32 uEpEnaIdx;
+
+ uEpEnaIdx = ucEpNum*2;
+
+ if (eEpDir == USBDEV3_EP_DIR_IN)
+ {
+ uEpEnaIdx++;
+ }
+
+ writel(readl(rDALEPENA) | (1<<uEpEnaIdx), rDALEPENA);
+}
+
+static int exynos_usb_activate_ep0(void)
+{
+ usbdev3_depcmd_t usbdev3_depcmd;
+ usbdev3_depcmdpar0_set_ep_cfg_t usbdev3_depcmdpar0_set_ep_cfg;
+ usbdev3_depcmdpar1_set_ep_cfg_t usbdev3_depcmdpar1_set_ep_cfg;
+
+ // . Start New Configuration
+ //-----------------------
+ usbdev3_depcmd.data = 0;
+ usbdev3_depcmd.b.cmd_type = DEPCMD_CMD_START_NEW_CFG;
+ usbdev3_depcmd.b.cmd_active = 1;
+ writel(usbdev3_depcmd.data, rDOEPCMD(0));
+ if (!exynos_usb_wait_ep_cmd_complete(USBDEV3_EP_DIR_OUT, 0, CMDCOMPLETEWAIT_UNIT))
+ {
+ return 0;
+ }
+
+ // . Issue Set Ep Configuraton for EP0-OUT
+ //------------------------------------
+ usbdev3_depcmdpar0_set_ep_cfg.data = 0;
+ usbdev3_depcmdpar0_set_ep_cfg.b.ep_type = USBDEV3_EP_CTRL;
+ usbdev3_depcmdpar0_set_ep_cfg.b.mps = oUsbDev3.m_uControlEPMaxPktSize; // should be reconfigured after ConnectDone event
+
+ usbdev3_depcmdpar1_set_ep_cfg.data = 0;
+ usbdev3_depcmdpar1_set_ep_cfg.b.xfer_cmpl_en = 1;
+ //usbdev3_depcmdpar1_set_ep_cfg.b.xfer_in_prog_en = 1;
+ usbdev3_depcmdpar1_set_ep_cfg.b.xfer_nrdy_en = 1;
+ usbdev3_depcmdpar1_set_ep_cfg.b.ep_dir = USBDEV3_EP_DIR_OUT;
+ usbdev3_depcmdpar1_set_ep_cfg.b.ep_num = 0;
+
+ if (!exynos_usb_set_ep_cfg(USBDEV3_EP_DIR_OUT, 0, usbdev3_depcmdpar0_set_ep_cfg.data, usbdev3_depcmdpar1_set_ep_cfg.data))
+ {
+ return 0;
+ }
+
+ // . Issue Set Ep Xfer Resource for EP0-OUT
+ //------------------------------------
+ if (!exynos_usb_set_ep_xfer_rsrc_cfg(USBDEV3_EP_DIR_OUT, 0, 1))
+ {
+ return 0;
+ }
+
+ // . Issue Set Ep Configuraton for EP0-IN
+ //------------------------------------
+ usbdev3_depcmdpar0_set_ep_cfg.data = 0;
+ usbdev3_depcmdpar0_set_ep_cfg.b.ep_type = USBDEV3_EP_CTRL;
+ usbdev3_depcmdpar0_set_ep_cfg.b.mps = oUsbDev3.m_uControlEPMaxPktSize; // should be reconfigured after ConnectDone event
+
+ usbdev3_depcmdpar1_set_ep_cfg.data = 0;
+ usbdev3_depcmdpar1_set_ep_cfg.b.xfer_cmpl_en = 1;
+ //usbdev3_depcmdpar1_set_ep_cfg.b.xfer_in_prog_en = 1;
+ usbdev3_depcmdpar1_set_ep_cfg.b.xfer_nrdy_en = 1;
+ usbdev3_depcmdpar1_set_ep_cfg.b.ep_dir = USBDEV3_EP_DIR_IN;
+ usbdev3_depcmdpar1_set_ep_cfg.b.ep_num = 0;
+
+ if (!exynos_usb_set_ep_cfg(USBDEV3_EP_DIR_IN, 0, usbdev3_depcmdpar0_set_ep_cfg.data, usbdev3_depcmdpar1_set_ep_cfg.data))
+ {
+ return 0;
+ }
+
+ // . Issue Set Ep Xfer Resource for EP0-IN
+ //------------------------------------
+ if (!exynos_usb_set_ep_xfer_rsrc_cfg(USBDEV3_EP_DIR_IN, 0, 1))
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int exynos_usb_activate_ep(USBDEV3_EP_DIR_e eEpDir, u8 ucEpNum)
+{
+ usbdev3_depcmd_t usbdev3_depcmd;
+ usbdev3_depcmdpar0_set_ep_cfg_t usbdev3_depcmdpar0_set_ep_cfg;
+ usbdev3_depcmdpar1_set_ep_cfg_t usbdev3_depcmdpar1_set_ep_cfg;
+
+
+ if (oUsbDev3.m_bEPs_Enabled == 0)
+ {
+ oUsbDev3.m_bEPs_Enabled = 1;
+
+ // . Start New Configuration
+ //-----------------------
+ usbdev3_depcmd.data = 0;
+ usbdev3_depcmd.b.param = 2; // XferRscIdx = 2 in case of non-EP0, XferRscIdx = 0 in case of EP0
+ usbdev3_depcmd.b.cmd_type = DEPCMD_CMD_START_NEW_CFG;
+ usbdev3_depcmd.b.cmd_active = 1;
+ writel(usbdev3_depcmd.data, rDOEPCMD(0));
+ if (!exynos_usb_wait_ep_cmd_complete(USBDEV3_EP_DIR_OUT, 0, CMDCOMPLETEWAIT_UNIT))
+ {
+ return 0;
+ }
+ }
+
+
+ // . Issue Set Ep Configuraton
+ //------------------------------------
+ usbdev3_depcmdpar0_set_ep_cfg.data = 0;
+ usbdev3_depcmdpar0_set_ep_cfg.b.ep_type = USBDEV3_EP_BULK;
+ usbdev3_depcmdpar0_set_ep_cfg.b.mps = oUsbDev3.m_uBulkEPMaxPktSize;
+
+ if (eEpDir == USBDEV3_EP_DIR_IN)
+ {
+ usbdev3_depcmdpar0_set_ep_cfg.b.fifo_num = ucEpNum;
+ }
+
+ usbdev3_depcmdpar0_set_ep_cfg.b.brst_siz = 0; // khs. should find best value
+
+
+ usbdev3_depcmdpar1_set_ep_cfg.data = 0;
+ usbdev3_depcmdpar1_set_ep_cfg.b.xfer_cmpl_en = 1;
+ //usbdev3_depcmdpar1_set_ep_cfg.b.xfer_in_prog_en = 1;
+ //usbdev3_depcmdpar1_set_ep_cfg.b.xfer_nrdy_en = 1; // when using preset transfer, this interrupt can be disabled
+ usbdev3_depcmdpar1_set_ep_cfg.b.ep_dir = (u32)eEpDir;
+ usbdev3_depcmdpar1_set_ep_cfg.b.ep_num = ucEpNum;
+
+ if (!exynos_usb_set_ep_cfg(eEpDir, ucEpNum, usbdev3_depcmdpar0_set_ep_cfg.data, usbdev3_depcmdpar1_set_ep_cfg.data))
+ {
+ return 0;
+ }
+
+ // . Issue Set Ep Xfer Resource
+ //--------------------------
+ if (!exynos_usb_set_ep_xfer_rsrc_cfg(eEpDir, ucEpNum, 1))
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+static void exynos_usb_runstop_device(u8 ucSet)
+{
+ usbdev3_dctl_t usbdev3_dctl;
+
+ usbdev3_dctl.data = readl(rDCTL);
+ usbdev3_dctl.b.run_stop = ucSet;
+ writel(usbdev3_dctl.data, rDCTL);
+}
+
+static int exynos_usb_start_ep_xfer(USBDEV3_EP_DIR_e eEpDir, u8 ucEpNum, u32 uTrbAddr, u32 uStrmidSofn, u32 *uTri)
+{
+ usbdev3_depcmd_t usbdev3_depcmd;
+ u32 uEpCmdAddr = (eEpDir==USBDEV3_EP_DIR_IN)? rDIEPCMD(ucEpNum) : rDOEPCMD(ucEpNum);
+ u32 uEpPar0Addr = (eEpDir==USBDEV3_EP_DIR_IN)? rDIEPCMDPAR0(ucEpNum) : rDOEPCMDPAR0(ucEpNum);
+ u32 uEpPar1Addr = (eEpDir==USBDEV3_EP_DIR_IN)? rDIEPCMDPAR1(ucEpNum) : rDOEPCMDPAR1(ucEpNum);
+
+
+ writel(virt_to_phys((void *)uTrbAddr), uEpPar1Addr);
+ writel(0, uEpPar0Addr);
+
+ usbdev3_depcmd.data = 0;
+ usbdev3_depcmd.b.cmd_type = DEPCMD_CMD_START_XFER;
+ usbdev3_depcmd.b.cmd_active = 1;
+ usbdev3_depcmd.b.param = uStrmidSofn;
+ writel(usbdev3_depcmd.data, uEpCmdAddr);
+
+ if (!exynos_usb_wait_ep_cmd_complete(eEpDir, ucEpNum, CMDCOMPLETEWAIT_UNIT))
+ {
+ return 0;
+ }
+
+ // . Get the Tranfer Resource Index from the start transfer command
+ //--------------------------------------------------------
+ usbdev3_depcmd.data = readl(uEpCmdAddr);
+ *uTri = usbdev3_depcmd.b.param & 0x7f;
+
+ return 1;
+}
+
+static void exynos_usb_fill_trb(usbdev3_trb_ptr_t pTrb, u32 uBufAddr, u32 uLen, u32 uTrbCtrl, u32 uHwo)
+{
+ pTrb->buf_ptr_l = virt_to_phys((void *)uBufAddr);
+ pTrb->buf_ptr_h = 0;
+
+ pTrb->status.data = 0;
+ pTrb->status.b.buf_siz = uLen;
+
+ pTrb->control.data = uTrbCtrl & 0xfffffffeU;
+
+ // must do this last => why?
+ if (uHwo)
+ {
+ pTrb->control.b.hwo = 1;
+ }
+
+}
+
+static int exynos_usb_start_ep0_setup_rx(void)
+{
+ usbdev3_trb_ctrl_t usbdev3_trb_ctrl;
+
+ // . Set TRB for Setup
+ //------------------
+ usbdev3_trb_ctrl.data = 0;
+ usbdev3_trb_ctrl.b.lst = 1;
+ usbdev3_trb_ctrl.b.trb_ctrl = (u32)TRB_CTRL_SETUP;
+ usbdev3_trb_ctrl.b.isp_imi = 1;
+ usbdev3_trb_ctrl.b.ioc = 1;
+ usbdev3_trb_ctrl.b.strmid_sofn = 0;
+
+ exynos_usb_fill_trb(oUsbDev3.m_oSetupTrbPtr, (u32)&oUsbDev3.m_oDeviceRequest,
+ oUsbDev3.m_uControlEPMaxPktSize, usbdev3_trb_ctrl.data, 1);
+
+ // . Issue Start Xfer for EP0-OUT
+ //----------------------------
+ if (!exynos_usb_start_ep_xfer(USBDEV3_EP_DIR_OUT, 0, (u32)oUsbDev3.m_oSetupTrbPtr, 0, &oUsbDev3.m_uTriOut[0]))
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int exynos_usb_init_core(USBDEV3_SPEED_e eSpeed)
+{
+ usbdev3_gsbuscfg0_t usbdev3_gsbuscfg0;
+ usbdev3_gsbuscfg1_t usbdev3_gsbuscfg1;
+ usbdev3_gusb2phycfg_t usbdev3_gusb2phycfg;
+ usbdev3_gusb3pipectl_t usbdev3_gusb3pipectl;
+ usbdev3_gevntsiz_t usbdev3_gevntsiz;
+ usbdev3_dcfg_t usbdev3_dcfg;
+ usbdev3_devten_t usbdev3_devten;
+ u32 uData = 0;
+
+ // . to soft-reset core
+ //-----------------
+ exynos_usb_softreset_core();
+ // . to crport configuration
+ //-----------------
+ exynos_usb_crport_config();
+ // . to configure GSBUSCFG0/1
+ // khs. I should find best setting value for our AP system
+ //----------------------------------------------
+ usbdev3_gsbuscfg0.data = 0;
+ //usbdev3_gsbuscfg0.b.incr_xbrst_ena = 1;
+ //usbdev3_gsbuscfg0.b.incr_4brst_ena = 1;
+ //usbdev3_gsbuscfg0.b.incr_8brst_ena = 1;
+ usbdev3_gsbuscfg0.b.incr_16brst_ena = 1;
+ writel(usbdev3_gsbuscfg0.data, rGSBUSCFG0);
+
+ usbdev3_gsbuscfg1.data = 0x00000300; // reset value
+ writel(usbdev3_gsbuscfg1.data, rGSBUSCFG1);
+
+ // . to configure GTXTHRCFG/GRXTHRCFG
+ //------------------------------------------------
+ // skipped because this sfr is only valid in the host mode
+
+ // . to check IP version
+ //-------------------
+ uData = readl(rGSNPSID);
+ DBG_USBD3("IP version is %1x.%03x\n", (uData&0xf000)>>12, (uData&0x0fff));
+
+ // . to set usb 2.0 phy-related configuration parmeters
+ //---------------------------------------------
+ usbdev3_gusb2phycfg.data = readl(rGUSB2PHYCFG);
+ usbdev3_gusb2phycfg.b.turnaround_time = 9;
+ writel(usbdev3_gusb2phycfg.data, rGUSB2PHYCFG);
+
+ // . to set usb 3.0 phy-related configuration parmeters
+ // (I should find proper setting value)
+ //---------------------------------------------
+ usbdev3_gusb3pipectl.data = 0x00260002; // reset value
+ // usbdev3_gusb3pipectl.data = 0x00240002; // clear suspend bit
+ writel(usbdev3_gusb3pipectl.data, rGUSB3PIPECTL);
+
+ // . to set tx fifo sizes
+ //------------------
+ // skipped because of using default setting
+
+
+ // . to set rx fifo sizes
+ //-------------------
+ // skipped because of using default setting
+
+
+ // . to initialize the Event Buffer registers
+ //-------------------------------------
+ writel(0, rGEVNTADR_HI0);
+ oUsbDev3.m_CurrentEventPosition = 0;
+ writel(virt_to_phys((void *)oUsbDev3.m_pEventBuffer), rGEVNTADR_LO0);
+ usbdev3_gevntsiz.data = 0;
+ usbdev3_gevntsiz.b.event_siz = 4*USBDEV3_EVENT_BUFFER_COUNT;
+ usbdev3_gevntsiz.b.event_int_mask = 0;
+ writel(usbdev3_gevntsiz.data, rGEVNTSIZ0);
+ writel(0, rGEVNTCOUNT0);
+
+ // . to set Gloval Control Register
+ // khs. I should find proper setting value
+ //--------------------------------
+ // writel(rGCTL, 0x30c02000);
+
+ // . to set Device Config. Register
+ //-----------------------------
+ usbdev3_dcfg.data = 0;
+ usbdev3_dcfg.b.dev_speed = (u32) eSpeed;
+ usbdev3_dcfg.b.dev_addr = 0;
+ usbdev3_dcfg.b.per_fr_int = 2; // 90%
+ usbdev3_dcfg.b.intr_num = 0;
+ usbdev3_dcfg.b.num_rx_buf = 1; // khs. 1(simulation code) or 4(reset value)?
+#ifdef USBDEV3_LPM_CAPABLE
+ usbdev3_dcfg.b.lpm_cap = 1;
+#endif
+ writel(usbdev3_dcfg.data, rDCFG);
+
+ // . to enable Global and Device interrupts
+ // (I should find proper setting value)
+ //------------------------------------
+ exynos_usb_disable_eventinterrupt();
+ exynos_usb_flush_eventbuffer();
+ exynos_usb_enable_eventinterrupt();
+
+ usbdev3_devten.data = 0;
+ usbdev3_devten.b.disconn_evt_en = 1;
+ usbdev3_devten.b.usb_reset_en = 1;
+ usbdev3_devten.b.conn_done_en = 1;
+ //usbdev3_devten.b.usb_lnk_sts_chng_en = 1;
+ //usbdev3_devten.b.wake_up_en = 1;
+ //usbdev3_devten.b.errtic_err_en = 1;
+ //usbdev3_devten.b.cmd_cmplt_en = 1;
+ usbdev3_devten.b.evnt_overflow_en = 1;
+ writel(usbdev3_devten.data, rDEVTEN);
+
+ // . to activate EP0
+ //----------------
+ if (!exynos_usb_activate_ep0())
+ {
+ DBG_USBD3("Activate Ep0 Fail\n");
+ return -1;
+ }
+
+ // . to start EP0 to receive SETUP packets
+ //----------------------------------
+ if (!exynos_usb_start_ep0_setup_rx())
+ {
+ DBG_USBD3("Start Ep0 Setup Rx Fail\n");
+ return -1;
+ }
+
+ // . to enable EP0-OUT/IN in DALEPENA register
+ //----------------------------------------
+ exynos_usb_enable_ep(USBDEV3_EP_DIR_OUT, 0);
+ exynos_usb_enable_ep(USBDEV3_EP_DIR_IN, 0);
+
+ // . to set the Run/Stop bit
+ //----------------------
+
+ return 0;
+}
+
+static void exynos_usb_handle_disconnect_int(void)
+{
+ oUsbDev3.m_eUsbDev3State = USBDEV3_STATE_DEFAULT;
+}
+
+static int exynos_usb_end_ep_xfer(USBDEV3_EP_DIR_e eEpDir, u8 ucEpNum, u32 uTri)
+{
+ usbdev3_depcmd_t usbdev3_depcmd;
+ u32 uEpCmdAddr = (eEpDir==USBDEV3_EP_DIR_IN)? rDIEPCMD(ucEpNum) : rDOEPCMD(ucEpNum);
+
+ usbdev3_depcmd.data = 0;
+ usbdev3_depcmd.b.cmd_type = DEPCMD_CMD_END_XFER;
+ usbdev3_depcmd.b.cmd_active = 1;
+ //usbdev3_depcmd.b.hipri_forcerm = 1;
+ usbdev3_depcmd.b.param = uTri;
+ writel(usbdev3_depcmd.data, uEpCmdAddr);
+
+ if (!exynos_usb_wait_ep_cmd_complete(eEpDir, ucEpNum, (10*CMDCOMPLETEWAIT_UNIT))) // wait time is longer than others'
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+static void exynos_usb_handle_reset_int(void)
+{
+ u32 uEpNum;
+ usbdev3_dcfg_t usbdev3_dcfg;
+ usbdev3_dsts_t usbdev3_dsts;
+ usbdev3_dgcmd_t usbdev3_dgcmd;
+ // . Stop All Transfers except for default control EP0
+ //-------------------------------------------
+ // stop any active xfers on the non-EP0 IN endpoints
+ for (uEpNum = 1; uEpNum < TOTL_EP_COUNT; uEpNum++)
+ {
+ if (oUsbDev3.m_uTriIn[uEpNum])
+ {
+ exynos_usb_end_ep_xfer(USBDEV3_EP_DIR_IN, uEpNum, oUsbDev3.m_uTriIn[uEpNum]);
+ oUsbDev3.m_uTriIn[uEpNum] = 0;
+ }
+ }
+
+ // stop any active xfers on the non-EP0 OUT endpoints
+ for (uEpNum = 1; uEpNum < TOTL_EP_COUNT; uEpNum++)
+ {
+ if (oUsbDev3.m_uTriOut[uEpNum])
+ {
+ exynos_usb_end_ep_xfer(USBDEV3_EP_DIR_OUT, uEpNum, oUsbDev3.m_uTriOut[uEpNum]);
+ oUsbDev3.m_uTriOut[uEpNum] = 0;
+ }
+ }
+
+ // . Flush all FIFOs
+ //---------------
+ usbdev3_dgcmd.data= 0;
+ usbdev3_dgcmd.b.cmd_type = DGCMD_CMD_ALL_FIFO_FLUSH;
+ usbdev3_dgcmd.b.cmd_active = 1;
+ writel(usbdev3_dgcmd.data, rDGCMD);
+
+ // wait until command is completed
+ do
+ {
+ udelay(1);
+ usbdev3_dgcmd.data = readl(rDGCMD);
+ }while(usbdev3_dgcmd.b.cmd_active);
+
+ // wait until Rx FIFO becomes empty
+ do
+ {
+ udelay(1);
+ usbdev3_dsts.data = readl(rDSTS);
+ }while(!(usbdev3_dsts.b.rx_fifo_empty));
+
+ // . Issue a DEPCSTALL command for any stalled EP
+ //--------------------------------------------
+ // this routine is necessary???
+
+ // . Set Device Address to 0
+ //-----------------------
+ usbdev3_dcfg.data = readl(rDCFG);
+ usbdev3_dcfg.b.dev_addr = 0;
+ writel(usbdev3_dcfg.data, rDCFG);
+
+ // . Set Device State to Default
+ //--------------------------
+ oUsbDev3.m_eUsbDev3State = USBDEV3_STATE_DEFAULT;
+}
+
+static void exynos_usb_set_maxpktsizes(USBDEV3_SPEED_e eSpeed)
+{
+ oUsbDev3.m_eSpeed = eSpeed;
+
+ if (eSpeed == USBDEV3_SPEED_SUPER)
+ {
+ oUsbDev3.m_uControlEPMaxPktSize = SUPER_SPEED_CONTROL_PKT_SIZE;
+ oUsbDev3.m_uBulkEPMaxPktSize = SUPER_SPEED_BULK_PKT_SIZE;
+ }
+ else if (eSpeed == USBDEV3_SPEED_HIGH)
+ {
+ oUsbDev3.m_uControlEPMaxPktSize = HIGH_SPEED_CONTROL_PKT_SIZE;
+ oUsbDev3.m_uBulkEPMaxPktSize = HIGH_SPEED_BULK_PKT_SIZE;
+ }
+ else
+ {
+ oUsbDev3.m_uControlEPMaxPktSize = FULL_SPEED_CONTROL_PKT_SIZE;
+ oUsbDev3.m_uBulkEPMaxPktSize = FULL_SPEED_BULK_PKT_SIZE;
+ }
+}
+
+static void exynos_usb_get_connected_speed(USBDEV3_SPEED_e *eSpeed)
+{
+ usbdev3_dsts_t usbdev3_dsts;
+
+ usbdev3_dsts.data = readl(rDSTS);
+
+ *eSpeed = (USBDEV3_SPEED_e)usbdev3_dsts.b.connect_speed;
+}
+
+static void exynos_usb_handle_connect_done_int(void)
+{
+ USBDEV3_SPEED_e eSpeed;
+ usbdev3_gusb2phycfg_t usbdev3_gusb2phycfg;
+ usbdev3_gusb3pipectl_t usbdev3_gusb3pipectl;
+
+ usbdev3_depcmdpar0_set_ep_cfg_t usbdev3_depcmdpar0_set_ep_cfg;
+ usbdev3_depcmdpar1_set_ep_cfg_t usbdev3_depcmdpar1_set_ep_cfg;
+
+ oUsbDev3.m_uEp0State = EP0_STATE_INIT;
+
+ // . Get the connected speed
+ //------------------------
+ exynos_usb_get_connected_speed(&eSpeed);
+
+ // . Suspend the Inactive PHY
+ //-------------------------
+ if (eSpeed == USBDEV3_SPEED_SUPER)
+ {
+ usbdev3_gusb2phycfg.data = readl(rGUSB2PHYCFG);
+ usbdev3_gusb2phycfg.b.suspend_usb2_phy = 1;
+ writel(usbdev3_gusb2phycfg.data, rGUSB2PHYCFG);
+ }
+ else
+ {
+ usbdev3_gusb3pipectl.data = readl(rGUSB3PIPECTL);
+ usbdev3_gusb3pipectl.b.suspend_usb3_ss_phy = 1;
+ writel(usbdev3_gusb3pipectl.data, rGUSB3PIPECTL);
+ }
+
+ // . Set Max Packet Size based on enumerated speed
+ //----------------------------------------------
+ switch(eSpeed) {
+ case USBDEV3_SPEED_SUPER :
+ exynos_usb_set_maxpktsizes(USBDEV3_SPEED_SUPER);
+ DBG_USBD3("(Enumerated Speed : Super)\n");
+ break;
+
+ case USBDEV3_SPEED_HIGH :
+ exynos_usb_set_maxpktsizes(USBDEV3_SPEED_HIGH);
+ DBG_USBD3("(Enumerated Speed : High)\n");
+ break;
+
+ case USBDEV3_SPEED_FULL :
+ exynos_usb_set_maxpktsizes(USBDEV3_SPEED_FULL);
+ DBG_USBD3("(Enumerated Speed : Full)\n");
+ break;
+
+ default :
+ return;
+ }
+
+ // . Issue Set Ep Configuraton for EP0-OUT/IN based on the connected speed
+ //----------------------------------------------------------------
+ usbdev3_depcmdpar0_set_ep_cfg.data = 0;
+ usbdev3_depcmdpar0_set_ep_cfg.b.ep_type = USBDEV3_EP_CTRL;
+ usbdev3_depcmdpar0_set_ep_cfg.b.mps = oUsbDev3.m_uControlEPMaxPktSize;
+ usbdev3_depcmdpar0_set_ep_cfg.b.ign_dsnum = 1; // to avoid resetting the sequnece number
+
+ usbdev3_depcmdpar1_set_ep_cfg.data = 0;
+ usbdev3_depcmdpar1_set_ep_cfg.b.xfer_cmpl_en = 1;
+ //usbdev3_depcmdpar1_set_ep_cfg.b.xfer_in_prog_en = 1;
+ usbdev3_depcmdpar1_set_ep_cfg.b.xfer_nrdy_en = 1;
+ usbdev3_depcmdpar1_set_ep_cfg.b.ep_dir = USBDEV3_EP_DIR_OUT;
+ usbdev3_depcmdpar1_set_ep_cfg.b.ep_num = 0;
+
+ if (!exynos_usb_set_ep_cfg(USBDEV3_EP_DIR_OUT, 0, usbdev3_depcmdpar0_set_ep_cfg.data, usbdev3_depcmdpar1_set_ep_cfg.data))
+ {
+ return ;
+ }
+
+ usbdev3_depcmdpar1_set_ep_cfg.b.ep_dir = USBDEV3_EP_DIR_IN;
+ if (!exynos_usb_set_ep_cfg(USBDEV3_EP_DIR_IN, 0, usbdev3_depcmdpar0_set_ep_cfg.data, usbdev3_depcmdpar1_set_ep_cfg.data))
+ {
+ return ;
+ }
+
+ // . Prepare Descriptor Table
+ //------------------------
+ if (is_fastboot)
+ fboot_usb_set_descriptors_tlb();
+ else
+ exynos_usb_set_descriptor_tlb();
+}
+
+static void exynos_usb_handle_dev_event(usbdev3_devt_t uDevEvent)
+{
+ switch (uDevEvent.b.evt_type)
+ {
+ case DEVT_DISCONN:
+ DBG_USBD3("Disconnect\n");
+ exynos_usb_handle_disconnect_int();
+ break;
+
+ case DEVT_USBRESET:
+ DBG_USBD3("USB Reset\n");
+ exynos_usb_handle_reset_int();
+ break;
+
+ case DEVT_CONNDONE:
+ DBG_USBD3("Connect Done\n");
+ exynos_usb_handle_connect_done_int();
+ break;
+
+ case DEVT_WKUP:
+ DBG_USBD3("Wakeup\n");
+ //USBDEV3_HandleWakeupDetectedInt();
+ break;
+
+ case DEVT_ULST_CHNG:
+ DBG_USBD3("Link Status Change\n");
+ //USBDEV3_HandleLinkStatusChange();
+ break;
+
+ case DEVT_EOPF:
+ DBG_USBD3("End of Periodic Frame\n");
+ //USBDEV3_HandleEndPeriodicFrameInt();
+ break;
+
+ case DEVT_SOF:
+ DBG_USBD3("Start of Frame\n");
+ //USBDEV3_HandleSofInt();
+ break;
+
+ case DEVT_ERRATICERR:
+ DBG_USBD3("Erratic Error\n");
+ break;
+
+ case DEVT_CMD_CMPL:
+ DBG_USBD3("Command Complete\n");
+ break;
+
+ case DEVT_OVERFLOW:
+ DBG_USBD3("Overflow\n");
+ break;
+
+ default:
+ DBG_USBD3("Unknown event!\n");
+ }
+
+}
+
+static void exynos_usb_handle_ep0_in_xfer_complete(void)
+{
+ switch (oUsbDev3.m_uEp0State) {
+ case EP0_STATE_IN_DATA_PHASE:
+ oUsbDev3.m_uEp0State = EP0_STATE_OUT_WAIT_NRDY;
+ break;
+
+ case EP0_STATE_IN_STATUS_PHASE:
+ oUsbDev3.m_uEp0State = EP0_STATE_INIT;
+
+ // . to start EP0 to receive SETUP packets
+ //----------------------------------
+ if (!exynos_usb_start_ep0_setup_rx())
+ {
+ return;
+ }
+ break;
+
+ // khs. this routine is abnormal case, and handling for this case is not prepared.
+ default :
+ DBG_USBD3("\nError : [EP0-InXferComplete]Not Supported @%d\n", oUsbDev3.m_uEp0State);
+ break;
+ }
+}
+
+static void exynos_usb_handle_ep_in_xfer_complete(void)
+{
+ g_uCntOfDescOutComplete = 0;
+
+ g_bIsBulkInXferDone = 1;
+
+ exynos_usb_free((u32)g_pBulkInTrbArray_Base);
+
+ oUsbDev3.m_pUpPt += oUsbDev3.m_uUploadSize;
+ DBG_USBD3("DMA IN : Transfer Complete\n");
+ if (oUsbDev3.m_uUploadSize > 0) {
+ exynos_receive_done = 1;
+ printf("Upload Done!! Upload Address: 0x%x, Upload Filesize:0x%x\n",
+ oUsbDev3.m_uUploadAddr, (oUsbDev3.m_uUploadSize));
+ }
+
+}
+
+static int exynos_usb_start_ep0_in_xfer(u32 pBufAddr, u32 uLen)
+{
+ usbdev3_trb_ctrl_t usbdev3_trb_ctrl;
+
+ usbdev3_trb_ctrl.data = 0;
+
+ if (oUsbDev3.m_uEp0State == EP0_STATE_IN_STATUS_PHASE) {
+ if (oUsbDev3.m_bEp0ThreeStage)
+ usbdev3_trb_ctrl.b.trb_ctrl = (u32)TRB_CTRL_STATUS_3;
+ else
+ usbdev3_trb_ctrl.b.trb_ctrl = (u32)TRB_CTRL_STATUS_2;
+ } else {
+ usbdev3_trb_ctrl.b.trb_ctrl = (u32)TRB_CTRL_CTLDATA_1ST;
+ }
+
+ usbdev3_trb_ctrl.b.lst = 1;
+ usbdev3_trb_ctrl.b.isp_imi = 1;
+ usbdev3_trb_ctrl.b.ioc = 1;
+ usbdev3_trb_ctrl.b.strmid_sofn = 0;
+
+ exynos_usb_fill_trb(oUsbDev3.m_oInTrbPtr, pBufAddr, uLen, usbdev3_trb_ctrl.data, 1);
+
+ // . Issue Start Xfer for EP0-IN
+ //----------------------------
+ if (!exynos_usb_start_ep_xfer(USBDEV3_EP_DIR_IN, 0, (u32)oUsbDev3.m_oInTrbPtr, 0, &oUsbDev3.m_uTriIn[0]))
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int exynos_usb_start_ep0_out_xfer(u32 pBufAddr, u32 uLen)
+{
+ usbdev3_trb_ctrl_t usbdev3_trb_ctrl;
+
+ usbdev3_trb_ctrl.data = 0;
+
+ if (oUsbDev3.m_uEp0State == EP0_STATE_OUT_STATUS_PHASE) {
+ if (oUsbDev3.m_bEp0ThreeStage)
+ usbdev3_trb_ctrl.b.trb_ctrl = (u32)TRB_CTRL_STATUS_3;
+ else
+ usbdev3_trb_ctrl.b.trb_ctrl = (u32)TRB_CTRL_STATUS_2;
+ } else {
+ usbdev3_trb_ctrl.b.trb_ctrl = (u32)TRB_CTRL_CTLDATA_1ST;
+ }
+
+ usbdev3_trb_ctrl.b.lst = 1;
+ usbdev3_trb_ctrl.b.isp_imi = 1;
+ usbdev3_trb_ctrl.b.ioc = 1;
+ usbdev3_trb_ctrl.b.strmid_sofn = 0;
+
+ exynos_usb_fill_trb(oUsbDev3.m_oOutTrbPtr, pBufAddr, uLen, usbdev3_trb_ctrl.data, 1);
+
+ // . Issue Start Xfer for EP0-OUT
+ //----------------------------
+ if (!exynos_usb_start_ep_xfer(USBDEV3_EP_DIR_OUT, 0, (u32)oUsbDev3.m_oOutTrbPtr, 0, &oUsbDev3.m_uTriOut[0]))
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+static void exynos_usb_setup_in_status_phase(void)
+{
+
+ DBG_USBD3("Setup EP0 IN ZLP\n");
+
+ oUsbDev3.m_uEp0State = EP0_STATE_IN_STATUS_PHASE;
+
+ exynos_usb_start_ep0_in_xfer(oUsbDev3.m_uStatusBufAddr, 0);
+}
+
+static void exynos_usb_setup_out_status_phase(void)
+{
+ DBG_USBD3("Setup EP0 OUT ZLP\n");
+
+ oUsbDev3.m_uEp0State = EP0_STATE_OUT_STATUS_PHASE;
+
+ exynos_usb_start_ep0_out_xfer((u32)&oUsbDev3.m_oDeviceRequest, 0);
+}
+
+static void exynos_usb_handle_ep0_in_xfer_not_ready(void)
+{
+ switch (oUsbDev3.m_uEp0State) {
+ case EP0_STATE_IN_WAIT_NRDY:
+ // . to setup in-status phase
+ exynos_usb_setup_in_status_phase();
+ break;
+
+ // khs. this routine is abnormal case, and handling for this case is not prepared.
+ default :
+ DBG_USBD3("\nError : [EP0-InXferNotReady]Not Supported @%d\n", oUsbDev3.m_uEp0State);
+ break;
+ }
+}
+
+static void exynos_usb_handle_ep_in_event(usbdev3_depevt_t uEpInEvent)
+{
+ u32 uEpNum = uEpInEvent.b.ep_num/2; // 1,3,5,7,...
+
+ DBG_USBD3("[EP%d] IN State = 0x%x Type = 0x%x[%x]\n", uEpNum, oUsbDev3.m_uEp0State, uEpInEvent.b.evt_type, uEpInEvent.data);
+ switch (uEpInEvent.b.evt_type)
+ {
+ case DEPEVT_EVT_XFER_CMPL:
+ DBG_USBD3("[EP%d] IN xfer complete @%d\n", uEpNum, oUsbDev3.m_uEp0State);
+ if (uEpNum == 0)
+ exynos_usb_handle_ep0_in_xfer_complete();
+ else if (uEpNum == BULK_IN_EP) {
+ if (is_fastboot)
+ fboot_usb_handle_ep_in_xfer_complete();
+ else
+ exynos_usb_handle_ep_in_xfer_complete();
+ }
+ else
+ Assert(0);
+ break;
+
+ case DEPEVT_EVT_XFER_IN_PROG:
+ DBG_USBD3("[EP%d] IN xfer in progress @%d\n", uEpNum, oUsbDev3.m_uEp0State);
+ break;
+
+ case DEPEVT_EVT_XFER_NRDY:
+ DBG_USBD3("[EP%d] IN xfer not ready @%d\n", uEpNum, oUsbDev3.m_uEp0State);
+ if (uEpNum == 0)
+ exynos_usb_handle_ep0_in_xfer_not_ready();
+ break;
+
+ case DEPEVT_EVT_FIFOXRUN:
+ DBG_USBD3("[EP%d] IN FIFO Underrun Error @%d\n", uEpNum, oUsbDev3.m_uEp0State);
+ break;
+
+ case DEPEVT_EVT_STRM_EVT:
+ DBG_USBD3("[EP%d] IN Stream Event @%d\n", uEpNum, oUsbDev3.m_uEp0State);
+ break;
+
+ case DEPEVT_EVT_EPCMD_CMPL:
+ DBG_USBD3("[EP%d] IN Command Complete @%d\n", uEpNum, oUsbDev3.m_uEp0State);
+ break;
+
+ default:
+ DBG_USBD3("Unknown event!\n");
+ }
+}
+
+static int exynos_usb_prepare_1st_bulk_out_trb(void)
+{
+ usbdev3_trb_ctrl_t usbdev3_trb_ctrl;
+
+ g_bIsBulkOutXferDone = 0;
+ g_bIsBulkInXferDone = 0;
+
+ g_pBulkOutTrb0 = (usbdev3_trb_ptr_t)exynos_usb_malloc(sizeof(usbdev3_trb_t), USBDEV3_MDWIDTH/8);
+ if (g_pBulkOutTrb0 == NULL)
+ {
+ Assert(0);
+ }
+ /* size + 1 is for fastboot */
+ g_ucTempDownBuf = (u8 *)exynos_usb_malloc(4096 + 1, USBDEV3_MDWIDTH/8);
+
+ if (g_ucTempDownBuf == NULL)
+ {
+ Assert(0);
+ }
+
+ // . Set TRB for 1st Bulk Out Packet
+ //-----------------------------
+ usbdev3_trb_ctrl.data = 0;
+ usbdev3_trb_ctrl.b.lst = 1;
+ usbdev3_trb_ctrl.b.trb_ctrl = (u32)TRB_CTRL_NORMAL;
+ usbdev3_trb_ctrl.b.isp_imi = 1;
+ usbdev3_trb_ctrl.b.ioc = 1;
+ usbdev3_trb_ctrl.b.strmid_sofn = 0;
+
+ exynos_usb_fill_trb(g_pBulkOutTrb0, (u32)g_ucTempDownBuf, oUsbDev3.m_uBulkEPMaxPktSize, usbdev3_trb_ctrl.data, 1);
+
+ // . Issue Start Xfer for 1st Bulk Out Packet
+ //------------------------------------
+ if (!exynos_usb_start_ep_xfer(USBDEV3_EP_DIR_OUT, BULK_OUT_EP, (u32)g_pBulkOutTrb0, 0, &oUsbDev3.m_uTriOut[BULK_OUT_EP]))
+ {
+ return 0;
+ }
+ return 1;
+}
+
+void exynos_usb_handle_setup(void)
+{
+ const u8 *string_desc1, *string_desc2, *string_desc3;
+ usbdev3_dcfg_t usbdev3_dcfg;
+ u32 uRemoteWakeUp = 0;
+
+ exynos_usb_print_ep0_pkt((u8 *)&oUsbDev3.m_oDeviceRequest, 8);
+
+ // . sort Request type
+ //-------------------
+ switch(oUsbDev3.m_oDeviceRequest.bmRequestType & 0x60) {
+ case STANDARD_TYPE:
+ break;
+
+ case CLASS_TYPE:
+ DBG_USBD3("Class Type Request is not supported yet\n");
+ return;
+
+ case VENDOR_TYPE:
+ DBG_USBD3("Vendor Type Request is not supported yet\n");
+ return;
+
+ default:
+ DBG_USBD3("0x%02x Type Request is not supported yet\n", oUsbDev3.m_oDeviceRequest.bmRequestType & 0x60);
+ return;
+ }
+
+ // . distinguish host2dev from dev2host
+ if (oUsbDev3.m_oDeviceRequest.bmRequestType & 0x80)
+ oUsbDev3.m_uEp0State = EP0_STATE_IN_DATA_PHASE;
+ else
+ oUsbDev3.m_uEp0State = EP0_STATE_OUT_DATA_PHASE;
+
+ // . find requestlength and decide whether control xfer is 2 stage or 3 stage
+ oUsbDev3.m_uDeviceRequestLength = (u32)((oUsbDev3.m_oDeviceRequest.wLength_H << 8) | oUsbDev3.m_oDeviceRequest.wLength_L);
+
+ oUsbDev3.m_bEp0ThreeStage = 1;
+
+ if (oUsbDev3.m_uDeviceRequestLength == 0)
+ {
+ oUsbDev3.m_uEp0State = EP0_STATE_IN_WAIT_NRDY;
+ oUsbDev3.m_bEp0ThreeStage = 0;
+ }
+
+
+ // . handle standard type request
+ //-----------------------------
+ switch(oUsbDev3.m_oDeviceRequest.bRequest) {
+ case STANDARD_SET_ADDRESS:
+ usbdev3_dcfg.data = readl(rDCFG);
+ usbdev3_dcfg.b.dev_addr = oUsbDev3.m_oDeviceRequest.wValue_L;
+ writel(usbdev3_dcfg.data, rDCFG);
+
+ DBG_USBD3("\n MCU >> Set Address : %d \n", usbdev3_dcfg.b.dev_addr);
+
+ oUsbDev3.m_eUsbDev3State = USBDEV3_STATE_ADDRESSED;
+ break;
+
+ case STANDARD_SET_DESCRIPTOR:
+ DBG_USBD3("\n MCU >> Set Descriptor \n");
+ break;
+
+ case STANDARD_SET_CONFIGURATION:
+ DBG_USBD3("\n MCU >> Set Configuration \n");
+ if (oUsbDev3.m_eSpeed == USBDEV3_SPEED_SUPER)
+ printf("Super speed enumeration success\n");
+ g_usConfig = oUsbDev3.m_oDeviceRequest.wValue_L; // Configuration value in configuration descriptor
+ oUsbDev3.m_eUsbDev3State = USBDEV3_STATE_CONFIGURED;
+
+ // . to activate endpoints for bulk xfer
+ exynos_usb_activate_ep(USBDEV3_EP_DIR_IN, BULK_IN_EP);
+ exynos_usb_activate_ep(USBDEV3_EP_DIR_OUT, BULK_OUT_EP);
+
+ // . to enable endpoints for bulk xfer
+ exynos_usb_enable_ep(USBDEV3_EP_DIR_IN, BULK_IN_EP);
+ exynos_usb_enable_ep(USBDEV3_EP_DIR_OUT, BULK_OUT_EP);
+
+ exynos_usb_prepare_1st_bulk_out_trb();
+ break;
+
+ case STANDARD_GET_CONFIGURATION:
+ exynos_usb_start_ep0_in_xfer((u32)&g_usConfig, 1);
+ break;
+
+ case STANDARD_GET_DESCRIPTOR:
+ switch (oUsbDev3.m_oDeviceRequest.wValue_H)
+ {
+ case DEVICE_DESCRIPTOR:
+ oUsbDev3.m_uDeviceRequestLength = (u32)((oUsbDev3.m_oDeviceRequest.wLength_H << 8) |
+ oUsbDev3.m_oDeviceRequest.wLength_L);
+ DBG_USBD3("\n MCU >> Get Device Descriptor = 0x%x \n",oUsbDev3.m_uDeviceRequestLength);
+
+ if (oUsbDev3.m_uDeviceRequestLength<=DEVICE_DESC_SIZE)
+ {
+ exynos_usb_start_ep0_in_xfer(((u32)&(oUsbDev3.m_oDesc.oDescDevice))+0, oUsbDev3.m_uDeviceRequestLength);
+ }
+ else
+ {
+ exynos_usb_start_ep0_in_xfer(((u32)&(oUsbDev3.m_oDesc.oDescDevice))+0, DEVICE_DESC_SIZE);
+ }
+ break;
+
+ case CONFIGURATION_DESCRIPTOR:
+ oUsbDev3.m_uDeviceRequestLength = (u32)((oUsbDev3.m_oDeviceRequest.wLength_H << 8) |
+ oUsbDev3.m_oDeviceRequest.wLength_L);
+ DBG_USBD3("\n MCU >> Get Configuration Descriptor = 0x%x \n",oUsbDev3.m_uDeviceRequestLength);
+
+ if (oUsbDev3.m_uDeviceRequestLength > CONFIG_DESC_SIZE){
+ // === GET_DESCRIPTOR:CONFIGURATION+INTERFACE+ENDPOINT0+ENDPOINT1 ===
+ // Windows98 gets these 4 descriptors all together by issuing only a request.
+ // Windows2000 gets each descriptor seperately.
+ // oUsbDev3.m_uEpZeroTransferLength = CONFIG_DESC_TOTAL_SIZE;
+ if(oUsbDev3.m_uDeviceRequestLength<=oUsbDev3.m_oDesc.oDescConfig.wTotalLengthL)
+ {
+ exynos_usb_start_ep0_in_xfer(((u32)&(oUsbDev3.m_oDesc.oDescConfig))+0, oUsbDev3.m_uDeviceRequestLength);
+ }
+ else
+ {
+ exynos_usb_start_ep0_in_xfer(((u32)&(oUsbDev3.m_oDesc.oDescConfig))+0, oUsbDev3.m_oDesc.oDescConfig.wTotalLengthL);
+ }
+ }
+ else // for win2k
+ {
+ if(oUsbDev3.m_uDeviceRequestLength<=CONFIG_DESC_SIZE)
+ {
+ exynos_usb_start_ep0_in_xfer(((u32)&(oUsbDev3.m_oDesc.oDescConfig))+0, oUsbDev3.m_uDeviceRequestLength);
+ }
+ else
+ {
+ exynos_usb_start_ep0_in_xfer(((u32)&(oUsbDev3.m_oDesc.oDescConfig))+0, CONFIG_DESC_SIZE);
+ }
+ }
+ break;
+
+ case STRING_DESCRIPTOR :
+ DBG_USBD3("\n MCU >> Get String Descriptor \n");
+ if (is_fastboot) {
+ string_desc1 = fboot_string_desc1;
+ string_desc2 = fboot_string_desc2;
+ string_desc3 = fboot_string_desc3;
+ } else {
+ string_desc1 = dnw_string_desc1;
+ string_desc2 = dnw_string_desc2;
+ }
+
+ switch(oUsbDev3.m_oDeviceRequest.wValue_L)
+ {
+ case 0:
+ exynos_usb_start_ep0_in_xfer((u32)string_desc0, STRING_DESC0_SIZE);
+ break;
+ case 1:
+ exynos_usb_start_ep0_in_xfer((u32)string_desc1, STRING_DESC1_SIZE);
+ break;
+ case 2:
+ exynos_usb_start_ep0_in_xfer((u32)string_desc2, STRING_DESC2_SIZE);
+ break;
+ case 3:
+ exynos_usb_start_ep0_in_xfer((u32)string_desc2, STRING_DESC2_SIZE);
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case ENDPOINT_DESCRIPTOR:
+ DBG_USBD3("\n MCU >> Get Endpoint Descriptor \n");
+ switch(oUsbDev3.m_oDeviceRequest.wValue_L&0xf)
+ {
+ case 0:
+ if (oUsbDev3.m_eSpeed == USBDEV3_SPEED_SUPER)
+ exynos_usb_start_ep0_in_xfer((u32)&(oUsbDev3.m_oSSDesc.oDescEp0), ENDPOINT_DESC_SIZE+ENDPOINT_COMP_DESC_SIZE);
+ else
+ exynos_usb_start_ep0_in_xfer((u32)&(oUsbDev3.m_oDesc.oDescEp0), ENDPOINT_DESC_SIZE);
+ break;
+ case 1:
+ if (oUsbDev3.m_eSpeed == USBDEV3_SPEED_SUPER)
+ exynos_usb_start_ep0_in_xfer((u32)&(oUsbDev3.m_oSSDesc.oDescEp1), ENDPOINT_DESC_SIZE+ENDPOINT_COMP_DESC_SIZE);
+ else
+ exynos_usb_start_ep0_in_xfer((u32)&(oUsbDev3.m_oDesc.oDescEp1), ENDPOINT_DESC_SIZE);
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case DEVICE_QUALIFIER: // only supported in over 2.0
+ oUsbDev3.m_uDeviceRequestLength = (u32)((oUsbDev3.m_oDeviceRequest.wLength_H << 8) |
+ oUsbDev3.m_oDeviceRequest.wLength_L);
+ DBG_USBD3("\n MCU >> Get Device Qualifier Descriptor = 0x%x \n",oUsbDev3.m_uDeviceRequestLength);
+
+ if(oUsbDev3.m_uDeviceRequestLength<=10)
+ {
+ exynos_usb_start_ep0_in_xfer((u32)qualifier_desc, oUsbDev3.m_uDeviceRequestLength);
+ }
+ else
+ {
+ exynos_usb_start_ep0_in_xfer((u32)qualifier_desc, 10);
+ }
+ break;
+
+ case OTHER_SPEED_CONFIGURATION :
+ DBG_USBD3(("\n MCU >> Get OTHER_SPEED_CONFIGURATION \n"));
+ oUsbDev3.m_uDeviceRequestLength = (u32)((oUsbDev3.m_oDeviceRequest.wLength_H << 8) |
+ oUsbDev3.m_oDeviceRequest.wLength_L);
+
+ if (oUsbDev3.m_eSpeed == USBDEV3_SPEED_HIGH)
+ {
+ if (oUsbDev3.m_uDeviceRequestLength ==9)
+ {
+ exynos_usb_start_ep0_in_xfer((u32)config_high, 9);
+ }
+ else if(oUsbDev3.m_uDeviceRequestLength ==32)
+ {
+ exynos_usb_start_ep0_in_xfer((u32)config_high_total, 32);
+ }
+ }
+ else if (oUsbDev3.m_eSpeed == USBDEV3_SPEED_FULL)
+ {
+ if (oUsbDev3.m_uDeviceRequestLength ==9)
+ {
+ exynos_usb_start_ep0_in_xfer((u32)config_full, 9);
+ }
+ else if(oUsbDev3.m_uDeviceRequestLength ==32)
+ {
+ exynos_usb_start_ep0_in_xfer((u32)config_full_total, 32);
+ }
+ }
+ else // super
+ {
+ DBG_USBD3("\n %s(line %d)\n", __FILE__, __LINE__);
+ DBG_USBD3("Error : Not implemented yet\n");
+ }
+
+ break;
+ case BOS :
+ if (oUsbDev3.m_uDeviceRequestLength == BOS_DESC_SIZE)
+ exynos_usb_start_ep0_in_xfer((u32)&oUsbDev3.m_oSSDesc.oDescBos, BOS_DESC_SIZE);
+ else
+ exynos_usb_start_ep0_in_xfer((u32)&oUsbDev3.m_oSSDesc.oDescBos, BOS_DESC_TOTAL_SIZE);
+ break;
+ }
+ break;
+
+ case STANDARD_CLEAR_FEATURE:
+ DBG_USBD3("\n MCU >> Clear Feature \n");
+ switch (oUsbDev3.m_oDeviceRequest.bmRequestType)
+ {
+ case DEVICE_RECIPIENT:
+ if (oUsbDev3.m_oDeviceRequest.wValue_L == 1)
+ uRemoteWakeUp = 0;
+ break;
+
+ case ENDPOINT_RECIPIENT:
+ if (oUsbDev3.m_oDeviceRequest.wValue_L == 0)
+ {
+ if ((oUsbDev3.m_oDeviceRequest.wIndex_L & 0x7f) == CONTROL_EP)
+ oStatusGet.EndpointCtrl= 0;
+
+ if ((oUsbDev3.m_oDeviceRequest.wIndex_L & 0x7f) == BULK_IN_EP) // IN Endpoint
+ oStatusGet.EndpointIn= 0;
+
+ if ((oUsbDev3.m_oDeviceRequest.wIndex_L & 0x7f) == BULK_OUT_EP) // OUT Endpoint
+ oStatusGet.EndpointOut= 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case STANDARD_SET_FEATURE:
+ DBG_USBD3("\n MCU >> Set Feature \n");
+ switch (oUsbDev3.m_oDeviceRequest.bmRequestType)
+ {
+ case DEVICE_RECIPIENT:
+ if (oUsbDev3.m_oDeviceRequest.wValue_L == 1)
+ uRemoteWakeUp = 1;
+ break;
+
+ case ENDPOINT_RECIPIENT:
+ if (oUsbDev3.m_oDeviceRequest.wValue_L == 0)
+ {
+ if ((oUsbDev3.m_oDeviceRequest.wIndex_L & 0x7f) == CONTROL_EP)
+ oStatusGet.EndpointCtrl= 1;
+
+ if ((oUsbDev3.m_oDeviceRequest.wIndex_L & 0x7f) == BULK_IN_EP)
+ oStatusGet.EndpointIn= 1;
+
+ if ((oUsbDev3.m_oDeviceRequest.wIndex_L & 0x7f) == BULK_OUT_EP)
+ oStatusGet.EndpointOut= 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ //=======================================================
+
+ switch (oUsbDev3.m_oDeviceRequest.wValue_L) {
+
+ case EP_STALL:
+ // TBD: additional processing if required
+ break;
+
+
+ case TEST_MODE:
+ if ((0 != oUsbDev3.m_oDeviceRequest.wIndex_L ) ||(0 != oUsbDev3.m_oDeviceRequest.bmRequestType))
+ {
+ DBG_USBD3("\n %s(line %d)\n", __FILE__, __LINE__);
+ DBG_USBD3("Error : Wrong Request Parameter\n");
+ break;
+ }
+
+ switch(oUsbDev3.m_oDeviceRequest.wIndex_H)
+ {
+ usbdev3_dctl_t usbdev3_dctl;
+
+ case TEST_J:
+ //Set Test J
+ exynos_usb_start_ep0_in_xfer((u32)NULL, 0);
+ DBG_USBD3 ("Test_J\n");
+ usbdev3_dctl.data = readl(rDCTL);
+ usbdev3_dctl.b.test_ctrl = (u32)DCTL_TEST_J_MODE;
+ writel(usbdev3_dctl.data, rDCTL);
+ break;
+
+ case TEST_K:
+ //Set Test K
+ exynos_usb_start_ep0_in_xfer((u32)NULL, 0);
+ DBG_USBD3 ("Test_K\n");
+ usbdev3_dctl.data = readl(rDCTL);
+ usbdev3_dctl.b.test_ctrl = (u32)DCTL_TEST_K_MODE;
+ writel(usbdev3_dctl.data, rDCTL);
+ break;
+
+ case TEST_SE0_NAK:
+ //Set Test SE0_NAK
+ exynos_usb_start_ep0_in_xfer((u32)NULL, 0);
+ DBG_USBD3 ("Test_SE0_NAK\n");
+ usbdev3_dctl.data = readl(rDCTL);
+ usbdev3_dctl.b.test_ctrl = (u32)DCTL_TEST_SE0_NAK_MODE;
+ writel(usbdev3_dctl.data, rDCTL);
+ break;
+
+ case TEST_PACKET:
+ //Set Test Packet
+ exynos_usb_start_ep0_in_xfer((u32)NULL, 0);
+
+ // khs. Is this routine necessary?
+ //exynos_usb_start_ep0_in_xfer((u32)TestPkt, TEST_PKT_SIZE);
+
+ DBG_USBD3 ("Test_Packet\n");
+ usbdev3_dctl.data = readl(rDCTL);
+ usbdev3_dctl.b.test_ctrl = (u32)DCTL_TEST_PACKET_MODE;
+ writel(usbdev3_dctl.data, rDCTL);
+ break;
+
+ case TEST_FORCE_ENABLE:
+ //Set Test Force Enable
+ exynos_usb_start_ep0_in_xfer((u32)NULL, 0);
+ DBG_USBD3 ("Test_Force_Enable\n");
+ usbdev3_dctl.data = readl(rDCTL);
+ usbdev3_dctl.b.test_ctrl = (u32)DCTL_TEST_FORCE_ENABLE;
+ writel(usbdev3_dctl.data, rDCTL);
+ break;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+ //=======================================================
+ break;
+
+ case STANDARD_GET_STATUS:
+ switch(oUsbDev3.m_oDeviceRequest.bmRequestType)
+ {
+ case (0x80): //device
+ oStatusGet.Device=((u8)uRemoteWakeUp<<1)|0x1; // SelfPowered
+ exynos_usb_start_ep0_in_xfer((u32)&oStatusGet.Device, 1);
+ break;
+
+ case (0x81): //interface
+ oStatusGet.Interface=0;
+ exynos_usb_start_ep0_in_xfer((u32)&oStatusGet.Interface, 1);
+ break;
+
+ case (0x82): //endpoint
+ if ((oUsbDev3.m_oDeviceRequest.wIndex_L & 0x7f) == CONTROL_EP)
+ exynos_usb_start_ep0_in_xfer((u32)&oStatusGet.EndpointCtrl, 1);
+
+ if ((oUsbDev3.m_oDeviceRequest.wIndex_L & 0x7f) == BULK_IN_EP)
+ exynos_usb_start_ep0_in_xfer((u32)&oStatusGet.EndpointIn, 1);
+
+ if ((oUsbDev3.m_oDeviceRequest.wIndex_L & 0x7f) == BULK_OUT_EP)
+ exynos_usb_start_ep0_in_xfer((u32)&oStatusGet.EndpointOut, 1);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case STANDARD_GET_INTERFACE:
+ exynos_usb_start_ep0_in_xfer((u32)&oInterfaceGet.AlternateSetting, 1);
+ break;
+
+ case STANDARD_SET_INTERFACE:
+ oInterfaceGet.AlternateSetting= oUsbDev3.m_oDeviceRequest.wValue_L;
+ break;
+
+ case STANDARD_SYNCH_FRAME:
+ break;
+
+ case STANDARD_SET_SEL:
+ oUsbDev3.m_bReq_Set_sel= 1;
+ /* For SET_SEL */
+ exynos_usb_start_ep0_out_xfer((u32)&set_sel, oUsbDev3.m_uControlEPMaxPktSize);
+ DBG_USBD3("Standard Req : SET SEL\n");
+ break;
+
+ case STANDARD_ISOCH_DELY:
+ DBG_USBD3("Standard Req : ISOCH Delay\n");
+ break;
+
+ default:
+ DBG_USBD3("\n %s(line %d)\n", __FILE__, __LINE__);
+ DBG_USBD3("Error : This Request(%d) is not implemented yet\n", oUsbDev3.m_oDeviceRequest.bRequest);
+ break;
+ }
+}
+
+static void exynos_usb_handle_ep0_out_xfer_complete(void)
+{
+ switch (oUsbDev3.m_uEp0State) {
+ case EP0_STATE_INIT:
+ exynos_usb_handle_setup();
+ break;
+
+ case EP0_STATE_OUT_DATA_PHASE:
+ oUsbDev3.m_uEp0State = EP0_STATE_IN_WAIT_NRDY;
+ break;
+
+ case EP0_STATE_OUT_STATUS_PHASE:
+ oUsbDev3.m_uEp0State = EP0_STATE_INIT;
+
+ // . to start EP0 to receive SETUP packets
+ //----------------------------------
+ if (!exynos_usb_start_ep0_setup_rx())
+ {
+ return;
+ }
+ break;
+
+ // khs. this routine is abnormal case, and handling for this case is not prepared.
+ default :
+ DBG_USBD3("\nError : [EP0-OutXferComplete]Not Supported @%d\n", oUsbDev3.m_uEp0State);
+ break;
+ }
+
+}
+
+static void exynos_usb_handle_ep_out_xfer_complete(void)
+{
+ u16 usRxCnt;
+ u16 usCheck;
+ u32 usCapTrbBufSiz;
+ u32 uLastBufSize;
+ u32 i=0;
+ usbdev3_trb_ptr_t pBulkOutTrb;
+ usbdev3_trb_ptr_t pBulkInTrb;
+ usbdev3_trb_ctrl_t usbdev3_trb_ctrl;
+
+ if (g_uCntOfDescOutComplete == 0)
+ {
+ // Check whether TRB was finished successfully or not
+ if ((g_pBulkOutTrb0->control.b.hwo != 0)||(g_pBulkOutTrb0->status.b.trb_sts != 0))
+ {
+ Assert(0);
+ }
+
+ g_uCntOfDescOutComplete++;
+
+ usRxCnt = oUsbDev3.m_uBulkEPMaxPktSize - g_pBulkOutTrb0->status.b.buf_siz;
+
+ exynos_usb_free((u32)g_pBulkOutTrb0);
+
+ if (usRxCnt == 10) //Upload Request
+ {
+ usCheck = *((u8 *)(g_ucTempDownBuf+8)) + (*((u8 *)(g_ucTempDownBuf+9))<<8);
+
+ if (usCheck == 0x1)
+ {
+ oUsbDev3.m_uUploadAddr =
+ *((u8 *)(g_ucTempDownBuf+0))+
+ (*((u8 *)(g_ucTempDownBuf+1))<<8)+
+ (*((u8 *)(g_ucTempDownBuf+2))<<16)+
+ (*((u8 *)(g_ucTempDownBuf+3))<<24);
+
+ oUsbDev3.m_uUploadSize =
+ *((u8 *)(g_ucTempDownBuf+4))+
+ (*((u8 *)(g_ucTempDownBuf+5))<<8)+
+ (*((u8 *)(g_ucTempDownBuf+6))<<16)+
+ (*((u8 *)(g_ucTempDownBuf+7))<<24);
+
+ exynos_usb_free((u32)g_ucTempDownBuf);
+
+ oUsbDev3.m_pUpPt=(u8 *)oUsbDev3.m_uUploadAddr;
+
+ DBG_USBD3("UploadAddress : 0x%x, UploadSize: %d\n", oUsbDev3.m_uUploadAddr, oUsbDev3.m_uUploadSize);
+
+ if (oUsbDev3.m_uUploadSize>0)
+ {
+ DBG_USBD3("Dma Start for IN PKT \n");
+
+ // buffer_size of TRB should be
+ usCapTrbBufSiz = TRB_BUF_SIZ_LIMIT/oUsbDev3.m_uBulkEPMaxPktSize*oUsbDev3.m_uBulkEPMaxPktSize;
+
+ g_uCntOfBulkInTrb = oUsbDev3.m_uUploadSize/usCapTrbBufSiz;
+
+ if ((oUsbDev3.m_uUploadSize%usCapTrbBufSiz) != 0)
+ {
+ g_uCntOfBulkInTrb++;
+ }
+
+ g_pBulkInTrbArray_Base = (usbdev3_trb_ptr_t)exynos_usb_malloc(g_uCntOfBulkInTrb*sizeof(usbdev3_trb_t), USBDEV3_MDWIDTH/8);
+
+ if (g_pBulkInTrbArray_Base == NULL)
+ {
+ Assert(0);
+ }
+
+ pBulkInTrb = g_pBulkInTrbArray_Base;
+
+
+ // . fill the Trbs
+ //------------------
+ // (Total Buffer size must be in terms of multiple of Max Packet Size)
+ usbdev3_trb_ctrl.data = 0;
+ usbdev3_trb_ctrl.b.lst = 0;
+ usbdev3_trb_ctrl.b.chn = 1;
+ usbdev3_trb_ctrl.b.csp = 0;
+ usbdev3_trb_ctrl.b.trb_ctrl = (u32)TRB_CTRL_NORMAL;
+ usbdev3_trb_ctrl.b.isp_imi = 1;
+ usbdev3_trb_ctrl.b.ioc = 0;
+ usbdev3_trb_ctrl.b.strmid_sofn = 0;
+ for(i=0;i<(g_uCntOfBulkInTrb-1);i++)
+ {
+ exynos_usb_fill_trb(pBulkInTrb, (u32)(oUsbDev3.m_pUpPt+usCapTrbBufSiz*i), usCapTrbBufSiz, usbdev3_trb_ctrl.data, 1);
+ pBulkInTrb++;
+ }
+
+ // i = g_uCntOfBulkInTrb-1, last Trb
+ usbdev3_trb_ctrl.b.lst = 1;
+ usbdev3_trb_ctrl.b.chn = 0;
+ usbdev3_trb_ctrl.b.ioc = 1;
+ uLastBufSize = oUsbDev3.m_uUploadSize-usCapTrbBufSiz*i;
+ exynos_usb_fill_trb(pBulkInTrb, (u32)(oUsbDev3.m_pUpPt+usCapTrbBufSiz*i), uLastBufSize, usbdev3_trb_ctrl.data, 1);
+ //
+ ////
+
+ // . Issue Start Xfer for Bulk In Xfer
+ //----------------------------
+ if (!exynos_usb_start_ep_xfer(USBDEV3_EP_DIR_IN, BULK_IN_EP, (u32)g_pBulkInTrbArray_Base, 0, &oUsbDev3.m_uTriIn[BULK_IN_EP]))
+ {
+ return;
+ }
+ }
+ }
+ else
+ {
+ Assert(0);
+ }
+ }
+ else //Download Request
+ {
+ oUsbDev3.m_uDownloadAddress =
+ *((u8 *)(g_ucTempDownBuf+0))+
+ (*((u8 *)(g_ucTempDownBuf+1))<<8)+
+ (*((u8 *)(g_ucTempDownBuf+2))<<16)+
+ (*((u8 *)(g_ucTempDownBuf+3))<<24);
+ oUsbDev3.m_uDownloadFileSize =
+ *((u8 *)(g_ucTempDownBuf+4))+
+ (*((u8 *)(g_ucTempDownBuf+5))<<8)+
+ (*((u8 *)(g_ucTempDownBuf+6))<<16)+
+ (*((u8 *)(g_ucTempDownBuf+7))<<24);
+
+ if (exynos_usbd_dn_addr)
+ {
+ oUsbDev3.m_uDownloadAddress = exynos_usbd_dn_addr; // Request usb down Addr
+ }
+
+ oUsbDev3.m_pDownPt=(u8 *)oUsbDev3.m_uDownloadAddress;
+
+ DBG_USBD3("downloadAddress : 0x%x, downloadFileSize: %d\n", oUsbDev3.m_uDownloadAddress, oUsbDev3.m_uDownloadFileSize);
+
+ memcpy((void *)oUsbDev3.m_pDownPt, (void *)(g_ucTempDownBuf+8), usRxCnt-8);
+
+ exynos_usb_free((u32)g_ucTempDownBuf);
+
+ oUsbDev3.m_pDownPt += usRxCnt-8;
+
+ if (oUsbDev3.m_uDownloadFileSize>usRxCnt) //there are more data to be received
+ {
+
+ usCapTrbBufSiz = TRB_BUF_SIZ_LIMIT/oUsbDev3.m_uBulkEPMaxPktSize*oUsbDev3.m_uBulkEPMaxPktSize;
+
+ g_uCntOfBulkOutTrb = (oUsbDev3.m_uDownloadFileSize-usRxCnt)/usCapTrbBufSiz;
+
+ if ((oUsbDev3.m_uDownloadFileSize-usRxCnt)%usCapTrbBufSiz != 0)
+ {
+ g_uCntOfBulkOutTrb++;
+ }
+
+ g_pBulkOutTrbArray_Base = (usbdev3_trb_ptr_t)exynos_usb_malloc(g_uCntOfBulkOutTrb*sizeof(usbdev3_trb_t), USBDEV3_MDWIDTH/8);
+
+ if (g_pBulkOutTrbArray_Base == NULL)
+ {
+ Assert(0);
+ }
+
+ pBulkOutTrb = (usbdev3_trb_ptr_t)virt_to_phys((void *)g_pBulkOutTrbArray_Base);
+
+ // . fill the Trbs
+ //------------------
+ // (Total Buffer size must be in terms of multiple of Max Packet Size)
+ usbdev3_trb_ctrl.data = 0;
+ usbdev3_trb_ctrl.b.lst = 0;
+ usbdev3_trb_ctrl.b.chn = 1;
+ usbdev3_trb_ctrl.b.csp = 0;
+ usbdev3_trb_ctrl.b.trb_ctrl = (u32)TRB_CTRL_NORMAL;
+ usbdev3_trb_ctrl.b.isp_imi = 1;
+ usbdev3_trb_ctrl.b.ioc = 0;
+ usbdev3_trb_ctrl.b.strmid_sofn = 0;
+
+ for(i=0;i<(g_uCntOfBulkOutTrb-1);i++)
+ {
+ exynos_usb_fill_trb(pBulkOutTrb, (u32)(oUsbDev3.m_pDownPt+usCapTrbBufSiz*i), usCapTrbBufSiz, usbdev3_trb_ctrl.data, 1);
+ pBulkOutTrb++;
+ }
+
+ // i = g_uCntOfBulkOutTrb-1, last Trb
+ usbdev3_trb_ctrl.b.lst = 1;
+ usbdev3_trb_ctrl.b.chn = 0;
+ usbdev3_trb_ctrl.b.ioc = 1;
+ uLastBufSize = (oUsbDev3.m_uDownloadFileSize-usRxCnt)-usCapTrbBufSiz*i;
+ uLastBufSize = ((uLastBufSize+oUsbDev3.m_uBulkEPMaxPktSize-1)/oUsbDev3.m_uBulkEPMaxPktSize)*oUsbDev3.m_uBulkEPMaxPktSize;
+ exynos_usb_fill_trb(pBulkOutTrb, (u32)(oUsbDev3.m_pDownPt+usCapTrbBufSiz*i), uLastBufSize, usbdev3_trb_ctrl.data, 1);
+ //
+ ////
+
+ // . Issue Start Xfer for Bulk Out Xfer
+ //----------------------------
+ if (!exynos_usb_start_ep_xfer(USBDEV3_EP_DIR_OUT, BULK_OUT_EP, (u32)g_pBulkOutTrbArray_Base, 0, &oUsbDev3.m_uTriOut[BULK_OUT_EP]))
+ {
+ return;
+ }
+ }
+ else //there are no more data
+ {
+ g_uCntOfDescOutComplete = 0;
+
+ exynos_receive_done = 1;
+
+ DBG_USBD3("DMA OUT : Transfer Complete\n");
+ }
+ }
+ }
+ else
+ {
+ g_uCntOfDescOutComplete = 0;
+
+ exynos_receive_done = 1;
+
+ exynos_usb_free((u32)g_pBulkOutTrbArray_Base);
+
+ oUsbDev3.m_pDownPt += (oUsbDev3.m_uDownloadFileSize - 8);
+
+ printf("Download Done!! Download Address: 0x%x, Download Filesize:0x%x\n",
+ oUsbDev3.m_uDownloadAddress, (oUsbDev3.m_uDownloadFileSize-10));
+ }
+}
+
+static void exynos_usb_handle_ep0_out_xfer_not_ready(void)
+{
+ switch (oUsbDev3.m_uEp0State) {
+ case EP0_STATE_OUT_WAIT_NRDY:
+ // . to setup out-status phase
+ exynos_usb_setup_out_status_phase();
+ break;
+ // khs. this routine is abnormal case, and handling for this case is not prepared.
+ default :
+ DBG_USBD3("\nError : [EP0-OutXferNotReady]Not Supported @%d\n", oUsbDev3.m_uEp0State);
+ break;
+ }
+}
+
+static void exynos_usb_handle_ep_out_event(usbdev3_depevt_t uEpOutEvent)
+{
+ u32 uEpNum = uEpOutEvent.b.ep_num/2; // 0,2,4,6,...
+
+ DBG_USBD3("[EP%d] Out State = 0x%x Type = 0x%x[0x%x]\n", uEpNum, oUsbDev3.m_uEp0State, uEpOutEvent.b.evt_type, uEpOutEvent.data);
+ switch (uEpOutEvent.b.evt_type)
+ {
+ case DEPEVT_EVT_XFER_CMPL:
+ DBG_USBD3("[EP%d] OUT xfer complete @%d\n", uEpNum, oUsbDev3.m_uEp0State);
+ if (uEpNum == 0)
+ exynos_usb_handle_ep0_out_xfer_complete();
+ else if (uEpNum == BULK_OUT_EP) {
+ if (is_fastboot)
+ fboot_usb_handle_ep_out_xfer_complete();
+ else
+ exynos_usb_handle_ep_out_xfer_complete();
+ } else
+ Assert(0);
+ break;
+
+ case DEPEVT_EVT_XFER_IN_PROG:
+ DBG_USBD3("[EP%d] OUT xfer in progress @%d\n", uEpNum, oUsbDev3.m_uEp0State);
+ break;
+
+ case DEPEVT_EVT_XFER_NRDY:
+ DBG_USBD3("[EP%d] OUT xfer not ready @%d\n", uEpNum, oUsbDev3.m_uEp0State);
+ if (uEpNum == 0)
+ exynos_usb_handle_ep0_out_xfer_not_ready();
+ else
+ ;//
+ break;
+
+ case DEPEVT_EVT_FIFOXRUN:
+ DBG_USBD3("[EP%d] OUT FIFO Overrun Error @%d\n", uEpNum, oUsbDev3.m_uEp0State);
+ break;
+
+ case DEPEVT_EVT_STRM_EVT:
+ DBG_USBD3("[EP%d] OUT Stream Event @%d\n", uEpNum, oUsbDev3.m_uEp0State);
+ break;
+
+ case DEPEVT_EVT_EPCMD_CMPL:
+ DBG_USBD3("[EP%d] OUT Command Complete @%d\n", uEpNum, oUsbDev3.m_uEp0State);
+ break;
+
+ default:
+ DBG_USBD3("Unknown event!\n");
+ }
+
+}
+
+static void exynos_usb_handle_event(void)
+{
+ u16 uEventCount, uLoop=0;
+ u32 uEventBufferCopied;
+
+ // . Get Event Buffer Count
+ //----------------------
+ uEventCount = readl(rGEVNTCOUNT0);
+
+ uEventCount = uEventCount/4;
+
+ if (uEventCount == 0)
+ {
+ return;
+ }
+ else
+ {
+ DBG_USBD3("## Event Count is %d ##\n", uEventCount);
+ }
+
+ while((uEventCount--> 0) && (uLoop < USBDEV3_EVENT_BUFFER_COUNT))
+ {
+ if (oUsbDev3.m_CurrentEventPosition == USBDEV3_EVENT_BUFFER_COUNT)
+ {
+ oUsbDev3.m_CurrentEventPosition = 0;
+ }
+
+ uEventBufferCopied = *(oUsbDev3.m_pEventBuffer + oUsbDev3.m_CurrentEventPosition); // to avoid that event buffer is overwritten.
+
+ uLoop++;
+ oUsbDev3.m_CurrentEventPosition++;
+
+ writel(4, rGEVNTCOUNT0); // update event buffer count
+ // core update event buffer whenever event occurs
+ if (uEventBufferCopied == 0)
+ {
+ DBG_USBD3("## Null Event!##\n");
+ }
+ else // event buffer contains event information
+ {
+ DBG_USBD3("\nLoop%d: Content of %dth Event Buffer is 0x%08x\n", uLoop, oUsbDev3.m_CurrentEventPosition, uEventBufferCopied);
+
+ // Device-Specific Event
+ if (uEventBufferCopied & 0x1)
+ {
+ usbdev3_devt_t usbdev3_devt;
+
+ usbdev3_devt.data = uEventBufferCopied;
+
+ //DBG_USBD3IntR("Device-Specific Event Occurred\n");
+
+ if (usbdev3_devt.b.dev_specific != 0)
+ {
+ DBG_USBD3("Other Core Event\n");
+ }
+
+ exynos_usb_handle_dev_event(usbdev3_devt);
+ }
+ else // Device Endpoint-Specific Event
+ {
+ usbdev3_depevt_t usbdev3_depevt;
+ u32 uEpNum;
+
+ usbdev3_depevt.data = uEventBufferCopied;
+
+ uEpNum = usbdev3_depevt.b.ep_num;
+
+ if (uEpNum & 1)
+ {
+ DBG_USBD3("IN Endpoint%d Event Occurred\n", (uEpNum/2));
+ exynos_usb_handle_ep_in_event(usbdev3_depevt);
+ }
+ else
+ {
+ DBG_USBD3("OUT Endpoint%d Event Occurred\n", (uEpNum/2));
+ exynos_usb_handle_ep_out_event(usbdev3_depevt);
+ }
+ }
+ }
+ }
+}
+
+struct exynos_usb3_phy {
+ unsigned int reserve1;
+ unsigned int link_system;
+ unsigned int phy_utmi;
+ unsigned int phy_pipe;
+ unsigned int phy_clk_rst;
+ unsigned int phy_reg0;
+ unsigned int phy_reg1;
+ unsigned int phy_param0;
+ unsigned int phy_param1;
+ unsigned int phy_term;
+ unsigned int phy_test;
+ unsigned int phy_adp;
+ unsigned int phy_batchg;
+ unsigned int phy_resume;
+ unsigned int reserve2[3];
+ unsigned int link_port;
+};
+
+int exynos_usb_wait_cable_insert(void)
+{
+ u32 tmp1, tmp2;
+ char ch;
+ int ret = -1;
+ oUsbDev3.m_uPhyBaseRegs = USBDEVICE3_PHYCTRL_CH0_BASE;
+ tmp1 = readl(EXYNOS_PHY_ADP);
+ oUsbDev3.m_uPhyBaseRegs = USBDEVICE3_PHYCTRL_CH1_BASE;
+ tmp2 = readl(EXYNOS_PHY_ADP);
+ oUsbDev3.m_uPhyBaseRegs = 0;
+ if (tmp1 & 0x8 || tmp2 & 0x8) {
+ if(oUsbDev3.m_cable != CONNECTED) {
+ ch = (tmp1 & 0x8) ? 0 : 1;
+ printf("USB cable Connected![CH-%d]\n", ch);
+ ret = 0;
+ oUsbDev3.m_cable = CONNECTED;
+ if (!ch) {
+ oUsbDev3.m_uLinkBaseRegs = USBDEVICE3_LINK_CH0_BASE;
+ oUsbDev3.m_uPhyBaseRegs = USBDEVICE3_PHYCTRL_CH0_BASE;
+ } else {
+ oUsbDev3.m_uLinkBaseRegs = USBDEVICE3_LINK_CH1_BASE;
+ oUsbDev3.m_uPhyBaseRegs = USBDEVICE3_PHYCTRL_CH1_BASE;
+ }
+ }
+ } else {
+ if(oUsbDev3.m_cable == UNCHECKED) {
+ printf("Insert a USB cable into the connector!\n");
+ oUsbDev3.m_cable = DISCONNECTED;
+ } else if(oUsbDev3.m_cable == CONNECTED) {
+ oUsbDev3.m_cable = UNCHECKED;
+ exynos_usb_runstop_device(0);
+ is_fastboot = 0;
+ }
+ }
+ return ret;
+}
+
+int exynos_usbc_activate (void)
+{
+ exynos_usb_runstop_device(1);
+ return 0;
+}
+
+int exynos_usb_stop( void )
+{
+ if(oUsbDev3.m_cable == CONNECTED)
+ exynos_usb_runstop_device(0);
+
+ exynoy_usb_phy_off();
+ oUsbDev3.m_cable = UNCHECKED;
+
+ return 0;
+}
+
+int exynos_udc_int_hndlr(void)
+{
+ exynos_usb_handle_event();
+ return OK;
+}
+
+int exynos_usbctl_init(void)
+{
+ usbdev3_gusb2phycfg_t usbdev3_gusb2phycfg;
+ usbdev3_gusb3pipectl_t usbdev3_gusb3pipectl;
+ usbdev3_gctl_t usbdev3_gctl;
+ USBDEV3_SPEED_e eSpeed = USBDEV3_SPEED_SUPER;
+
+ // . to initialize variables for usb device
+ //--------------------------------
+ // khs. to be implemented more
+ oUsbDev3.m_eSpeed = eSpeed;
+ oUsbDev3.m_eUsbDev3State = USBDEV3_STATE_DEFAULT;
+ oUsbDev3.m_uEp0State = EP0_STATE_UNCONNECTED;
+ oUsbDev3.m_uEp0SubState = 0;
+ oUsbDev3.m_bEPs_Enabled = 0;
+ oUsbDev3.m_bReq_Set_sel = 0;
+ switch(eSpeed)
+ {
+ case USBDEV3_SPEED_SUPER:
+ oUsbDev3.m_uControlEPMaxPktSize = SUPER_SPEED_CONTROL_PKT_SIZE;
+ break;
+
+ case USBDEV3_SPEED_FULL:
+ oUsbDev3.m_uControlEPMaxPktSize = FULL_SPEED_CONTROL_PKT_SIZE;
+ break;
+
+ default :
+ oUsbDev3.m_uControlEPMaxPktSize = HIGH_SPEED_CONTROL_PKT_SIZE;
+ break;
+ }
+
+ // . to allocate initial buffers for usb device
+ //------------------------------------
+ oUsbDev3.m_pEventBuffer = (u32 *)exynos_usb_malloc(4*USBDEV3_EVENT_BUFFER_COUNT, USBDEV3_MDWIDTH/8);
+ oUsbDev3.m_uStatusBufAddr = exynos_usb_malloc(CTRL_BUF_SIZE, USBDEV3_MDWIDTH/8);
+ oUsbDev3.m_oSetupTrbPtr = (usbdev3_trb_ptr_t)exynos_usb_malloc(sizeof(usbdev3_trb_t), USBDEV3_MDWIDTH/8);
+ oUsbDev3.m_oOutTrbPtr = (usbdev3_trb_ptr_t)exynos_usb_malloc(sizeof(usbdev3_trb_t), USBDEV3_MDWIDTH/8);
+ oUsbDev3.m_oInTrbPtr = (usbdev3_trb_ptr_t)exynos_usb_malloc(sizeof(usbdev3_trb_t), USBDEV3_MDWIDTH/8);
+
+ // khs. ep_init 함수 호출을 통한 ep 별 structure 초기화 수행해야할까....?
+
+ // . to set AP system related to usb device (ex. clock source & gating, phy enable)
+ //--------------------------------------------------------------------
+ // - to enable a bus clock for usb dev controller & phy control block
+ //TODO: Enable system clock and so on.
+ /* USBDEV3_HclkUsb3ClkGate(true); */
+ /* USBDEV3_Usb3PhyEnable(); // USB PHY Enable */
+ exynos_usb_phy_on();
+
+ /* EXYNOS5 EVT1 : PHY should be reset before global register configuration
+ This sequence cover reset sequence on EXYNOS5 EVT0. */
+ exynos_usb_softreset_phy(1);
+ exynos_usb_init_phy();
+ exynos_usb_softreset_phy(0);
+
+ usbdev3_gusb2phycfg.data = readl(rGUSB2PHYCFG);
+ usbdev3_gusb2phycfg.b.suspend_usb2_phy = 0;
+ usbdev3_gusb2phycfg.b.enable_sleep_n = 0;
+ writel(usbdev3_gusb2phycfg.data, rGUSB2PHYCFG);
+
+ usbdev3_gusb3pipectl.data = readl(rGUSB3PIPECTL);
+ usbdev3_gusb3pipectl.b.suspend_usb3_ss_phy = 0;
+ writel(usbdev3_gusb3pipectl.data, rGUSB3PIPECTL);
+
+ // . to initialize usb device phy
+ //--------------------------
+ usbdev3_gctl.data = readl(rGCTL);
+ usbdev3_gctl.b.core_soft_reset = 1; // to keep the core in reset state until phy clocks are stable(GCTL의 11번 bit 설명 참조)
+ /*
+ * WORKAROUND: DWC3 revisions <1.90a have a bug
+ * when The device fails to connect at SuperSpeed
+ * and falls back to high-speed mode which causes
+ * the device to enter in a Connect/Disconnect loop
+ */
+ usbdev3_gctl.b.u2rst_ecn = 1;
+ writel(usbdev3_gctl.data, rGCTL);
+
+ usbdev3_gctl.data = readl(rGCTL);
+ usbdev3_gctl.b.core_soft_reset = 0; // to keep the core out of reset state after phy clocks are stable(GCTL의 11번 bit 설명 참조)
+ writel(usbdev3_gctl.data, rGCTL);
+
+ usbdev3_gctl.b.pwr_down_scale = ((unsigned int)get_usbdrd_clk()) / 16000;
+ usbdev3_gctl.b.ram_clk_sel = 0; // 00:bus clock, 01:pipe clock, 10:pipe/2 clock
+ usbdev3_gctl.b.DisScramble = 0;
+ writel(usbdev3_gctl.data, rGCTL);
+
+ g_uCntOfDescOutComplete = 0;
+ is_fastboot = 0;
+ // . to initialize usb device controller
+ //------------------------------
+ if (exynos_usb_init_core(eSpeed))
+ {
+ DBG_USBD3("Exynos USB3 Core Init Fail\n");
+ return 0;
+ }
+
+ return 0;
+}
+#endif
diff --git a/drivers/usb/gadget/usbd3-ss.h b/drivers/usb/gadget/usbd3-ss.h
new file mode 100755
index 0000000000..6ac2a86a7f
--- /dev/null
+++ b/drivers/usb/gadget/usbd3-ss.h
@@ -0,0 +1,1178 @@
+/*
+ * drivers/usb/gadget/usbd3-ss.h
+ *
+ * (C) Copyright 2011
+ * Yulgon Kim, Samsung Erectronics, yulgon.kim@samsung.com.
+ * - only support for S5PC510
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __EXYNOS_USBD_SS_H__
+#define __EXYNOS_USBD_SS_H__
+
+#include <asm/byteorder.h>
+#include <asm/arch/cpu.h>
+#include <mach/usb.h>
+#include <asm/io.h>
+
+//==========================
+// Define
+//==========================
+#define CONTROL_EP 0
+#define BULK_IN_EP 1
+#define BULK_OUT_EP 2
+#define TOTL_EP_COUNT 16
+
+#define USBDEV3_MDWIDTH 64 // master data bus width
+#define USBDEV3_DATA_BUF_SIZ 16384 // 16KB
+
+#define CMDCOMPLETEWAIT_UNIT 1000
+
+#define RX_FIFO_SIZE 1024
+#define NPTX_FIFO_START_ADDR RX_FIFO_SIZE
+#define NPTX_FIFO_SIZE 256
+#define PTX_FIFO_SIZE 256
+
+#define CTRL_BUF_SIZE 128 //512
+
+// string descriptor
+#define LANGID_US_L (0x09)
+#define LANGID_US_H (0x04)
+
+// Feature Selectors
+#define EP_STALL 0
+#define DEVICE_REMOTE_WAKEUP 1
+#define TEST_MODE 2
+
+/* Test Mode Selector*/
+#define TEST_J 1
+#define TEST_K 2
+#define TEST_SE0_NAK 3
+#define TEST_PACKET 4
+#define TEST_FORCE_ENABLE 5
+
+#define USB_DEVICE 0
+#define USB_HOST 1
+#define USB_OTG 2
+
+#define FULL_SPEED_CONTROL_PKT_SIZE 64
+#define FULL_SPEED_BULK_PKT_SIZE 64
+
+#define HIGH_SPEED_CONTROL_PKT_SIZE 64
+#define HIGH_SPEED_BULK_PKT_SIZE 512
+
+#define SUPER_SPEED_CONTROL_PKT_EXP_SZ 9 // 2^9 = 512
+#define SUPER_SPEED_CONTROL_PKT_SIZE 512
+#define SUPER_SPEED_BULK_PKT_SIZE 1024
+
+typedef struct {
+ u8 bLength;
+ u8 bDescriptorType;
+ u8 bcdUSBL;
+ u8 bcdUSBH;
+ u8 bDeviceClass;
+ u8 bDeviceSubClass;
+ u8 bDeviceProtocol;
+ u8 bMaxPacketSize0;
+ u8 idVendorL;
+ u8 idVendorH;
+ u8 idProductL;
+ u8 idProductH;
+ u8 bcdDeviceL;
+ u8 bcdDeviceH;
+ u8 iManufacturer;
+ u8 iProduct;
+ u8 iSerialNumber;
+ u8 bNumConfigurations;
+} USB_DEVICE_DESCRIPTOR;
+
+typedef struct {
+ u8 bLength;
+ u8 bDescriptorType;
+ u8 wTotalLengthL;
+ u8 wTotalLengthH;
+ u8 bNumInterfaces;
+ u8 bConfigurationValue;
+ u8 iConfiguration;
+ u8 bmAttributes;
+ u8 maxPower;
+} USB_CONFIGURATION_DESCRIPTOR;
+
+typedef struct {
+ u8 bLength;
+ u8 bDescriptorType;
+ u8 bInterfaceNumber;
+ u8 bAlternateSetting;
+ u8 bNumEndpoints;
+ u8 bInterfaceClass;
+ u8 bInterfaceSubClass;
+ u8 bInterfaceProtocol;
+ u8 iInterface;
+} USB_INTERFACE_DESCRIPTOR;
+
+typedef struct {
+ u8 bLength;
+ u8 bDescriptorType;
+ u8 bEndpointAddress;
+ u8 bmAttributes;
+ u8 wMaxPacketSizeL;
+ u8 wMaxPacketSizeH;
+ u8 bInterval;
+} USB_ENDPOINT_DESCRIPTOR;
+
+typedef struct {
+ u8 bLength;
+ u8 bDescriptorType;
+ u8 bMaxBurst;
+ u8 bmAttributes;
+ u16 wBytesPerInterval;
+} __attribute__ ((packed)) USB_SS_EP_COMP_DESCRIPTOR;
+
+typedef struct {
+ u8 bLength;
+ u8 bDescriptorType;
+ u8 *pString;
+} USB_STRING_DESCRIPTOR;
+
+typedef struct {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __le16 wTotalLength;
+ __u8 bNumDeviceCaps;
+} __attribute__ ((packed)) USB_BOS_DESCRIPTOR;
+
+typedef struct {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDevCapabilityType;
+ __le32 bmAttributes;
+} __attribute__ ((packed)) USB20_EXT_CAP_DESCRIPTOR;
+
+typedef struct {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDevCapabilityType;
+ __u8 bmAttributes;
+ __le16 wSpeedsSupported;
+ __u8 bFunctionalitySupport;
+ __u8 bU1DevExitLat;
+ __le16 wU2DevExitLat;
+} __attribute__ ((packed)) USB_SUPERSPEED_CAP_DESCRIPTOR;
+
+typedef struct {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDevCapabilityType;
+ __u8 bReserved;
+ __u8 containerID[16];
+} __attribute__ ((packed)) USB_CONTAINER_ID_CAP_DESCRIPTOR;
+
+typedef struct {
+ USB_DEVICE_DESCRIPTOR oDescDevice;
+ USB_CONFIGURATION_DESCRIPTOR oDescConfig;
+ USB_INTERFACE_DESCRIPTOR oDescInterface;
+ USB_ENDPOINT_DESCRIPTOR oDescEp0;
+ USB_ENDPOINT_DESCRIPTOR oDescEp1;
+ USB_ENDPOINT_DESCRIPTOR oDescEp2;
+ USB_ENDPOINT_DESCRIPTOR oDescEp3;
+} __attribute__ ((packed)) USB_DESCRIPTORS;
+
+typedef struct {
+ USB_DEVICE_DESCRIPTOR oDescDevice;
+ USB_CONFIGURATION_DESCRIPTOR oDescConfig;
+ USB_INTERFACE_DESCRIPTOR oDescInterface;
+ USB_ENDPOINT_DESCRIPTOR oDescEp0;
+ USB_SS_EP_COMP_DESCRIPTOR oDescEp0Comp;
+ USB_ENDPOINT_DESCRIPTOR oDescEp1;
+ USB_SS_EP_COMP_DESCRIPTOR oDescEp1Comp;
+ USB_ENDPOINT_DESCRIPTOR oDescEp2;
+ USB_SS_EP_COMP_DESCRIPTOR oDescEp2Comp;
+ USB_ENDPOINT_DESCRIPTOR oDescEp3;
+ USB_SS_EP_COMP_DESCRIPTOR oDescEp3Comp;
+ USB_BOS_DESCRIPTOR oDescBos;
+ USB20_EXT_CAP_DESCRIPTOR oDescUsb20Ext;
+ USB_SUPERSPEED_CAP_DESCRIPTOR oDescSuperCap;
+ USB_CONTAINER_ID_CAP_DESCRIPTOR oDescContainCap;
+} __attribute__ ((packed)) USB_SS_DESCRIPTORS;
+
+typedef struct {
+ u8 bmRequestType;
+ u8 bRequest;
+ u8 wValue_L;
+ u8 wValue_H;
+ u8 wIndex_L;
+ u8 wIndex_H;
+ u8 wLength_L;
+ u8 wLength_H;
+} DEVICE_REQUEST, *DEVICE_REQUEST_PTR;
+
+//=====================================================================
+// definitions related to Standard Device Requests
+#define SETUP_DATA_SIZE 8
+
+// Standard bmRequestType (direction)
+// #define DEVICE_bmREQUEST_TYPE(oDeviceRequest) ((m_poDeviceRequest->bmRequestType) & 0x80)
+enum DEV_REQUEST_DIRECTION
+{
+ HOST_TO_DEVICE = 0x00,
+ DEVICE_TO_HOST = 0x80
+};
+
+// Standard bmRequestType (Type)
+// #define DEVICE_bmREQUEST_TYPE(oDeviceRequest) ((m_poDeviceRequest->bmRequestType) & 0x60)
+enum DEV_REQUEST_TYPE
+{
+ STANDARD_TYPE = 0x00,
+ CLASS_TYPE = 0x20,
+ VENDOR_TYPE = 0x40,
+ RESERVED_TYPE = 0x60
+};
+
+// Standard bmRequestType (Recipient)
+// #define DEVICE_bmREQUEST_RECIPIENT(oDeviceRequest) ((m_poDeviceRequest->bmRequestType) & 0x07)
+enum DEV_REQUEST_RECIPIENT
+{
+ DEVICE_RECIPIENT = 0,
+ INTERFACE_RECIPIENT = 1,
+ ENDPOINT_RECIPIENT = 2,
+ OTHER_RECIPIENT = 3
+};
+
+// Standard bRequest codes
+enum STANDARD_REQUEST_CODE
+{
+ STANDARD_GET_STATUS = 0,
+ STANDARD_CLEAR_FEATURE = 1,
+ STANDARD_RESERVED_1 = 2,
+ STANDARD_SET_FEATURE = 3,
+ STANDARD_RESERVED_2 = 4,
+ STANDARD_SET_ADDRESS = 5,
+ STANDARD_GET_DESCRIPTOR = 6,
+ STANDARD_SET_DESCRIPTOR = 7,
+ STANDARD_GET_CONFIGURATION = 8,
+ STANDARD_SET_CONFIGURATION = 9,
+ STANDARD_GET_INTERFACE = 10,
+ STANDARD_SET_INTERFACE = 11,
+ STANDARD_SYNCH_FRAME = 12,
+ STANDARD_SET_SEL = 48,
+ STANDARD_ISOCH_DELY = 49,
+};
+
+// Descriptor types
+enum DESCRIPTOR_TYPE
+{
+ DEVICE_DESCRIPTOR = 1,
+ CONFIGURATION_DESCRIPTOR = 2,
+ STRING_DESCRIPTOR = 3,
+ INTERFACE_DESCRIPTOR = 4,
+ ENDPOINT_DESCRIPTOR = 5,
+ DEVICE_QUALIFIER = 6,
+ OTHER_SPEED_CONFIGURATION = 7,
+ INTERFACE_POWER = 8,
+ BOS = 15,
+};
+
+// configuration descriptor: bmAttributes
+enum CONFIG_ATTRIBUTES
+{
+ CONF_ATTR_DEFAULT = 0x80, // in Spec 1.0, it was BUSPOWERED bit.
+ CONF_ATTR_REMOTE_WAKEUP = 0x20,
+ CONF_ATTR_SELFPOWERED = 0x40
+};
+
+// endpoint descriptor
+enum ENDPOINT_ATTRIBUTES
+{
+ EP_ADDR_IN = 0x80,
+ EP_ADDR_OUT = 0x00,
+
+ EP_ATTR_CONTROL = 0x0,
+ EP_ATTR_ISOCHRONOUS = 0x1,
+ EP_ATTR_BULK = 0x2,
+ EP_ATTR_INTERRUPT = 0x3
+};
+
+// Descriptor size
+enum DESCRIPTOR_SIZE
+{
+ DEVICE_DESC_SIZE = 18,
+ STRING_DESC0_SIZE = 4,
+ STRING_DESC1_SIZE = 22,
+ STRING_DESC2_SIZE = 42,
+ CONFIG_DESC_SIZE = 9,
+ INTERFACE_DESC_SIZE = 9,
+ ENDPOINT_DESC_SIZE = 7,
+ ENDPOINT_COMP_DESC_SIZE = 6,
+ DEVICE_QUALIFIER_SIZE = 10,
+ OTHER_SPEED_CFG_SIZE = 9,
+ BOS_DESC_SIZE = 5,
+ USB20_EXT_CAP_DESC_SIZE = 7,
+ SUPER_CAP_DESC_SIZE = 10,
+ CONTAIN_CAP_DESC_SIZE = 5,
+};
+
+typedef enum
+{
+ USB_HIGH, USB_FULL, USB_LOW
+} USB_SPEED;
+
+typedef enum
+{
+ USBPHY0,
+ USBPHY1,
+} USB_PHY;
+
+typedef enum {
+ DIFF_100MHz,
+ DIFF_24MHz,
+ DIFF_20MHz,
+ DIFF_19_2MHz,
+
+ EXTREF_50MHz,
+ EXTREF_24MHz,
+ EXTREF_20MHz,
+ EXTREF_19_2MHz,
+ EXTREF_12MHz,
+ EXTREF_10MHz,
+ EXTREF_9_6MHz,
+} USB3_PHY_CLKFREQ;
+
+typedef enum
+{
+ UNCHECKED, DISCONNECTED, CONNECTED
+} CABLE_STATUS;
+
+typedef struct {
+ u8 ConfigurationValue;
+} __attribute__ ((packed)) USB_CONFIGURATION_SET;
+
+typedef struct {
+ u8 Device;
+ u8 Interface;
+ u8 EndpointCtrl;
+ u8 EndpointIn;
+ u8 EndpointOut;
+} __attribute__ ((packed)) USB_GET_STATUS;
+
+typedef struct {
+ u8 AlternateSetting;
+} __attribute__ ((packed)) USB_INTERFACE_GET;
+
+typedef struct Usb_st_REG {
+ u8 name[64];
+ u32 uAddr;
+ u8 uBitLen;
+ u8 uRWType;
+ u8 uFlag; //Option Flag(DPDB, DPPB, PPDB PPPB)
+ u32 uPrivateBitMask;
+ u32 rValue;
+} USBDEV3_REGINFO;
+
+//==================================================================
+// CSR STRUCTURE
+//
+// PHYUTMI
+typedef union
+{
+ u32 data; // reset value : 0x00000630
+ struct {
+ // bit[0] : force sleep
+ unsigned force_sleep:1;
+ // bit[1] : force suspend
+ unsigned force_suspend:1;
+ // bit[2] : dmpulldown
+ unsigned dm_pulldown:1;
+ // bit[3] : dppulldown
+ unsigned dp_pulldown:1;
+ // bit[4] : drvvbus
+ unsigned drvvbus:1;
+ // bit[5] : idpullup
+ unsigned id_pullup:1;
+ // bit[6] : otg disable
+ unsigned otg_disable:1;
+ // bit[8:7] : reserved
+ unsigned rsvd8_7:2;
+ // bit[9] : external vbus valid indicator (to phy)
+ unsigned vbusvld_ext:1;
+ // bit[10] : external vbus valid select
+ unsigned vbusvld_extsel:1;
+ // bit[31:11] : reserved
+ unsigned rsvd31_11:21;
+ }b;
+} usb3_phy_utmi_t;
+
+// PHYCLKPWR
+typedef union
+{
+ u32 data; // reset value : 0x801bee3b@c520, 0x441b4558@c510
+ struct {
+ // bit[0] : common block power-down control
+ // (0->in suspend or sleep mode, the HS bias and pll blocks remain powered and continue to draw current,
+ // 1->in suspend or sleep mode, the HS bias and pll blocks are powered down)
+ unsigned commononn:1;
+ // bit[1] : per-port reset (reest the port's USB2.0 transmit and receive logic without disableing the clocks)
+ unsigned portreset:1;
+ // bit[3:2] : reference clock select for pll block
+ // (2'b11:HS pll uses EXTREFCLK as reference, 2'b10:HS pll uses ref_pad_clk{p,m}
+ unsigned refclksel:2;
+ // bit[4] : lowered digital suplly indicator (0->normal operating mode, 1->analog blocks are powered-down
+ unsigned retenablen:1;
+ // bit[10:5] : frequency select
+ unsigned fsel:6;
+ // bit[17:11] : mpll frequency multiplier control
+ unsigned mpll_multiplier:7;
+ // bit[18] : input reference clock divider control
+ unsigned ref_clkdiv2:1;
+ // bit[19] : reference clock enable for SS function
+ // enables the reference clock to the prescaler
+ // this must remain deasserted until the ref. clock is running at the appropriate fre.,
+ // at which point ref_ssp_en can be asserted.
+ // for lower power states, ref_ssp_en can be deasserted.
+ unsigned ref_ssp_en:1;
+ // bit[20] : spread spectrum enable
+ unsigned ssc_en:1;
+ // bit[22:21] : spread spectrum clock range
+ unsigned ssc_range:2;
+ // bit[30:23] : spread spectrum reference clock shifting
+ unsigned ssc_ref_clk_sel:8;
+ // bit[31] : reserved
+ unsigned rsvd31:1;
+ }b;
+} usbdev3_phy_clkpwr_t;
+
+// PHYREG0
+typedef union
+{
+ u32 data;
+ struct {
+ // bit[0] : CR_CMD_ADDR
+ unsigned cr_cap_addr:1;
+ // bit[1] : CR_CMD_DATA
+ unsigned cr_cap_data:1;
+ // bit[17:2] : send data to crport
+ unsigned cr_data_in:16;
+ // bit[18] : CR_CMD_READ
+ unsigned cr_read:1;
+ // bit[19] : CR_CMD_WRITE
+ unsigned cr_write:1;
+ // bit[31:20] : reserved
+ unsigned rsvd31_11:12;
+ }b;
+} usb3_phy_reg0_t;
+// PHYREG1
+typedef union
+{
+ u32 data;
+ struct {
+ // bit[0] : receive ack from crport
+ unsigned cr_ack:1;
+ // bit[16:1] : receive data from crport
+ unsigned cr_data_out:16;
+ // bit[31:17] : reserved
+ unsigned rsvd31_11:15;
+ }b;
+} usb3_phy_reg1_t;
+//-----------------------
+// Global Registers (Gxxxx)
+//-----------------------
+// rGSBUSCFG0
+typedef union
+{
+ u32 data; // reset value : 0x00000001
+ struct {
+ // bit[0] : undefined length INCR burst type enable
+ unsigned incr_xbrst_ena:1;
+ // bit[1] : INCR4 burst type enable
+ unsigned incr_4brst_ena:1;
+ // bit[2] : INCR8 burst type enable
+ unsigned incr_8brst_ena:1;
+ // bit[3] : INCR16 burst type enable
+ unsigned incr_16brst_ena:1;
+ // bit[10:4] :
+ unsigned rsvd10_4:7;
+ // bit[11] : data access is big endian
+ unsigned dat_big_end:1;
+ // bit[12] : bus store-and-forward mode?
+ unsigned sbus_store_and_forward:1;
+ // bit[31:13]
+ unsigned rsvd31_13:19;
+ }b;
+} usbdev3_gsbuscfg0_t;
+
+// rGSBUSCFG1
+typedef union
+{
+ u32 data; // reset value : 0x00000300
+ struct {
+ // bit[7:0] :
+ unsigned rsvd7_0:8;
+ // bit[11:8] : axi burst request limit
+ unsigned breq_limit:4;
+ // bit[12] : 1k page boundary enable
+ unsigned en_1kpage:1;
+ // bit[31:13]
+ unsigned rsvd31_13:19;
+ }b;
+} usbdev3_gsbuscfg1_t;
+
+// rGSCTL
+typedef union
+{
+ u32 data; // reset value : 0x30c02000
+ struct {
+ // bit[0] : Disable Clock Gating in LP Mode ( 0:Enable, 1:disable )
+ unsigned dis_clk_gating:1;
+ // bit[1] : HS/FS/LS Module Power Clamp
+ unsigned HsFsLsPwrClmp:1;
+ // bit[2] : SS Module Power Clamp
+ unsigned SsPwrClmp:1;
+ // bit[3] : Disable Data Scrambling in SS ( 0:enable, 1:disable )
+ unsigned DisScramble:1;
+ // bit[5:4] : Scale Down : for simulation
+ unsigned ScaleDown:2;
+ // bit[7:6] : ram clock select (0:bus, 1:pipe, 2:pipe/2, 3:rsvd)
+ unsigned ram_clk_sel:2;
+ // bit[8] : debug attach
+ unsigned debug_attach:1;
+ // bit[9] : loopback enable
+ unsigned phy_loopback_en:1;
+ // bit[10] : local loopback enable
+ unsigned local_loopback_en:1;
+ // bit[11] : core soft reset
+ unsigned core_soft_reset:1;
+ // bit[13:12] : port cabpbility direction (1:host, 2:device, 3:otg configuration)
+ unsigned port_capdir:2;
+ // bit[15:14] :
+ unsigned frm_scale_down:2;
+ // bit[16] :
+ unsigned u2rst_ecn:1;
+ // bit[18:17] :
+ unsigned rsvd18_17:2;
+ // bit[31:19] : power down scale
+ unsigned pwr_down_scale:13;
+ }b;
+} usbdev3_gctl_t;
+
+// GSTS
+typedef enum
+{
+ GSTS_CUR_OP_MODE_DEVICE, GSTS_CUR_OP_MODE_HOST, GSTS_CUR_OP_MODE_DRD
+} USBDEV3_GSTS_CUR_OP_MODE;
+typedef union
+{
+ u32 data; // reset value : 0x
+ struct {
+ // bit[1:0] : current mode of operation
+ unsigned cur_mod:2;
+ // bit[31:2] :
+ unsigned rsvd31_2:30;
+ }b;
+} usbdev3_gsts_t;
+
+// GUSB2PHYCFG
+typedef union
+{
+ u32 data; // reset value : 0x
+ struct {
+ // bit[2:0] :
+ unsigned timeout_cal:3;
+ // bit[3] : 0-> 8bit, 1-> 16bit
+ unsigned phy_if:1;
+ // bit[5:4] :
+ unsigned rsvd5_4:2;
+ // bit[6] :
+ unsigned suspend_usb2_phy:1;
+ // bit[7] :
+ unsigned rsvd7:1;
+ // bit[8] :
+ unsigned enable_sleep_n:1;
+ // bit[9] :
+ unsigned rsvd9:1;
+ // bit[13:10] :
+ unsigned turnaround_time:4;
+ // bit[30:14] :
+ unsigned rsvd30_14:17;
+ // bit[31] :
+ unsigned phy_soft_reset:1;
+ }b;
+} usbdev3_gusb2phycfg_t;
+
+// GUSB3PIPECTL
+typedef union
+{
+ u32 data; // reset value : 0x00260002
+ struct {
+ // bit[16:0] :
+ unsigned rsvd16_0:17;
+ // bit[17] : suspend USB3.0 SS PHY
+ unsigned suspend_usb3_ss_phy:1;
+ // bit[30:18] :
+ unsigned rsvd31_18:13;
+ // bit[31] : usb3 phy soft reset
+ unsigned phy_soft_reset:1;
+ }b;
+} usbdev3_gusb3pipectl_t;
+
+// GEVNTSIZ
+typedef union
+{
+ u32 data; // reset value : 0x00000000
+ struct {
+ // bit[15:0] : event buffer size in bytes (must be a multiple of 4)
+ unsigned event_siz:16;
+ // bit[30:16] :
+ unsigned rsvd30_16:15;
+ // bit[31] : event interrupt mask (1 : prevent the interrupt from being generated)
+ unsigned event_int_mask:1;
+ }b;
+} usbdev3_gevntsiz_t;
+
+//-----------------------
+// Device Registers (Dxxxx)
+//-----------------------
+// DCFG
+typedef enum
+{
+ USBDEV3_SPEED_SUPER = 4,
+ USBDEV3_SPEED_HIGH = 0,
+ USBDEV3_SPEED_FULL = 1
+}USBDEV3_SPEED_e;
+typedef union
+{
+ u32 data; // reset value : 0x00080804
+ struct {
+ // bit[2:0] : device speed
+ unsigned dev_speed:3;
+ // bit[9:3] : device address
+ unsigned dev_addr:7;
+ // bit[11:10] : periodic frame interval
+ unsigned per_fr_int:2;
+ // bit [16:12] : interrupt number
+ unsigned intr_num:5;
+ // bit[21:17] : # of rx buffers
+ unsigned num_rx_buf:5;
+ // bit[22] : lpm capable
+ unsigned lpm_cap:1;
+ // bit[23] : ignore stream pp ???
+ unsigned ignore_stream_pp:1;
+ // bit[31:24] :
+ unsigned rsvd31_24:8;
+ }b;
+} usbdev3_dcfg_t;
+
+typedef enum
+{
+ DCTL_TEST_MODE_DISABLED = 0,
+ DCTL_TEST_J_MODE = 1,
+ DCTL_TEST_K_MODE = 2,
+ DCTL_TEST_SE0_NAK_MODE = 3,
+ DCTL_TEST_PACKET_MODE = 4,
+ DCTL_TEST_FORCE_ENABLE = 5,
+ DCTL_TEST_CTRL_FIELD = 7
+} USBDEV3_DCTL_TEST_CTRL_e;
+
+// DCTL
+typedef union
+{
+ u32 data; // reset value : 0x0
+ struct {
+ // bit[0] :
+ unsigned rsvd0:1;
+ // bit[4:1] : Test Control
+ unsigned test_ctrl:4;
+ // bit[29:5] :
+ unsigned rsvd29_5:25;
+ // bit[30] : core soft reset
+ unsigned core_soft_reset:1;
+ // bit[31] : run/stop
+ unsigned run_stop:1;
+ }b;
+} usbdev3_dctl_t;
+
+// DEVTEN
+typedef union
+{
+ u32 data; // reset value : 0x0
+ struct {
+ // bit[0] : disconnect detected event enable
+ unsigned disconn_evt_en:1;
+ // bit[1] : usb reset enable
+ unsigned usb_reset_en:1;
+ // bit[2] : connection done enable
+ unsigned conn_done_en:1;
+ // bit[3] : usb/link state change event enable
+ unsigned usb_lnk_sts_chng_en:1;
+ // bit[4] : resume/remote wakeup detected event enable
+ unsigned wake_up_en:1;
+ // bit[5] :
+ unsigned rsvd5:1;
+ // bit[6] : end of periodic frame event enable
+ unsigned eopf_en:1;
+ // bit[7] : start of (micro)frame enable
+ unsigned sof_en:1;
+ // bit[8] :
+ unsigned rsvd8:1;
+ // bit[9] : erratic error event enable
+ unsigned errtic_err_en:1;
+ // bit[10] : generic command compete event enable
+ unsigned cmd_cmplt_en:1;
+ // bit[11] : event buffer overflow event enable
+ unsigned evnt_overflow_en:1;
+ // bit[12] : vendor device test LMP received event enable ???
+ unsigned vndr_dev_tst_rcved_en:1;
+ // bit[31:13] :
+ unsigned rsvd31_13:19;
+ }b;
+} usbdev3_devten_t;
+
+// DSTS
+typedef union
+{
+ u32 data; // reset value : 0x00020004
+ struct {
+ // bit[2:0] : connected speed(0:hs, 1:fs, 4:ss)
+ unsigned connect_speed:3;
+ // bit[16:3] : (u)frame # of the received SOF
+ unsigned soffn:14;
+ // bit[17] : RxFIFO Empty
+ unsigned rx_fifo_empty:1;
+ // bit[21:18] : USB/Link State
+ unsigned usb_link_sts:4;
+ // bit[22] : device controller halted
+ unsigned dev_ctrl_halted:1;
+ // bit[23] : core idle
+ unsigned core_idle:1;
+ // bit[24] : power up request
+ unsigned pwr_up_req:1;
+ // bit[31:25]
+ unsigned rsvd31_25:7;
+ }b;
+} usbdev3_dsts_t;
+
+// DGCMD
+typedef enum
+{
+ DGCMD_CMD_XMIT_SET_LINK_FUNC_LMP = 0x1,
+ DGCMD_CMD_SET_PERIODIC_PARAMS = 0x2,
+ DGCMD_CMD_XMIT_FUNC_WAKE_DEV_NOTIF = 0x3,
+ DGCMD_CMD_SELECTED_FIFO_FLUSH = 0x9,
+ DGCMD_CMD_ALL_FIFO_FLUSH = 0xa,
+ DGCMD_CMD_SET_EP_NRDY = 0xc,
+ DGCMD_CMD_RUN_SOC_BUS_LOOPBACK_TEST = 0x10
+} USBDEV3_DGCMD_CMD_e;
+
+typedef union
+{
+ u32 data; // reset value : 0x0
+ struct {
+ // bit[7:0] : command type
+ unsigned cmd_type:8;
+ // bit[8] : command interrupt on complete
+ unsigned ioc:1;
+ // bit[9]
+ unsigned rsvd9:1;
+ // bit[10] : command active
+ unsigned cmd_active:1;
+ // bit[14:11]
+ unsigned rsvd14_11:4;
+ // bit[15] : command completion status (0:error, 1:success)
+ unsigned cmd_sts:1;
+ // bit[31:16] :
+ unsigned rsvd31_16:16;
+ }b;
+} usbdev3_dgcmd_t;
+
+// DEPCMDPAR1
+ // This structure represents the bit fields in the Device Endpoint Command
+ // Parameter 1 Register (DEPCMDPAR1n) for the Set Endpoint Configuration
+ // (DEPCMD_SET_EP_CFG) command.
+typedef enum
+{
+ USBDEV3_EP_DIR_OUT = 0,
+ USBDEV3_EP_DIR_IN = 1
+} USBDEV3_EP_DIR_e;
+
+typedef union
+{
+ u32 data; // reset value : 0x0
+ struct {
+ // bit[4:0] : interrupt number
+ unsigned intr_num:5;
+ // bit[7:5]
+ unsigned rsvd7_5:3;
+ // bit[8] : transfer complete enable
+ unsigned xfer_cmpl_en:1;
+ // bit[9] : xfer in progress enable
+ unsigned xfer_in_prog_en:1;
+ // bit[10] : xfer not ready enable
+ unsigned xfer_nrdy_en:1;
+ // bit[11] : fifo under/over-run enable
+ unsigned fifo_xrun_en:1;
+ // bit[12]
+ unsigned rsvd12:1;
+ // bit[13] : stream event enable
+ unsigned str_evnt_en:1;
+ // bit[15:14]
+ unsigned rsvd15_14:2;
+ // bit[23:16] : b interval -1
+ unsigned binterval_m1:8;
+ // bit[24] : stream capable
+ unsigned strm_cap:1;
+ // bit[25] : ep direction(0:out, 1:in)
+ unsigned ep_dir:1;
+ // bit[29:26] : ep number
+ unsigned ep_num:4;
+ // bit[30] : bulk-base
+ unsigned bulk_based:1;
+ // bit[31] : fifo-based
+ unsigned fifo_based:1;
+ }b;
+} usbdev3_depcmdpar1_set_ep_cfg_t;
+
+// DEPCMDPAR0
+ // This structure represents the bit fields in the Device Endpoint Command
+ // Parameter 0 Register (DEPCMDPAR0n) for the Set Endpoint Configuration
+ // (DEPCMD_SET_EP_CFG) command.
+typedef enum
+{
+ USBDEV3_EP_CTRL = 0,
+ USBDEV3_EP_ISOC = 1,
+ USBDEV3_EP_BULK = 2,
+ USBDEV3_EP_INTR = 3
+}USBDEV3_EP_TYPE_e;
+
+typedef union
+{
+ u32 data; // reset value : 0x0
+ struct {
+ // bit[0]
+ unsigned rsvd0:1;
+ // bit[2:1] : ep type
+ unsigned ep_type:2;
+ // bit[13:3] : maximum packet size
+ unsigned mps:11;
+ // bit[16:14]
+ unsigned rsvd16_14:3;
+ // bit[21:17] : fifo number
+ unsigned fifo_num:5;
+ // bit[25:22] : burst size
+ unsigned brst_siz:4;
+ // bit[30:26] : data sequence number
+ unsigned ds_num:5;
+ // bit[31] : ignor sequence number
+ unsigned ign_dsnum:1;
+ }b;
+} usbdev3_depcmdpar0_set_ep_cfg_t;
+
+// DEPCMD
+typedef enum
+{
+ DEPCMD_CMD_RSVD = 0x0,
+ DEPCMD_CMD_SET_EP_CFG = 0x1,
+ DEPCMD_CMD_SET_EP_XFER_RSRC_CFG = 0x2,
+ DEPCMD_CMD_GET_DATA_SEQ_NUM = 0x3,
+ DEPCMD_CMD_SET_STALL = 0x4,
+ DEPCMD_CMD_CLR_STALL = 0x5,
+ DEPCMD_CMD_START_XFER = 0x6,
+ DEPCMD_CMD_UPDATE_XFER = 0x7,
+ DEPCMD_CMD_END_XFER = 0x8,
+ DEPCMD_CMD_START_NEW_CFG = 0x9
+} USBDEV3_DEPCMD_CMD_TYPE_e;
+typedef union
+{
+ u32 data; // reset value : 0x0
+ struct {
+ // bit[3:0] : Command Type
+ unsigned cmd_type:4;
+ // bit[7:4]
+ unsigned rsvd7_4:4;
+ // bit[8] : command interrupt on complete
+ unsigned ioc:1;
+ // bit9]
+ unsigned rsvd9:1;
+ // bit[10] : command active
+ unsigned cmd_active:1;
+ // bit[11] : high priority(only valid for start transfer command), forceRM(only valid for end transfer command)
+ unsigned hipri_forcerm:1;
+ // bit[15:12] : command completion status
+ unsigned cmd_sts:4;
+ // bit[31:16] : command parameters(written case), event parameters(read case)
+ unsigned param:16;
+ }b;
+} usbdev3_depcmd_t;
+
+/////////////////////////////////////////////////
+// Event Buffer Structures
+//
+
+#define USBDEV3_EVENT_BUFFER_COUNT 128 //256
+
+// Event Buffer for Device Endpoint-Specific Events
+typedef enum
+{
+ DEPEVT_EVT_XFER_CMPL = 1,
+ DEPEVT_EVT_XFER_IN_PROG = 2,
+ DEPEVT_EVT_XFER_NRDY = 3,
+ DEPEVT_EVT_FIFOXRUN = 4,
+ DEPEVT_EVT_STRM_EVT = 6,
+ DEPEVT_EVT_EPCMD_CMPL = 7,
+}USBDEV3_DEPEVT_EVT_e;
+
+typedef union
+{
+ u32 data;
+ struct {
+ // bit[0] : 0-> ep-specific event
+ unsigned non_ep_evnt:1;
+ // bit[5:1] : ep number
+ unsigned ep_num:5;
+ // bit[9:6] : event type
+ unsigned evt_type:4;
+ // bit[11:10]
+ unsigned rsvd11_10:2;
+ // bit[15:12] : event status
+ unsigned evnt_sts:4;
+ // bit[31:16] : event parameters
+ unsigned evnt_param:16;
+ }b;
+}usbdev3_depevt_t;
+
+// Event Buffer for Device-Specific Events
+typedef enum
+{
+ DEVT_DISCONN = 0,
+ DEVT_USBRESET = 1,
+ DEVT_CONNDONE = 2,
+ DEVT_ULST_CHNG = 3,
+ DEVT_WKUP = 4,
+ DEVT_EOPF = 6,
+ DEVT_SOF = 7,
+ DEVT_ERRATICERR = 9,
+ DEVT_CMD_CMPL = 10,
+ DEVT_OVERFLOW = 11,
+ DEVT_VNDR_DEV_TST_RCVD = 12,
+ DEVT_INACT_TIMEOUT_RCVD = 13,
+}USBDEV3_DEVT_e;
+
+typedef union
+{
+ u32 data;
+ struct {
+ // bit[0] : 1-> device-specific event
+ unsigned non_ep_evnt:1;
+ // bit[7:1] : 0-> device specific, 1-> OTG, 3-> ULPI Carkit, 4-> I2C
+ unsigned dev_specific:7;
+ // bit[11:8] : event type
+ unsigned evt_type:4;
+ // bit[15:12]
+ unsigned rsvd15_12:4;
+ // bit[23:16] : event information bits
+ unsigned evt_info:8;
+ // bit[31:24]
+ unsigned rsvd31_24:8;
+ }b;
+}usbdev3_devt_t;
+//
+
+/////////////////////////////////////////////////
+// DMA Descriptor Specific Structures
+//
+
+// Limit of bytes in one TRB
+#define TRB_BUF_SIZ_LIMIT 16777215 //2^24 - 1 (16MB -1byte)
+
+// status field of TRB
+typedef union
+{
+ u32 data;
+ struct
+ {
+ // bit[23:0] : buffer size
+ unsigned buf_siz:24;
+ // bit[25:24] : packet count minus 1
+ unsigned pkt_cnt_m1:2;
+ // bit[27:26]
+ unsigned rsvd27_26:2;
+ // bit[31:28] : TRB status
+ unsigned trb_sts:4;
+ }b;
+}usbdev3_trb_sts_t;
+
+typedef enum
+{
+ TRB_CTRL_NORMAL = 1, // Control-Data-2+ / bulk / Interrupt
+ TRB_CTRL_SETUP = 2,
+ TRB_CTRL_STATUS_2 = 3,
+ TRB_CTRL_STATUS_3 = 4,
+ TRB_CTRL_CTLDATA_1ST = 5, // 1st TRB of Data stage
+ TRB_CTRL_ISOC_1ST = 6, // 1st TRB of Service Interval
+ TRB_CTRL_ISOC = 7,
+ TRB_CTRL_LINK = 8, // Link TRB
+} USBDEV3_TRB_TYPE_e;
+
+// control field of TRB
+typedef union
+{
+ u32 data;
+ struct
+ {
+ // bit[0] : h/w owner of descriptor
+ unsigned hwo:1;
+ // bit[1] : last TRB
+ unsigned lst:1;
+ // bit[2] : chain buffers
+ unsigned chn:1;
+ // bit[3] : continue on short packet
+ unsigned csp:1;
+ // bit[9:4] : TRB control
+ unsigned trb_ctrl:6;
+ // bit[10] : interrupt on short packet/ interrupt on missed ISOC
+ unsigned isp_imi:1;
+ // bit[11] : interrupt on complete
+ unsigned ioc:1;
+ // bit[13:12]
+ unsigned rsvd13_12:2;
+ // bit[29:14] : stream ID/ SOF #
+ unsigned strmid_sofn:16;
+ // bit[31:30]
+ unsigned rsvd31_30:2;
+ }b;
+} usbdev3_trb_ctrl_t;
+
+// TRB structure
+typedef struct
+{
+ u32 buf_ptr_l; // buffer pointer low
+ u32 buf_ptr_h; // buffer pointer high
+ usbdev3_trb_sts_t status;
+ usbdev3_trb_ctrl_t control;
+} usbdev3_trb_t, *usbdev3_trb_ptr_t;
+
+
+//------------------------------------------------
+// USBDEV state
+typedef enum
+{
+ USBDEV3_STATE_DEFAULT,
+ USBDEV3_STATE_ADDRESSED,
+ USBDEV3_STATE_CONFIGURED,
+} USBDEV3_STATE;
+
+typedef struct
+{
+ union {
+ USB_DESCRIPTORS m_oDesc;
+ USB_SS_DESCRIPTORS m_oSSDesc;
+ };
+
+ DEVICE_REQUEST m_oDeviceRequest;
+
+ u32 m_uEp0State;
+ u32 m_uEp0SubState;
+ USBDEV3_SPEED_e m_eSpeed;
+ u32 m_uControlEPMaxPktSize;
+ u32 m_uBulkEPMaxPktSize;
+ u32 m_uDownloadAddress;
+ u32 m_uDownloadFileSize;
+ u32 m_uUploadAddr;
+ u32 m_uUploadSize;
+ u8* m_pDownPt;
+ u8* m_pUpPt;
+ USBDEV3_STATE m_eUsbDev3State;
+ u32 m_uDeviceRequestLength;
+ u8 m_bEp0ThreeStage;
+
+ u8 m_bEPs_Enabled;
+
+ u32 m_uLinkBaseRegs;
+ u32 m_uPhyBaseRegs;
+ u32 *m_pEventBuffer;
+ u16 m_CurrentEventPosition;
+
+ // Buffer for GET_STATUS & GET_DESCRIPTOR up to 512 bytes in length
+ u32 m_uStatusBufAddr;
+
+ // SET_SEL request pending info
+ u8 m_bReq_Set_sel;
+
+ // TRB for Setup Packet
+ volatile usbdev3_trb_ptr_t m_oSetupTrbPtr;
+
+ // TRB for Data-Out or Status-Out phase
+ volatile usbdev3_trb_ptr_t m_oOutTrbPtr;
+
+ // TRB for Data-In or Status-In phase
+ volatile usbdev3_trb_ptr_t m_oInTrbPtr;
+
+ // Transfer Resource Index for Each EP
+ u32 m_uTriOut[TOTL_EP_COUNT];
+ u32 m_uTriIn[TOTL_EP_COUNT];
+
+ // Stall Status for Each EP
+ u8 m_bEpOutStalled[TOTL_EP_COUNT];
+ u8 m_bEpInStalled[TOTL_EP_COUNT];
+
+ CABLE_STATUS m_cable;
+} USBDEV3;
+
+// EP0 state
+enum EP0_STATE
+{
+ EP0_STATE_UNCONNECTED = 0xffff,
+ EP0_STATE_INIT = 0,
+ EP0_STATE_IN_DATA_PHASE = 1,
+ EP0_STATE_OUT_DATA_PHASE = 2,
+ EP0_STATE_IN_WAIT_NRDY = 3,
+ EP0_STATE_OUT_WAIT_NRDY = 4,
+ EP0_STATE_IN_STATUS_PHASE = 5,
+ EP0_STATE_OUT_STATUS_PHASE = 6,
+ EP0_STATE_STALL = 7
+};
+
+//=====================================================================================
+// prototypes of API functions
+void Isr_UsbDev3(void);
+u8 USBDEV3_Init(USBDEV3_SPEED_e eSpeed);
+void USBDEV3_DeInit(void);
+
+u8 USBDEV3_IsUsbDevSetConfiguration(void);
+
+void USBDEV3_Prepare1stBulkOutTrb(void);
+
+void USBDEV3_ClearDownFileInfo(void);
+void USBDEV3_GetDownFileInfo(u32* uDownAddr, u32* uDownFileSize, u8* bIsFinished);
+void USBDEV3_ClearUpFileInfo(void);
+void USBDEV3_GetUpFileInfo(u32* uUpAddr, u32* uUpFileSize, u8* bIsFinished);
+u8 USBDEV3_VerifyChecksum(void);
+void USBDEV3_OpenUsingUsbDownAddr(u32 Addr);
+void USBDEV3_CloseUsingUsbDownAddr(void);
+u32 USBDEV3_AllocateDataStructure(u32 uSize, u32 uAlign);
+void USBDEV3_FreeDataStructure(u32 uAddr);
+
+int exynos_usbctl_init(void);
+int exynos_usbc_activate (void);
+int exynos_usb_stop( void );
+int exynos_udc_int_hndlr(void);
+
+/* in usbd3-ss.c */
+extern unsigned int exynos_usbd_dn_addr;
+extern unsigned int exynos_usbd_dn_cnt;
+extern int DNW;
+extern int exynos_got_header;
+extern int exynos_receive_done;
+
+#endif
diff --git a/include/configs/odroid_xu4.h b/include/configs/odroid_xu4.h
index 248302922c..18b2dc9bea 100755
--- a/include/configs/odroid_xu4.h
+++ b/include/configs/odroid_xu4.h
@@ -69,6 +69,13 @@
#define PART_SIZE_CACHE SZ_256M
#define ANDROID_PART_START SZ_64M
+#define CFG_FASTBOOT_TRANSFER_BUFFER (CONFIG_SYS_SDRAM_BASE + 0x8000000)
+#define CFG_FASTBOOT_TRANSFER_BUFFER_SIZE (0x30000000) /* 768MB */
+#define CFG_FASTBOOT_ADDR_KERNEL (CONFIG_SYS_SDRAM_BASE + 0x8000)
+#define CFG_FASTBOOT_ADDR_RAMDISK (CONFIG_SYS_SDRAM_BASE + 0x1000000)
+#define CFG_FASTBOOT_PAGESIZE (2048) // Page size of booting device
+#define CFG_FASTBOOT_SDMMC_BLOCKSIZE (512) // Block size of sdmmc
+
#endif /* #if defined(CONFIG_FASTBOOT) */
#define CONFIG_ENV_IS_IN_MMC
@@ -115,6 +122,23 @@
#define CONFIG_USB_EHCI
#define CONFIG_USB_EHCI_EXYNOS
+/*
+#define CONFIG_EXYNOS_USBD3
+*/
+#define EXYNOS_SYSREG_BASE EXYNOS5_SYSREG_BASE
+#define EXYNOS_POWER_BASE EXYNOS5_POWER_BASE
+
+/*
+ * USBD 3.0 SFR
+ */
+#define USBDEVICE3_LINK_CH0_BASE 0x12000000
+#define USBDEVICE3_PHYCTRL_CH0_BASE 0x12100000
+#define USBDEVICE3_LINK_CH1_BASE 0x12400000
+#define USBDEVICE3_PHYCTRL_CH1_BASE 0x12500000
+
+#define EXYNOS_USB_PHY_BASE EXYNOS5_USBPHY_BASE
+#define EXYNOS_USB_LINK_BASE EXYNOS5_USBOTG_BASE
+
/* DFU */
#define CONFIG_SYS_DFU_DATA_BUF_SIZE SZ_32M
#define DFU_DEFAULT_POLL_TIMEOUT 300
diff --git a/include/fastboot.h b/include/fastboot.h
index 616631e9aa..b47196979c 100644..100755
--- a/include/fastboot.h
+++ b/include/fastboot.h
@@ -19,4 +19,292 @@
void fastboot_fail(const char *reason);
void fastboot_okay(const char *reason);
+#if defined(CONFIG_TARGET_ODROID_XU4) || defined(CONFIG_TARGET_ODROID_XU3)
+#include <common.h>
+#include <command.h>
+
+#include <asm/byteorder.h>
+#include <asm/arch/cpu.h>
+#include <asm/io.h>
+
+/* This is the interface file between the common cmd_fastboot.c and
+ the board specific support.
+
+ To use this interface, define CONFIG_FASTBOOT in your board config file.
+ An example is include/configs/omap3430labrador.h
+ ...
+ #define CONFIG_FASTBOOT 1 / * Using fastboot interface * /
+ ...
+
+ An example of the board specific spupport for omap3 is found at
+ cpu/omap3/fastboot.c
+
+*/
+
+/* From fastboot client.. */
+#define FASTBOOT_INTERFACE_CLASS 0xff
+#define FASTBOOT_INTERFACE_SUB_CLASS 0x42
+#define FASTBOOT_INTERFACE_PROTOCOL 0x03
+
+#define FASTBOOT_VERSION "0.4"
+
+/* The fastboot client uses a value of 2048 for the
+ page size of it boot.img file format.
+ Reset this in your board config file as needed. */
+#ifndef CFG_FASTBOOT_MKBOOTIMAGE_PAGE_SIZE
+#define CFG_FASTBOOT_MKBOOTIMAGE_PAGE_SIZE 2048
+#endif
+
+struct cmd_fastboot_interface
+{
+ /* This function is called when a buffer has been
+ recieved from the client app.
+ The buffer is a supplied by the board layer and must be unmodified.
+ The buffer_size is how much data is passed in.
+ Returns 0 on success
+ Returns 1 on failure
+
+ Set by cmd_fastboot */
+ int (*rx_handler)(const unsigned char *buffer,
+ unsigned int buffer_size);
+
+ /* This function is called when an exception has
+ occurred in the device code and the state
+ off fastboot needs to be reset
+
+ Set by cmd_fastboot */
+ void (*reset_handler)(void);
+
+ /* A getvar string for the product name
+ It can have a maximum of 60 characters
+
+ Set by board */
+ char *product_name;
+
+ /* A getvar string for the serial number
+ It can have a maximum of 60 characters
+
+ Set by board */
+ char *serial_no;
+
+ /* Nand block size
+ Supports the write option WRITE_NEXT_GOOD_BLOCK
+
+ Set by board */
+ unsigned int nand_block_size;
+
+ /* Transfer buffer, for handling flash updates
+ Should be multiple of the nand_block_size
+ Care should be take so it does not overrun bootloader memory
+ Controlled by the configure variable CFG_FASTBOOT_TRANSFER_BUFFER
+
+ Set by board */
+ unsigned char *transfer_buffer;
+
+ /* How big is the transfer buffer
+ Controlled by the configure variable
+ CFG_FASTBOOT_TRANSFER_BUFFER_SIZE
+
+ Set by board */
+ unsigned int transfer_buffer_size;
+
+};
+
+/* Android-style flash naming */
+typedef struct fastboot_ptentry fastboot_ptentry;
+
+/* flash partitions are defined in terms of blocks
+** (flash erase units)
+*/
+struct fastboot_ptentry
+{
+ /* The logical name for this partition, null terminated */
+ char name[16];
+ /* The start wrt the nand part, must be multiple of nand block size */
+ unsigned long long start;
+ /* The length of the partition, must be multiple of nand block size */
+ unsigned long long length;
+ /* Controls the details of how operations are done on the partition
+ See the FASTBOOT_PTENTRY_FLAGS_*'s defined below */
+ unsigned int flags;
+};
+
+/* Lower byte shows if the read/write/erase operation in
+ repeated. The base address is incremented.
+ Either 0 or 1 is ok for a default */
+
+#define FASTBOOT_PTENTRY_FLAGS_REPEAT(n) (n & 0x0f)
+#define FASTBOOT_PTENTRY_FLAGS_REPEAT_MASK 0x0000000F
+
+/* Writes happen a block at a time.
+ If the write fails, go to next block
+ NEXT_GOOD_BLOCK and CONTIGOUS_BLOCK can not both be set */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_NEXT_GOOD_BLOCK 0x00000010
+
+/* Find a contiguous block big enough for a the whole file
+ NEXT_GOOD_BLOCK and CONTIGOUS_BLOCK can not both be set */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_CONTIGUOUS_BLOCK 0x00000020
+
+/* Sets the ECC to hardware before writing
+ HW and SW ECC should not both be set. */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_HW_ECC 0x00000040
+
+/* Sets the ECC to software before writing
+ HW and SW ECC should not both be set. */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_SW_ECC 0x00000080
+
+/* Write the file with write.i */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_I 0x00000100
+
+/* Write the file with write.yaffs */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_YAFFS 0x00000200
+
+/* Write the file as a series of variable/value pairs
+ using the setenv and saveenv commands */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_ENV 0x00000400
+
+/* Use mmc command to read/write this partition */
+#define FASTBOOT_PTENTRY_FLAGS_USE_MMC_CMD 0x00010000
+
+/* Use movi command to read/write this partition */
+#define FASTBOOT_PTENTRY_FLAGS_USE_MOVI_CMD 0x00020000
+
+/* Status values */
+#define FASTBOOT_OK 0
+#define FASTBOOT_ERROR -1
+#define FASTBOOT_DISCONNECT 1
+#define FASTBOOT_INACTIVE 2
+
+/* Magic string to enable fastboot during preboot */
+#define FASTBOOT_REBOOT_MAGIC "REBOOT-FASTBOOT"
+#define FASTBOOT_REBOOT_MAGIC_SIZE 15
+
+/* Android bootimage file format */
+#define FASTBOOT_BOOT_MAGIC "ANDROID!"
+#define FASTBOOT_BOOT_MAGIC_SIZE 8
+#define FASTBOOT_BOOT_NAME_SIZE 16
+#define FASTBOOT_BOOT_ARGS_SIZE 512
+
+/* Input of fastboot_tx_status */
+#define FASTBOOT_TX_ASYNC 0
+#define FASTBOOT_TX_SYNC 1
+
+struct fastboot_boot_img_hdr {
+ unsigned char magic[FASTBOOT_BOOT_MAGIC_SIZE];
+
+ unsigned kernel_size; /* size in bytes */
+ unsigned kernel_addr; /* physical load addr */
+
+ unsigned ramdisk_size; /* size in bytes */
+ unsigned ramdisk_addr; /* physical load addr */
+
+ unsigned second_size; /* size in bytes */
+ unsigned second_addr; /* physical load addr */
+
+ unsigned tags_addr; /* physical addr for kernel tags */
+ unsigned page_size; /* flash page size we assume */
+ unsigned unused[2]; /* future expansion: should be 0 */
+
+ unsigned char name[FASTBOOT_BOOT_NAME_SIZE]; /* asciiz product name */
+
+ unsigned char cmdline[FASTBOOT_BOOT_ARGS_SIZE];
+
+ unsigned id[8]; /* timestamp / checksum / sha1 / etc */
+};
+
+#if defined(CONFIG_FASTBOOT)
+/* A board specific test if u-boot should go into the fastboot command
+ ahead of the bootcmd
+ Returns 0 to continue with normal u-boot flow
+ Returns 1 to execute fastboot */
+extern int fastboot_preboot(void);
+
+/* Initizes the board specific fastboot
+ Returns 0 on success
+ Returns 1 on failure */
+extern int fastboot_init(struct cmd_fastboot_interface *interface);
+
+/* Cleans up the board specific fastboot */
+extern void fastboot_shutdown(void);
+
+/*
+ * Handles board specific usb protocol exchanges
+ * Returns 0 on success
+ * Returns 1 on disconnects, break out of loop
+ * Returns 2 if no USB activity detected
+ * Returns -1 on failure, unhandled usb requests and other error conditions
+*/
+extern int fastboot_poll(void);
+
+/* Is this high speed (2.0) or full speed (1.1) ?
+ Returns 0 on full speed
+ Returns 1 on high speed */
+extern int fastboot_is_highspeed(void);
+
+/* Return the size of the fifo */
+extern int fastboot_fifo_size(void);
+
+/* Send a status reply to the client app
+ buffer does not have to be null terminated.
+ buffer_size must be not be larger than what is returned by
+ fastboot_fifo_size
+ Returns 0 on success
+ Returns 1 on failure */
+extern int fastboot_tx_status(const char *buffer, unsigned int buffer_size, const u32 need_sync_flag);
+
+/* A board specific variable handler.
+ The size of the buffers is governed by the fastboot spec.
+ rx_buffer is at most 57 bytes
+ tx_buffer is at most 60 bytes
+ Returns 0 on success
+ Returns 1 on failure */
+extern int fastboot_getvar(const char *rx_buffer, char *tx_buffer);
+
+/* The Android-style flash handling */
+
+/* tools to populate and query the partition table */
+extern void fastboot_flash_add_ptn(fastboot_ptentry *ptn);
+extern fastboot_ptentry *fastboot_flash_find_ptn(const char *name);
+extern fastboot_ptentry *fastboot_flash_get_ptn(unsigned n);
+extern unsigned int fastboot_flash_get_ptn_count(void);
+extern void fastboot_flash_dump_ptn(void);
+
+extern int fastboot_flash_init(void);
+extern int fastboot_flash_erase(fastboot_ptentry *ptn);
+extern int fastboot_flash_read_ext(fastboot_ptentry *ptn,
+ unsigned extra_per_page, unsigned offset,
+ void *data, unsigned bytes);
+#define fastboot_flash_read(ptn, offset, data, bytes) \
+ flash_read_ext(ptn, 0, offset, data, bytes)
+extern int fastboot_flash_write(fastboot_ptentry *ptn, unsigned extra_per_page,
+ const void *data, unsigned bytes);
+
+
+#else
+
+/* Stubs for when CONFIG_FASTBOOT is not defined */
+#define fastboot_preboot() 0
+#define fastboot_init(a) 1
+#define fastboot_shutdown()
+#define fastboot_poll() 1
+#define fastboot_is_highspeed() 0
+#define fastboot_fifo_size() 0
+#define fastboot_tx_status(a, b, c) 1
+#define fastboot_getvar(a,b) 1
+
+#define fastboot_flash_add_ptn(a)
+#define fastboot_flash_find_ptn(a) NULL
+#define fastboot_flash_get_ptn(a) NULL
+#define fastboot_flash_get_ptn_count() 0
+#define fastboot_flash_dump_ptn()
+#define fastboot_flash_init()
+#define fastboot_flash_erase(a) 1
+#define fastboot_flash_read_ext(a, b, c, d, e) 0
+#define fastboot_flash_read(a, b, c, d, e) 0
+#define fastboot_flash_write(a, b, c, d) 0
+
+#endif /* CONFIG_FASTBOOT */
+
+#endif /* #if defined(CONFIG_TARGET_ODROID_XU4) || defined(CONFIG_TARGET_ODROID_XU3) */
+
#endif /* _FASTBOOT_H_ */