diff options
author | Inderpal Singh <inderpal.singh@linaro.org> | 2012-10-23 17:16:08 +0530 |
---|---|---|
committer | John Rigby <john.rigby@linaro.org> | 2012-12-06 13:51:42 -0700 |
commit | a111cd0051581055481d6ed9df21804b9db1727a (patch) | |
tree | 7d142d019d6f8f382b9e84328c2164a3dbecc501 | |
parent | e4d8b1a03c918b8c47afb49590d1c79d829fc4d0 (diff) |
Add DNW Support for Origen Quad board
Signed-off-by: Inderpal Singh <inderpal.singh@linaro.org>
-rw-r--r-- | common/Makefile | 1 | ||||
-rw-r--r-- | common/cmd_usbd.c | 129 | ||||
-rw-r--r-- | common/cpu.h | 768 | ||||
-rw-r--r-- | drivers/usb/gadget/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/gadget/usbd-otg-hs.c | 1936 | ||||
-rw-r--r-- | drivers/usb/gadget/usbd-otg-hs.h | 306 | ||||
-rw-r--r-- | drivers/usb/host/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/host/usb_ohci.c | 750 | ||||
-rw-r--r-- | drivers/usb/host/usb_ohci.h | 397 | ||||
-rw-r--r-- | include/configs/origen_quad.h | 21 |
10 files changed, 4308 insertions, 2 deletions
diff --git a/common/Makefile b/common/Makefile index 9e4332221..910a80e72 100644 --- a/common/Makefile +++ b/common/Makefile @@ -28,6 +28,7 @@ LIB = $(obj)libcommon.o # core ifndef CONFIG_SPL_BUILD COBJS-y += main.o +COBJS-$(CONFIG_S3C_USBD) += cmd_usbd.o COBJS-y += command.o COBJS-y += exports.o COBJS-$(CONFIG_SYS_HUSH_PARSER) += hush.o diff --git a/common/cmd_usbd.c b/common/cmd_usbd.c new file mode 100644 index 000000000..7b7a930e6 --- /dev/null +++ b/common/cmd_usbd.c @@ -0,0 +1,129 @@ +/* + * common/cmd_usbd.c + * + * $Id: cmd_usbd.c,v 1.2 2009/01/28 00:11:42 dark0351 Exp $ + * + * (C) Copyright 2007 + * Byungjae Lee, Samsung Erectronics, bjlee@samsung.com. + * - support for S3C2412, S3C2443 and S3C6400 + * + * (C) Copyright SAMSUNG Electronics + * SW.LEE <hitchcar@samsung.com> + * - add USB device fo S3C2440A, S3C24A0A + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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 as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +/* + * Memory Functions + * + * Copied from FADS ROM, Dan Malek (dmalek@jlc.net) + */ + +#include <common.h> +#include <command.h> +#include "cpu.h" + +#ifdef CONFIG_S3C_USBD + +//#include <s5pv310.h> + +#if defined(CONFIG_S3C2412) || defined(CONFIG_S3C2442) +#include "../cpu/s3c24xx/usbd-fs.h" +#elif defined(CONFIG_S3C2443) || \ + defined(CONFIG_S3C2450) || \ + defined(CONFIG_S3C2416) +#include "../cpu/s3c24xx/usbd-hs.h" +#elif defined(CONFIG_S3C6400) || \ + defined(CONFIG_S3C6410) || \ + defined(CONFIG_S3C6430) +#include "../cpu/s3c64xx/usbd-otg-hs.h" +#elif defined(CONFIG_S5PC100) +#include "../cpu/s5pc1xx/usbd-otg-hs.h" +#elif defined(CONFIG_S5PC210) || defined(CONFIG_EXYNOS4) +#include "../drivers/usb/gadget/usbd-otg-hs.h" +#elif defined(CONFIG_S5P6440) +#include "../cpu/s5p64xx/usbd-otg-hs.h" +#elif defined(CONFIG_S5P6442) +#include "../cpu/s5p644x/usbd-otg-hs.h" +#else +#error "* CFG_ERROR : you have to setup right Samsung CPU configuration" +#endif + +#undef CMD_USBD_DEBUG +#ifdef CMD_USBD_DEBUG +#define PRINTF(fmt, args...) printf(fmt, ##args) +#else +#define PRINTF(fmt, args...) +#endif + +static const char pszMe[] = "usbd: "; + +int do_usbd_dnw(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + + if (argv[0][0] == 'u') { + DNW = 0; + } else { + DNW = 1; + s3c_got_header = 0; + } + + switch (argc) { + case 1: + s3c_usbd_dn_addr = USBD_DOWN_ADDR; /* Default Address */ + break; + case 2: + s3c_usbd_dn_addr = simple_strtoul(argv[1], NULL, 16); + break; + default: + printf("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + s3c_receive_done = 0; + + s3c_usbctl_init(); + s3c_usbc_activate(); + + PRINTF("Download address 0x%08x\n", s3c_usbd_dn_addr); + printf("Now, Waiting for DNW to transmit data\n"); + + while (1) { + if (S3C_USBD_DETECT_IRQ()) { + s3c_udc_int_hndlr(); + S3C_USBD_CLEAR_IRQ(); + } + + if (s3c_receive_done) + break; + + if (serial_tstc()) { + serial_getc(); + break; + } + } + + /* when operation is done, usbd must be stopped */ + s3c_usb_stop(); + + return 0; +} + +U_BOOT_CMD( + dnw, 3, 0, do_usbd_dnw, + "dnw - initialize USB device and ready \ + to receive for Windows server (specific)\n", + "[download address]\n" +); + +#endif /* CONFIG_S3C_USBD */ diff --git a/common/cpu.h b/common/cpu.h new file mode 100644 index 000000000..2d9ca0f52 --- /dev/null +++ b/common/cpu.h @@ -0,0 +1,768 @@ +/* + * (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 _S5PV310_CPU_H +#define _S5PV310_CPU_H + +#ifdef CONFIG_CPU_EXYNOS5210 +#include "cpu_exynos5210.h" +#elif CONFIG_CPU_EXYNOS5250 +#include "cpu_exynos5250.h" +#else + +//#define S5PV310_ADDR_BASE 0xE0000000 +/* S5PV310 */ +#define S5PV310_PRO_ID 0x10000000 +#define S5PV310_SYSREG_BASE 0x10010000 +#define S5PV310_POWER_BASE 0x10020000 +#define S5PV310_CLOCK_BASE 0x10030000 +//#define S5PC100_GPIO_BASE 0xE0300000 +//#define S5PC100_VIC0_BASE 0xE4000000 +//#define S5PC100_VIC1_BASE 0xE4100000 +//#define S5PC100_VIC2_BASE 0xE4200000 +//#define S5PC100_DMC_BASE 0xE6000000 +//#define S5PC100_SROMC_BASE 0xE7000000 +//#define S5PC100_ONENAND_BASE 0xE7100000 +#define S5PV310_HSMMC_BASE 0x12510000 +#define S5PV310_PWMTIMER_BASE 0x139D0000 +//#define S5PC100_WATCHDOG_BASE 0xEA200000 +#define S5PV310_UART_BASE 0x13800000 +//#define S5PC100_MMC_BASE 0xED800000 + +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +#define __REG(x) (*(unsigned int *)(x)) + +/* + * CHIP ID + */ +#define CHIP_ID_BASE 0x10000000 + +#define PRO_ID_OFFSET 0x0 +#define PRO_ID __REG(CHIP_ID_BASE+PRO_ID_OFFSET) + +/* + * SYSREG + */ +#define GENERAL_CTRL_C2C_OFFSET 0x10C +#define USB_CFG_OFFSET 0x21C +#define USB_CFG_REG (S5PV310_SYSREG_BASE+USB_CFG_OFFSET) + +/* + * POWER + */ +#define OMR_OFFSET 0x0 +#define SW_RST_REG_OFFSET 0x400 +#define SW_RST_REG __REG(S5PV310_POWER_BASE+SW_RST_REG_OFFSET) + +#define INF_REG_BASE 0x10020800 + +#define INF_REG0_OFFSET 0x00 +#define INF_REG1_OFFSET 0x04 +#define INF_REG2_OFFSET 0x08 +#define INF_REG3_OFFSET 0x0c +#define INF_REG4_OFFSET 0x10 +#define INF_REG5_OFFSET 0x14 +#define INF_REG6_OFFSET 0x18 +#define INF_REG7_OFFSET 0x1c + +#define C2C_CTRL_OFFSET 0x24 + +#define INF_REG0_REG __REG(INF_REG_BASE+INF_REG0_OFFSET) +#define INF_REG1_REG __REG(INF_REG_BASE+INF_REG1_OFFSET) +#define INF_REG2_REG __REG(INF_REG_BASE+INF_REG2_OFFSET) +#define INF_REG3_REG __REG(INF_REG_BASE+INF_REG3_OFFSET) +#define INF_REG4_REG __REG(INF_REG_BASE+INF_REG4_OFFSET) +#define INF_REG5_REG __REG(INF_REG_BASE+INF_REG5_OFFSET) +#define INF_REG6_REG __REG(INF_REG_BASE+INF_REG6_OFFSET) +#define INF_REG7_REG __REG(INF_REG_BASE+INF_REG7_OFFSET) + +/* Define Mode */ +#define S5P_CHECK_SLEEP 0x00000BAD +#define S5P_CHECK_DIDLE 0xBAD00000 +#define S5P_CHECK_LPA 0xABAD0000 + +/* + * CLOCK + */ +#define ELFIN_CLOCK_BASE 0x10030000 + +#define CLK_SRC_LEFTBUS_OFFSET 0x04200 +#define CLK_DIV_LEFTBUS_OFFSET 0x04500 + +#define CLK_SRC_RIGHTBUS_OFFSET 0x08200 +#define CLK_DIV_RIGHTBUS_OFFSET 0x08500 + +#define EPLL_LOCK_OFFSET 0x0C010 +#define VPLL_LOCK_OFFSET 0x0C020 +#define EPLL_CON0_OFFSET 0x0C110 +#define EPLL_CON1_OFFSET 0x0C114 +#ifdef CONFIG_SMDKC220 +#define EPLL_CON2_OFFSET 0x0C118 +#endif +#define VPLL_CON0_OFFSET 0x0C120 +#define VPLL_CON1_OFFSET 0x0C124 +#ifdef CONFIG_SMDKC220 +#define VPLL_CON2_OFFSET 0x0C128 +#endif + +#define CLK_SRC_TOP0_OFFSET 0x0C210 +#define CLK_SRC_TOP1_OFFSET 0x0C214 +#define CLK_SRC_FSYS_OFFSET 0x0C240 +#define CLK_SRC_PERIL0_OFFSET 0x0C250 +#define CLK_DIV_TOP_OFFSET 0x0C510 +#define CLK_DIV_FSYS1_OFFSET 0x0C544 +#define CLK_DIV_FSYS2_OFFSET 0x0C548 +#define CLK_DIV_FSYS3_OFFSET 0x0C54C +#define CLK_DIV_PERIL0_OFFSET 0x0C550 + +#define CLK_SRC_DMC_OFFSET 0x10200 +#define CLK_DIV_DMC0_OFFSET 0x10500 +#define CLK_DIV_DMC1_OFFSET 0x10504 + +#define APLL_LOCK_OFFSET 0x14000 +#define MPLL_LOCK_OFFSET 0x14008 +#define APLL_CON0_OFFSET 0x14100 +#define APLL_CON1_OFFSET 0x14104 +#ifdef CONFIG_SMDKC220 +#define MPLL_CON0_OFFSET 0x10108 +#define MPLL_CON1_OFFSET 0x1010C +#else +#define MPLL_CON0_OFFSET 0x14108 +#define MPLL_CON1_OFFSET 0x1410C +#endif + +#define CLK_SRC_CPU_OFFSET 0x14200 +#define CLK_DIV_CPU0_OFFSET 0x14500 +#define CLK_DIV_CPU1_OFFSET 0x14504 + +#define CLK_SRC_FSYS __REG(ELFIN_CLOCK_BASE+CLK_SRC_FSYS_OFFSET) +#define CLK_DIV_FSYS1 __REG(ELFIN_CLOCK_BASE+CLK_DIV_FSYS1_OFFSET) +#define CLK_DIV_FSYS2 __REG(ELFIN_CLOCK_BASE+CLK_DIV_FSYS2_OFFSET) +#define CLK_DIV_FSYS3 __REG(ELFIN_CLOCK_BASE+CLK_DIV_FSYS3_OFFSET) +#define APLL_CON0_REG __REG(ELFIN_CLOCK_BASE+APLL_CON0_OFFSET) +#define MPLL_CON0_REG __REG(ELFIN_CLOCK_BASE+MPLL_CON0_OFFSET) +#define EPLL_CON0_REG __REG(ELFIN_CLOCK_BASE+EPLL_CON0_OFFSET) +#define VPLL_CON0_REG __REG(ELFIN_CLOCK_BASE+VPLL_CON0_OFFSET) + +#define USB_PHY_CONTROL_OFFSET 0x0704 +#define USB_PHY_CONTROL (0x10020000+USB_PHY_CONTROL_OFFSET)//(ELFIN_CLOCK_POWER_BASE+USB_PHY_CONTROL_OFFSET) + +/* + * TZPC + */ +#define ELFIN_TZPC0_BASE 0x10110000 +#define ELFIN_TZPC1_BASE 0x10120000 +#define ELFIN_TZPC2_BASE 0x10130000 +#define ELFIN_TZPC3_BASE 0x10140000 +#define ELFIN_TZPC4_BASE 0x10150000 +#define ELFIN_TZPC5_BASE 0x10160000 + +#define TZPC_DECPROT0SET_OFFSET 0x804 +#define TZPC_DECPROT1SET_OFFSET 0x810 +#define TZPC_DECPROT2SET_OFFSET 0x81C +#define TZPC_DECPROT3SET_OFFSET 0x828 + +/* + * Memory controller + */ +#define ELFIN_SROM_BASE 0x12570000 + +#define SROM_BW_REG __REG(ELFIN_SROM_BASE+0x0) +#define SROM_BC0_REG __REG(ELFIN_SROM_BASE+0x4) +#define SROM_BC1_REG __REG(ELFIN_SROM_BASE+0x8) +#define SROM_BC2_REG __REG(ELFIN_SROM_BASE+0xC) +#define SROM_BC3_REG __REG(ELFIN_SROM_BASE+0x10) +#define SROM_BC4_REG __REG(ELFIN_SROM_BASE+0x14) +#define SROM_BC5_REG __REG(ELFIN_SROM_BASE+0x18) + +/* + * SDRAM Controller + */ +#ifdef CONFIG_SMDKC220 +#define APB_DMC_0_BASE 0x10600000 +#define APB_DMC_1_BASE 0x10610000 +#else +#define APB_DMC_0_BASE 0x10400000 +#define APB_DMC_1_BASE 0x10410000 +#endif + +#define DMC_CONCONTROL 0x00 +#define DMC_MEMCONTROL 0x04 +#define DMC_MEMCONFIG0 0x08 +#define DMC_MEMCONFIG1 0x0C +#define DMC_DIRECTCMD 0x10 +#define DMC_PRECHCONFIG 0x14 +#define DMC_PHYCONTROL0 0x18 +#define DMC_PHYCONTROL1 0x1C +#define DMC_PHYCONTROL2 0x20 +#define DMC_PWRDNCONFIG 0x28 +#define DMC_TIMINGAREF 0x30 +#define DMC_TIMINGROW 0x34 +#define DMC_TIMINGDATA 0x38 +#define DMC_TIMINGPOWER 0x3C +#define DMC_PHYSTATUS 0x40 +#define DMC_PHYZQCONTROL 0x44 +#define DMC_CHIP0STATUS 0x48 +#define DMC_CHIP1STATUS 0x4C +#define DMC_AREFSTATUS 0x50 +#define DMC_MRSTATUS 0x54 +#define DMC_PHYTEST0 0x58 +#define DMC_PHYTEST1 0x5C +#define DMC_QOSCONTROL0 0x60 +#define DMC_QOSCONFIG0 0x64 +#define DMC_QOSCONTROL1 0x68 +#define DMC_QOSCONFIG1 0x6C +#define DMC_QOSCONTROL2 0x70 +#define DMC_QOSCONFIG2 0x74 +#define DMC_QOSCONTROL3 0x78 +#define DMC_QOSCONFIG3 0x7C +#define DMC_QOSCONTROL4 0x80 +#define DMC_QOSCONFIG4 0x84 +#define DMC_QOSCONTROL5 0x88 +#define DMC_QOSCONFIG5 0x8C +#define DMC_QOSCONTROL6 0x90 +#define DMC_QOSCONFIG6 0x94 +#define DMC_QOSCONTROL7 0x98 +#define DMC_QOSCONFIG7 0x9C +#define DMC_QOSCONTROL8 0xA0 +#define DMC_QOSCONFIG8 0xA4 +#define DMC_QOSCONTROL9 0xA8 +#define DMC_QOSCONFIG9 0xAC +#define DMC_QOSCONTROL10 0xB0 +#define DMC_QOSCONFIG10 0xB4 +#define DMC_QOSCONTROL11 0xB8 +#define DMC_QOSCONFIG11 0xBC +#define DMC_QOSCONTROL12 0xC0 +#define DMC_QOSCONFIG12 0xC4 +#define DMC_QOSCONTROL13 0xC8 +#define DMC_QOSCONFIG13 0xCC +#define DMC_QOSCONTROL14 0xD0 +#define DMC_QOSCONFIG14 0xD4 +#define DMC_QOSCONTROL15 0xD8 +#define DMC_QOSCONFIG15 0xDC +#ifdef CONFIG_SMDKC220 +#define DMC_IVCONTROL 0xF0 +#endif + +/* + * MIU + */ +#define MIU_BASE 0x10600000 +#define MIU_INTLV_CONFIG 0x400 +#define MIU_INTLV_START_ADDR 0x808 +#define MIU_MAPPING_UPDATE 0x800 +#define MIU_INTLV_END_ADDR 0x810 + +#define MIU_SINGLE_MAPPING0_START_ADDR 0x818 +#define MIU_SINGLE_MAPPING0_END_ADDR 0x820 +#define MIU_SINGLE_MAPPING1_START_ADDR 0x828 +#define MIU_SINGLE_MAPPING1_END_ADDR 0x830 + +/* + * UART + */ + +#define S5PV310_UART0_OFFSET 0x00000 +#define S5PV310_UART1_OFFSET 0x10000 +#define S5PV310_UART2_OFFSET 0x20000 +#define S5PV310_UART3_OFFSET 0x30000 + +#if defined(CONFIG_SERIAL0) +#define S5PV310_UART_CONSOLE_BASE (S5PV310_UART_BASE + S5PV310_UART0_OFFSET) +#elif defined(CONFIG_SERIAL1) +#define S5PV310_UART_CONSOLE_BASE (S5PV310_UART_BASE + S5PV310_UART1_OFFSET) +#elif defined(CONFIG_SERIAL2) +#define S5PV310_UART_CONSOLE_BASE (S5PV310_UART_BASE + S5PV310_UART2_OFFSET) +#elif defined(CONFIG_SERIAL3) +#define S5PV310_UART_CONSOLE_BASE (S5PV310_UART_BASE + S5PV310_UART3_OFFSET) +#else +#define S5PV310_UART_CONSOLE_BASE (S5PV310_UART_BASE + S5PV310_UART0_OFFSET) +#endif + +#define ULCON_OFFSET 0x00 +#define UCON_OFFSET 0x04 +#define UFCON_OFFSET 0x08 +#define UMCON_OFFSET 0x0C +#define UTRSTAT_OFFSET 0x10 +#define UERSTAT_OFFSET 0x14 +#define UFSTAT_OFFSET 0x18 +#define UMSTAT_OFFSET 0x1C +#define UTXH_OFFSET 0x20 +#define URXH_OFFSET 0x24 +#define UBRDIV_OFFSET 0x28 +#define UDIVSLOT_OFFSET 0x2C +#define UINTP_OFFSET 0x30 +#define UINTSP_OFFSET 0x34 +#define UINTM_OFFSET 0x38 +//#define UTRSTAT_TX_EMPTY BIT2 +//#define UTRSTAT_RX_READY BIT0 +#define UART_ERR_MASK 0xF + +/* + * HS MMC + */ +#define ELFIN_HSMMC_0_BASE 0x12510000 +#define ELFIN_HSMMC_1_BASE 0x12520000 +#define ELFIN_HSMMC_2_BASE 0x12530000 +#define ELFIN_HSMMC_3_BASE 0x12540000 +#define ELFIN_HSMMC_4_BASE 0x12550000 + +#define HM_SYSAD (0x00) +#define HM_BLKSIZE (0x04) +#define HM_BLKCNT (0x06) +#define HM_ARGUMENT (0x08) +#define HM_TRNMOD (0x0c) +#define HM_CMDREG (0x0e) +#define HM_RSPREG0 (0x10) +#define HM_RSPREG1 (0x14) +#define HM_RSPREG2 (0x18) +#define HM_RSPREG3 (0x1c) +#define HM_BDATA (0x20) +#define HM_PRNSTS (0x24) +#define HM_HOSTCTL (0x28) +#define HM_PWRCON (0x29) +#define HM_BLKGAP (0x2a) +#define HM_WAKCON (0x2b) +#define HM_CLKCON (0x2c) +#define HM_TIMEOUTCON (0x2e) +#define HM_SWRST (0x2f) +#define HM_NORINTSTS (0x30) +#define HM_ERRINTSTS (0x32) +#define HM_NORINTSTSEN (0x34) +#define HM_ERRINTSTSEN (0x36) +#define HM_NORINTSIGEN (0x38) +#define HM_ERRINTSIGEN (0x3a) +#define HM_ACMD12ERRSTS (0x3c) +#define HM_CAPAREG (0x40) +#define HM_MAXCURR (0x48) +#define HM_CONTROL2 (0x80) +#define HM_CONTROL3 (0x84) +#define HM_CONTROL4 (0x8c) +#define HM_HCVER (0xfe) + +/* USBD 2.0 SFR */ +#define USBOTG_LINK_BASE (0x12480000) //(0xEC000000) +#define USBOTG_PHY_BASE (0x125B0000) //(0xEC100000) + +/* PENDING BIT */ +#define BIT_EINT0 (0x1) +#define BIT_EINT1 (0x1<<1) +#define BIT_EINT2 (0x1<<2) +#define BIT_EINT3 (0x1<<3) +#define BIT_EINT4_7 (0x1<<4) +#define BIT_EINT8_23 (0x1<<5) +#define BIT_BAT_FLT (0x1<<7) +#define BIT_TICK (0x1<<8) +#define BIT_WDT (0x1<<9) +#define BIT_TIMER0 (0x1<<10) +#define BIT_TIMER1 (0x1<<11) +#define BIT_TIMER2 (0x1<<12) +#define BIT_TIMER3 (0x1<<13) +#define BIT_TIMER4 (0x1<<14) +#define BIT_UART2 (0x1<<15) +#define BIT_LCD (0x1<<16) +#define BIT_DMA0 (0x1<<17) +#define BIT_DMA1 (0x1<<18) +#define BIT_DMA2 (0x1<<19) +#define BIT_DMA3 (0x1<<20) +#define BIT_SDI (0x1<<21) +#define BIT_SPI0 (0x1<<22) +#define BIT_UART1 (0x1<<23) +#define BIT_USBH (0x1<<26) +#define BIT_IIC (0x1<<27) +#define BIT_UART0 (0x1<<28) +#define BIT_SPI1 (0x1<<29) +#define BIT_RTC (0x1<<30) +#define BIT_ADC (0x1<<31) +#define BIT_ALLMSK (0xFFFFFFFF) + +#ifndef __ASSEMBLY__ +#include <asm/io.h> +/* CPU detection macros */ +//extern unsigned int s5p_cpu_id; + +//static inline void s5p_set_cpu_id(void) +//{ +// s5p_cpu_id = readl(S5PC100_PRO_ID); +// s5p_cpu_id = 0xC000 | ((s5p_cpu_id & 0x00FFF000) >> 12); +//} + +//#define IS_SAMSUNG_TYPE(type, id) \ +//static inline int cpu_is_##type(void) \ +//{ \ +// return s5p_cpu_id == id ? 1 : 0; \ +//} + +//IS_SAMSUNG_TYPE(s5pc100, 0xc100) +//IS_SAMSUNG_TYPE(s5pc110, 0xc110) + +/*#define SAMSUNG_BASE(device, base) \ +static inline unsigned int samsung_get_base_##device(void) \ +{ \ + return S5PV310_##base; \ +} +*/ +//SAMSUNG_BASE(clock, CLOCK_BASE) +//SAMSUNG_BASE(gpio, GPIO_BASE) +//SAMSUNG_BASE(pro_id, PRO_ID) +//SAMSUNG_BASE(mmc, MMC_BASE) +//SAMSUNG_BASE(sromc, SROMC_BASE) +//SAMSUNG_BASE(timer, PWMTIMER_BASE) +//SAMSUNG_BASE(uart, UART_CONSOLE_BASE) +#endif +#endif /* !CONFIG_EXYNOS5210 */ +/* + * USB2.0 HS OTG (Chapter 26) + */ + +#define S5P_OTG_PHYPWR (USBOTG_PHY_BASE + 0x000) /* R/W OTG PHY Power Control Register */ +#define S5P_OTG_PHYCLK (USBOTG_PHY_BASE + 0x004) /* R/W OTG PHY Clock Control Register */ +#define S5P_OTG_RSTCON (USBOTG_PHY_BASE + 0x008) /* R/W OTG Reset Control Register */ +#define S5P_OTG_PHYTUNE0 (USBOTG_PHY_BASE + 0x020) /* R/W OTG PHY0 Tuning Register */ +#define S5P_OTG_PHYTUNE1 (USBOTG_PHY_BASE + 0x024) /* R/W OTG PHY1 Tuning Register */ + +/* Core Global Register */ +#define S5P_OTG_GOTGCTL (USBOTG_LINK_BASE + 0x000) /* R/W OTG Control and Status Register */ +#define S5P_OTG_GOTGINT (USBOTG_LINK_BASE + 0x004) /* R/W OTG Interrupt Register */ +#define S5P_OTG_GAHBCFG (USBOTG_LINK_BASE + 0x008) /* R/W Core AHB Configuration Register */ +#define S5P_OTG_GUSBCFG (USBOTG_LINK_BASE + 0x00C) /* R/W Core USB Configuration Register */ +#define S5P_OTG_GRSTCTL (USBOTG_LINK_BASE + 0x010) /* R/W Core Reset Register */ +#define S5P_OTG_GINTSTS (USBOTG_LINK_BASE + 0x014) /* R/W Core Interrupt Register */ +#define S5P_OTG_GINTMSK (USBOTG_LINK_BASE + 0x018) /* R/W Core Interrupt Mask Register */ +#define S5P_OTG_GRXSTSR (USBOTG_LINK_BASE + 0x01C) /* R Receive Status Debug Read Register */ +#define S5P_OTG_GRXSTSP (USBOTG_LINK_BASE + 0x020) /* R Receive Status Read/Pop Register */ +#define S5P_OTG_GRXFSIZ (USBOTG_LINK_BASE + 0x024) /* R/W Receive FIFO Size Register */ +#define S5P_OTG_GNPTXFSIZ (USBOTG_LINK_BASE + 0x028) /* R/W Non-Periodic Transmit FIFO Size Register */ +#define S5P_OTG_GNPTXSTS (USBOTG_LINK_BASE + 0x02C) /* R Non-Periodic Transmit FIFO/Queue Status Register */ +#define S5P_OTG_HPTXFSIZ (USBOTG_LINK_BASE + 0x100) /* R/W Host Periodic Transmit FIFO Size Register */ +#define S5P_OTG_DPTXFSIZ1 (USBOTG_LINK_BASE + 0x104) /* R/W Device Periodic Transmit FIFO-1 Size Register */ +#define S5P_OTG_DPTXFSIZ2 (USBOTG_LINK_BASE + 0x108) /* R/W Device Periodic Transmit FIFO-2 Size Register */ +#define S5P_OTG_DPTXFSIZ3 (USBOTG_LINK_BASE + 0x10C) /* R/W Device Periodic Transmit FIFO-3 Size Register */ +#define S5P_OTG_DPTXFSIZ4 (USBOTG_LINK_BASE + 0x110) /* R/W Device Periodic Transmit FIFO-4 Size Register */ +#define S5P_OTG_DPTXFSIZ5 (USBOTG_LINK_BASE + 0x114) /* R/W Device Periodic Transmit FIFO-5 Size Register */ +#define S5P_OTG_DPTXFSIZ6 (USBOTG_LINK_BASE + 0x118) /* R/W Device Periodic Transmit FIFO-6 Size Register */ +#define S5P_OTG_DPTXFSIZ7 (USBOTG_LINK_BASE + 0x11C) /* R/W Device Periodic Transmit FIFO-7 Size Register */ +#define S5P_OTG_DPTXFSIZ8 (USBOTG_LINK_BASE + 0x120) /* R/W Device Periodic Transmit FIFO-8 Size Register */ +#define S5P_OTG_DPTXFSIZ9 (USBOTG_LINK_BASE + 0x124) /* R/W Device Periodic Transmit FIFO-9 Size Register */ +#define S5P_OTG_DPTXFSIZ10 (USBOTG_LINK_BASE + 0x128) /* R/W Device Periodic Transmit FIFO-10 Size Register */ +#define S5P_OTG_DPTXFSIZ11 (USBOTG_LINK_BASE + 0x12C) /* R/W Device Periodic Transmit FIFO-11 Size Register */ +#define S5P_OTG_DPTXFSIZ12 (USBOTG_LINK_BASE + 0x130) /* R/W Device Periodic Transmit FIFO-12 Size Register */ +#define S5P_OTG_DPTXFSIZ13 (USBOTG_LINK_BASE + 0x134) /* R/W Device Periodic Transmit FIFO-13 Size Register */ +#define S5P_OTG_DPTXFSIZ14 (USBOTG_LINK_BASE + 0x138) /* R/W Device Periodic Transmit FIFO-14 Size Register */ +#define S5P_OTG_DPTXFSIZ15 (USBOTG_LINK_BASE + 0x13C) /* R/W Device Periodic Transmit FIFO-15 Size Register */ + +/* Host Mode Register */ +/* Host Global Register */ +#define S5P_OTG_HCFG (USBOTG_LINK_BASE + 0x400) /* R/W Host Configuration Register */ +#define S5P_OTG_HFIR (USBOTG_LINK_BASE + 0x404) /* R/W Host Frame Interval Register */ +#define S5P_OTG_HFNUM (USBOTG_LINK_BASE + 0x408) /* R Host Frame Number/Frame Time Remaining Register */ + +#define S5P_OTG_HPTXSTS (USBOTG_LINK_BASE + 0x410) /* R Host Periodic Transmit FIFO/Queue Status Register */ +#define S5P_OTG_HAINT (USBOTG_LINK_BASE + 0x414) /* R Host All Channels Interrupt Register */ +#define S5P_OTG_HAINTMSK (USBOTG_LINK_BASE + 0x418) /* R/W Host All Channels Interrupt Mask Register */ + +/*Host Port Control and Status Register */ +#define S5P_OTG_HPRT (USBOTG_LINK_BASE + 0x440) /* R/W Host Port Control and Status Register */ + +/*Host Channel-Specific Register */ +#define S5P_OTG_HCCHAR0 (USBOTG_LINK_BASE + 0x500) /* R/W Host Channel 0 Characteristics Register */ +#define S5P_OTG_HCSPLT0 (USBOTG_LINK_BASE + 0x504) /* R/W Host Channel 0 Spilt Control Register */ +#define S5P_OTG_HCINT0 (USBOTG_LINK_BASE + 0x508) /* R/W Host Channel 0 Interrupt Register */ +#define S5P_OTG_HCINTMSK0 (USBOTG_LINK_BASE + 0x50C) /* R/W Host Channel 0 Interrupt Mask Register */ +#define S5P_OTG_HCTSIZ0 (USBOTG_LINK_BASE + 0x510) /* R/W Host Channel 0 Transfer Size Register */ +#define S5P_OTG_HCDMA0 (USBOTG_LINK_BASE + 0x514) /* R/W Host Channel 0 DMA Address Register */ +#define S5P_OTG_HCCHAR1 (USBOTG_LINK_BASE + 0x520) /* R/W Host Channel 1 Characteristics Register */ +#define S5P_OTG_HCSPLT1 (USBOTG_LINK_BASE + 0x524) /* R/W Host Channel 1 Spilt Control Register */ +#define S5P_OTG_HCINT1 (USBOTG_LINK_BASE + 0x528) /* R/W Host Channel 1 Interrupt Register */ +#define S5P_OTG_HCINTMSK1 (USBOTG_LINK_BASE + 0x52C) /* R/W Host Channel 1 Interrupt Mask Register */ +#define S5P_OTG_HCTSIZ1 (USBOTG_LINK_BASE + 0x530) /* R/W Host Channel 1 Transfer Size Register */ +#define S5P_OTG_HCDMA1 (USBOTG_LINK_BASE + 0x534) /* R/W Host Channel 1 DMA Address Register */ +#define S5P_OTG_HCCHAR2 (USBOTG_LINK_BASE + 0x540) /* R/W Host Channel 2 Characteristics Register */ +#define S5P_OTG_HCSPLT2 (USBOTG_LINK_BASE + 0x544) /* R/W Host Channel 2 Spilt Control Register */ +#define S5P_OTG_HCINT2 (USBOTG_LINK_BASE + 0x548) /* R/W Host Channel 2 Interrupt Register */ +#define S5P_OTG_HCINTMSK2 (USBOTG_LINK_BASE + 0x54C) /* R/W Host Channel 2 Interrupt Mask Register */ +#define S5P_OTG_HCTSIZ2 (USBOTG_LINK_BASE + 0x550) /* R/W Host Channel 2 Transfer Size Register */ +#define S5P_OTG_HCDMA2 (USBOTG_LINK_BASE + 0x554) /* R/W Host Channel 2 DMA Address Register */ +#define S5P_OTG_HCCHAR3 (USBOTG_LINK_BASE + 0x560) /* R/W Host Channel 3 Characteristics Register */ +#define S5P_OTG_HCSPLT3 (USBOTG_LINK_BASE + 0x564) /* R/W Host Channel 3 Spilt Control Register */ +#define S5P_OTG_HCINT3 (USBOTG_LINK_BASE + 0x568) /* R/W Host Channel 3 Interrupt Register */ +#define S5P_OTG_HCINTMSK3 (USBOTG_LINK_BASE + 0x56C) /* R/W Host Channel 3 Interrupt Mask Register */ +#define S5P_OTG_HCTSIZ3 (USBOTG_LINK_BASE + 0x570) /* R/W Host Channel 3 Transfer Size Register */ +#define S5P_OTG_HCDMA3 (USBOTG_LINK_BASE + 0x574) /* R/W Host Channel 3 DMA Address Register */ +#define S5P_OTG_HCCHAR4 (USBOTG_LINK_BASE + 0x580) /* R/W Host Channel 4 Characteristics Register */ +#define S5P_OTG_HCSPLT4 (USBOTG_LINK_BASE + 0x584) /* R/W Host Channel 4 Spilt Control Register */ +#define S5P_OTG_HCINT4 (USBOTG_LINK_BASE + 0x588) /* R/W Host Channel 4 Interrupt Register */ +#define S5P_OTG_HCINTMSK4 (USBOTG_LINK_BASE + 0x58C) /* R/W Host Channel 4 Interrupt Mask Register */ +#define S5P_OTG_HCTSIZ4 (USBOTG_LINK_BASE + 0x580) /* R/W Host Channel 4 Transfer Size Register */ +#define S5P_OTG_HCDMA4 (USBOTG_LINK_BASE + 0x584) /* R/W Host Channel 4 DMA Address Register */ +#define S5P_OTG_HCCHAR5 (USBOTG_LINK_BASE + 0x5A0) /* R/W Host Channel 5 Characteristics Register */ +#define S5P_OTG_HCSPLT5 (USBOTG_LINK_BASE + 0x5A4) /* R/W Host Channel 5 Spilt Control Register */ +#define S5P_OTG_HCINT5 (USBOTG_LINK_BASE + 0x5A8) /* R/W Host Channel 5 Interrupt Register */ +#define S5P_OTG_HCINTMSK5 (USBOTG_LINK_BASE + 0x5AC) /* R/W Host Channel 5 Interrupt Mask Register */ +#define S5P_OTG_HCTSIZ5 (USBOTG_LINK_BASE + 0x5B0) /* R/W Host Channel 5 Transfer Size Register */ +#define S5P_OTG_HCDMA5 (USBOTG_LINK_BASE + 0x5B4) /* R/W Host Channel 5 DMA Address Register */ +#define S5P_OTG_HCCHAR6 (USBOTG_LINK_BASE + 0x5C0) /* R/W Host Channel 6 Characteristics Register */ +#define S5P_OTG_HCSPLT6 (USBOTG_LINK_BASE + 0x5C4) /* R/W Host Channel 6 Spilt Control Register */ +#define S5P_OTG_HCINT6 (USBOTG_LINK_BASE + 0x5C8) /* R/W Host Channel 6 Interrupt Register */ +#define S5P_OTG_HCINTMSK6 (USBOTG_LINK_BASE + 0x5CC) /* R/W Host Channel 6 Interrupt Mask Register */ +#define S5P_OTG_HCTSIZ6 (USBOTG_LINK_BASE + 0x5D0) /* R/W Host Channel 6 Transfer Size Register */ +#define S5P_OTG_HCDMA6 (USBOTG_LINK_BASE + 0x5D4) /* R/W Host Channel 6 DMA Address Register */ +#define S5P_OTG_HCCHAR7 (USBOTG_LINK_BASE + 0x5E0) /* R/W Host Channel 7 Characteristics Register */ +#define S5P_OTG_HCSPLT7 (USBOTG_LINK_BASE + 0x5E4) /* R/W Host Channel 7 Spilt Control Register */ +#define S5P_OTG_HCINT7 (USBOTG_LINK_BASE + 0x5E8) /* R/W Host Channel 7 Interrupt Register */ +#define S5P_OTG_HCINTMSK7 (USBOTG_LINK_BASE + 0x5EC) /* R/W Host Channel 7 Interrupt Mask Register */ +#define S5P_OTG_HCTSIZ7 (USBOTG_LINK_BASE + 0x5F0) /* R/W Host Channel 7 Transfer Size Register */ +#define S5P_OTG_HCDMA7 (USBOTG_LINK_BASE + 0x5F4) /* R/W Host Channel 7 DMA Address Register */ +#define S5P_OTG_HCCHAR8 (USBOTG_LINK_BASE + 0x600) /* R/W Host Channel 8 Characteristics Register */ +#define S5P_OTG_HCSPLT8 (USBOTG_LINK_BASE + 0x604) /* R/W Host Channel 8 Spilt Control Register */ +#define S5P_OTG_HCINT8 (USBOTG_LINK_BASE + 0x608) /* R/W Host Channel 8 Interrupt Register */ +#define S5P_OTG_HCINTMSK8 (USBOTG_LINK_BASE + 0x60C) /* R/W Host Channel 8 Interrupt Mask Register */ +#define S5P_OTG_HCTSIZ8 (USBOTG_LINK_BASE + 0x610) /* R/W Host Channel 8 Transfer Size Register */ +#define S5P_OTG_HCDMA8 (USBOTG_LINK_BASE + 0x614) /* R/W Host Channel 8 DMA Address Register */ +#define S5P_OTG_HCCHAR9 (USBOTG_LINK_BASE + 0x620) /* R/W Host Channel 9 Characteristics Register */ +#define S5P_OTG_HCSPLT9 (USBOTG_LINK_BASE + 0x624) /* R/W Host Channel 9 Spilt Control Register */ +#define S5P_OTG_HCINT9 (USBOTG_LINK_BASE + 0x628) /* R/W Host Channel 9 Interrupt Register */ +#define S5P_OTG_HCINTMSK9 (USBOTG_LINK_BASE + 0x62C) /* R/W Host Channel 9 Interrupt Mask Register */ +#define S5P_OTG_HCTSIZ9 (USBOTG_LINK_BASE + 0x630) /* R/W Host Channel 9 Transfer Size Register */ +#define S5P_OTG_HCDMA9 (USBOTG_LINK_BASE + 0x634) /* R/W Host Channel 9 DMA Address Register */ +#define S5P_OTG_HCCHAR10 (USBOTG_LINK_BASE + 0x640) /* R/W Host Channel 10 Characteristics Register */ +#define S5P_OTG_HCSPLT10 (USBOTG_LINK_BASE + 0x644) /* R/W Host Channel 10 Spilt Control Register */ +#define S5P_OTG_HCINT10 (USBOTG_LINK_BASE + 0x648) /* R/W Host Channel 10 Interrupt Register */ +#define S5P_OTG_HCINTMSK10 (USBOTG_LINK_BASE + 0x64C) /* R/W Host Channel 10 Interrupt Mask Register */ +#define S5P_OTG_HCTSIZ10 (USBOTG_LINK_BASE + 0x650) /* R/W Host Channel 10 Transfer Size Register */ +#define S5P_OTG_HCDMA10 (USBOTG_LINK_BASE + 0x654) /* R/W Host Channel 10 DMA Address Register */ +#define S5P_OTG_HCCHAR11 (USBOTG_LINK_BASE + 0x660) /* R/W Host Channel 11 Characteristics Register */ +#define S5P_OTG_HCSPLT11 (USBOTG_LINK_BASE + 0x664) /* R/W Host Channel 11 Spilt Control Register */ +#define S5P_OTG_HCINT11 (USBOTG_LINK_BASE + 0x668) /* R/W Host Channel 11 Interrupt Register */ +#define S5P_OTG_HCINTMSK11 (USBOTG_LINK_BASE + 0x66C) /* R/W Host Channel 11 Interrupt Mask Register */ +#define S5P_OTG_HCTSIZ11 (USBOTG_LINK_BASE + 0x670) /* R/W Host Channel 11 Transfer Size Register */ +#define S5P_OTG_HCDMA11 (USBOTG_LINK_BASE + 0x674) /* R/W Host Channel 11 DMA Address Register */ +#define S5P_OTG_HCCHAR12 (USBOTG_LINK_BASE + 0x680) /* R/W Host Channel 12 Characteristics Register */ +#define S5P_OTG_HCSPLT12 (USBOTG_LINK_BASE + 0x684) /* R/W Host Channel 12 Spilt Control Register */ +#define S5P_OTG_HCINT12 (USBOTG_LINK_BASE + 0x688) /* R/W Host Channel 12 Interrupt Register */ +#define S5P_OTG_HCINTMSK12 (USBOTG_LINK_BASE + 0x68C) /* R/W Host Channel 12 Interrupt Mask Register */ +#define S5P_OTG_HCTSIZ12 (USBOTG_LINK_BASE + 0x690) /* R/W Host Channel 12 Transfer Size Register */ +#define S5P_OTG_HCDMA12 (USBOTG_LINK_BASE + 0x694) /* R/W Host Channel 12 DMA Address Register */ +#define S5P_OTG_HCCHAR13 (USBOTG_LINK_BASE + 0x6A0) /* R/W Host Channel 13 Characteristics Register */ +#define S5P_OTG_HCSPLT13 (USBOTG_LINK_BASE + 0x6A4) /* R/W Host Channel 13 Spilt Control Register */ +#define S5P_OTG_HCINT13 (USBOTG_LINK_BASE + 0x6A8) /* R/W Host Channel 13 Interrupt Register */ +#define S5P_OTG_HCINTMSK13 (USBOTG_LINK_BASE + 0x6AC) /* R/W Host Channel 13 Interrupt Mask Register */ +#define S5P_OTG_HCTSIZ13 (USBOTG_LINK_BASE + 0x6B0) /* R/W Host Channel 13 Transfer Size Register */ +#define S5P_OTG_HCDMA13 (USBOTG_LINK_BASE + 0x6B4) /* R/W Host Channel 13 DMA Address Register */ +#define S5P_OTG_HCCHAR14 (USBOTG_LINK_BASE + 0x6C0) /* R/W Host Channel 14 Characteristics Register */ +#define S5P_OTG_HCSPLT14 (USBOTG_LINK_BASE + 0x6C4) /* R/W Host Channel 14 Spilt Control Register */ +#define S5P_OTG_HCINT14 (USBOTG_LINK_BASE + 0x6C8) /* R/W Host Channel 14 Interrupt Register */ +#define S5P_OTG_HCINTMSK14 (USBOTG_LINK_BASE + 0x6CC) /* R/W Host Channel 14 Interrupt Mask Register */ +#define S5P_OTG_HCTSIZ14 (USBOTG_LINK_BASE + 0x6D0) /* R/W Host Channel 14 Transfer Size Register */ +#define S5P_OTG_HCDMA14 (USBOTG_LINK_BASE + 0x6D4) /* R/W Host Channel 14 DMA Address Register */ +#define S5P_OTG_HCCHAR15 (USBOTG_LINK_BASE + 0x6E0) /* R/W Host Channel 15 Characteristics Register */ +#define S5P_OTG_HCSPLT15 (USBOTG_LINK_BASE + 0x6E4) /* R/W Host Channel 15 Spilt Control Register */ +#define S5P_OTG_HCINT15 (USBOTG_LINK_BASE + 0x6E8) /* R/W Host Channel 15 Interrupt Register */ +#define S5P_OTG_HCINTMSK15 (USBOTG_LINK_BASE + 0x6EC) /* R/W Host Channel 15 Interrupt Mask Register */ +#define S5P_OTG_HCTSIZ15 (USBOTG_LINK_BASE + 0x6F0) /* R/W Host Channel 15 Transfer Size Register */ +#define S5P_OTG_HCDMA15 (USBOTG_LINK_BASE + 0x6F4) /* R/W Host Channel 15 DMA Address Register */ + +/* Device Global Register */ +#define S5P_OTG_DCFG (USBOTG_LINK_BASE + 0x800) /* R/W Device Configuration Register */ +#define S5P_OTG_DCTL (USBOTG_LINK_BASE + 0x804) /* R/W Device Control Register */ +#define S5P_OTG_DSTS (USBOTG_LINK_BASE + 0x808) /* R Device Status Register */ +#define S5P_OTG_DIEPMSK (USBOTG_LINK_BASE + 0x810) /* R/W Device IN Endpoint Common Interrupt Mask Register */ +#define S5P_OTG_DOEPMSK (USBOTG_LINK_BASE + 0x814) /* R/W Device OUT Endpoint Common Interrupt Mask Register */ +#define S5P_OTG_DAINT (USBOTG_LINK_BASE + 0x818) /* R Device ALL Endpoints Interrupt Register */ +#define S5P_OTG_DAINTMSK (USBOTG_LINK_BASE + 0x81C) /* R/W Device ALL Endpoints Interrupt Mask Register */ +#define S5P_OTG_DTKNQR1 (USBOTG_LINK_BASE + 0x820) /* R Device IN Token Sequence Learning Queue Read Register */ +#define S5P_OTG_DTKNQR2 (USBOTG_LINK_BASE + 0x824) /* R Device IN Token Sequence Learning Queue Read Register */ +#define S5P_OTG_DVBUSDIS (USBOTG_LINK_BASE + 0x828) /* R/W Device VBUS Discharge Time Register */ +#define S5P_OTG_DVBUSPULSE (USBOTG_LINK_BASE + 0x82C) /* R/W Device VBUS Pulsing Time Register */ +#define S5P_OTG_DTKNQR3 (USBOTG_LINK_BASE + 0x830) /* R Device IN Token Sequence Learning Queue Read Register */ +#define S5P_OTG_DTKNQR4 (USBOTG_LINK_BASE + 0x834) /* R Device IN Token Sequence Learning Queue Read Register */ + +/* Device Logical IN Endpo int-Specific Registers */ +#define S5P_OTG_DIEPCTL0 (USBOTG_LINK_BASE + 0x900) /* R/W Device Control IN Endpoint 0 Control Register */ +#define S5P_OTG_DIEPINT0 (USBOTG_LINK_BASE + 0x908) /* R/W Device IN Endpoint 0 Interrupt Register */ +#define S5P_OTG_DIEPTSIZ0 (USBOTG_LINK_BASE + 0x910) /* R/W Device IN Endpoint 0 Transfer Size Register */ +#define S5P_OTG_DIEPDMA0 (USBOTG_LINK_BASE + 0x914) /* R/W Device IN Endpoint 0 DMA Address Register */ +#define S5P_OTG_DIEPCTL1 (USBOTG_LINK_BASE + 0x920) /* R/W Device Control IN Endpoint 1 Control Register */ +#define S5P_OTG_DIEPINT1 (USBOTG_LINK_BASE + 0x928) /* R/W Device IN Endpoint 1 Interrupt Register */ +#define S5P_OTG_DIEPTSIZ1 (USBOTG_LINK_BASE + 0x930) /* R/W Device IN Endpoint 1 Transfer Size Register */ +#define S5P_OTG_DIEPDMA1 (USBOTG_LINK_BASE + 0x934) /* R/W Device IN Endpoint 1 DMA Address Register */ +#define S5P_OTG_DIEPCTL2 (USBOTG_LINK_BASE + 0x940) /* R/W Device Control IN Endpoint 2 Control Register */ +#define S5P_OTG_DIEPINT2 (USBOTG_LINK_BASE + 0x948) /* R/W Device IN Endpoint 2 Interrupt Register */ +#define S5P_OTG_DIEPTSIZ2 (USBOTG_LINK_BASE + 0x950) /* R/W Device IN Endpoint 2 Transfer Size Register */ +#define S5P_OTG_DIEPDMA2 (USBOTG_LINK_BASE + 0x954) /* R/W Device IN Endpoint 2 DMA Address Register */ +#define S5P_OTG_DIEPCTL3 (USBOTG_LINK_BASE + 0x960) /* R/W Device Control IN Endpoint 3 Control Register */ +#define S5P_OTG_DIEPINT3 (USBOTG_LINK_BASE + 0x968) /* R/W Device IN Endpoint 3 Interrupt Register */ +#define S5P_OTG_DIEPTSIZ3 (USBOTG_LINK_BASE + 0x970) /* R/W Device IN Endpoint 3 Transfer Size Register */ +#define S5P_OTG_DIEPDMA3 (USBOTG_LINK_BASE + 0x974) /* R/W Device IN Endpoint 3 DMA Address Register */ +#define S5P_OTG_DIEPCTL4 (USBOTG_LINK_BASE + 0x980) /* R/W Device Control IN Endpoint 0 Control Register */ +#define S5P_OTG_DIEPINT4 (USBOTG_LINK_BASE + 0x988) /* R/W Device IN Endpoint 4 Interrupt Register */ +#define S5P_OTG_DIEPTSIZ4 (USBOTG_LINK_BASE + 0x990) /* R/W Device IN Endpoint 4 Transfer Size Register */ +#define S5P_OTG_DIEPDMA4 (USBOTG_LINK_BASE + 0x994) /* R/W Device IN Endpoint 4 DMA Address Register */ +#define S5P_OTG_DIEPCTL5 (USBOTG_LINK_BASE + 0x9A0) /* R/W Device Control IN Endpoint 5 Control Register */ +#define S5P_OTG_DIEPINT5 (USBOTG_LINK_BASE + 0x9A8) /* R/W Device IN Endpoint 5 Interrupt Register */ +#define S5P_OTG_DIEPTSIZ5 (USBOTG_LINK_BASE + 0x9B0) /* R/W Device IN Endpoint 5 Transfer Size Register */ +#define S5P_OTG_DIEPDMA5 (USBOTG_LINK_BASE + 0x9B4) /* R/W Device IN Endpoint 5 DMA Address Register */ +#define S5P_OTG_DIEPCTL6 (USBOTG_LINK_BASE + 0x9C0) /* R/W Device Control IN Endpoint 6 Control Register */ +#define S5P_OTG_DIEPINT6 (USBOTG_LINK_BASE + 0x9C8) /* R/W Device IN Endpoint 6 Interrupt Register */ +#define S5P_OTG_DIEPTSIZ6 (USBOTG_LINK_BASE + 0x9D0) /* R/W Device IN Endpoint 6 Transfer Size Register */ +#define S5P_OTG_DIEPDMA6 (USBOTG_LINK_BASE + 0x9D4) /* R/W Device IN Endpoint 6 DMA Address Register */ +#define S5P_OTG_DIEPCTL7 (USBOTG_LINK_BASE + 0x9E0) /* R/W Device Control IN Endpoint 7 Control Register */ +#define S5P_OTG_DIEPINT7 (USBOTG_LINK_BASE + 0x9E8) /* R/W Device IN Endpoint 7 Interrupt Register */ +#define S5P_OTG_DIEPTSIZ7 (USBOTG_LINK_BASE + 0x9F0) /* R/W Device IN Endpoint 7 Transfer Size Register */ +#define S5P_OTG_DIEPDMA7 (USBOTG_LINK_BASE + 0x9F4) /* R/W Device IN Endpoint 7 DMA Address Register */ +#define S5P_OTG_DIEPCTL8 (USBOTG_LINK_BASE + 0xA00) /* R/W Device Control IN Endpoint 8 Control Register */ +#define S5P_OTG_DIEPINT8 (USBOTG_LINK_BASE + 0xA08) /* R/W Device IN Endpoint 8 Interrupt Register */ +#define S5P_OTG_DIEPTSIZ8 (USBOTG_LINK_BASE + 0xA10) /* R/W Device IN Endpoint 8 Transfer Size Register */ +#define S5P_OTG_DIEPDMA8 (USBOTG_LINK_BASE + 0xA14) /* R/W Device IN Endpoint 8 DMA Address Register */ +#define S5P_OTG_DIEPCTL9 (USBOTG_LINK_BASE + 0xA20) /* R/W Device Control IN Endpoint 9 Control Register */ +#define S5P_OTG_DIEPINT9 (USBOTG_LINK_BASE + 0xA28) /* R/W Device IN Endpoint 9 Interrupt Register */ +#define S5P_OTG_DIEPTSIZ9 (USBOTG_LINK_BASE + 0xA30) /* R/W Device IN Endpoint 9 Transfer Size Register */ +#define S5P_OTG_DIEPDMA9 (USBOTG_LINK_BASE + 0xA34) /* R/W Device IN Endpoint 9 DMA Address Register */ +#define S5P_OTG_DIEPCTL10 (USBOTG_LINK_BASE + 0xA40) /* R/W Device Control IN Endpoint 10 Control Register */ +#define S5P_OTG_DIEPINT10 (USBOTG_LINK_BASE + 0xA48) /* R/W Device IN Endpoint 10 Interrupt Register */ +#define S5P_OTG_DIEPTSIZ10 (USBOTG_LINK_BASE + 0xA50) /* R/W Device IN Endpoint 10 Transfer Size Register */ +#define S5P_OTG_DIEPDMA10 (USBOTG_LINK_BASE + 0xA54) /* R/W Device IN Endpoint 10 DMA Address Register */ +#define S5P_OTG_DIEPCTL11 (USBOTG_LINK_BASE + 0xA60) /* R/W Device Control IN Endpoint 11 Control Register */ +#define S5P_OTG_DIEPINT11 (USBOTG_LINK_BASE + 0xA68) /* R/W Device IN Endpoint 11 Interrupt Register */ +#define S5P_OTG_DIEPTSIZ11 (USBOTG_LINK_BASE + 0xA70) /* R/W Device IN Endpoint 11 Transfer Size Register */ +#define S5P_OTG_DIEPDMA11 (USBOTG_LINK_BASE + 0xA74) /* R/W Device IN Endpoint 11 DMA Address Register */ +#define S5P_OTG_DIEPCTL12 (USBOTG_LINK_BASE + 0xA80) /* R/W Device Control IN Endpoint 12 Control Register */ +#define S5P_OTG_DIEPINT12 (USBOTG_LINK_BASE + 0xA88) /* R/W Device IN Endpoint 12 Interrupt Register */ +#define S5P_OTG_DIEPTSIZ12 (USBOTG_LINK_BASE + 0xA90) /* R/W Device IN Endpoint 12 Transfer Size Register */ +#define S5P_OTG_DIEPDMA12 (USBOTG_LINK_BASE + 0xA94) /* R/W Device IN Endpoint 12 DMA Address Register */ +#define S5P_OTG_DIEPCTL13 (USBOTG_LINK_BASE + 0xAA0) /* R/W Device Control IN Endpoint 13 Control Register */ +#define S5P_OTG_DIEPINT13 (USBOTG_LINK_BASE + 0xAA8) /* R/W Device IN Endpoint 13 Interrupt Register */ +#define S5P_OTG_DIEPTSIZ13 (USBOTG_LINK_BASE + 0xAB0) /* R/W Device IN Endpoint 13 Transfer Size Register */ +#define S5P_OTG_DIEPDMA13 (USBOTG_LINK_BASE + 0xAB4) /* R/W Device IN Endpoint 13 DMA Address Register */ +#define S5P_OTG_DIEPCTL14 (USBOTG_LINK_BASE + 0xAC0) /* R/W Device Control IN Endpoint 14 Control Register */ +#define S5P_OTG_DIEPINT14 (USBOTG_LINK_BASE + 0xAC8) /* R/W Device IN Endpoint 14 Interrupt Register */ +#define S5P_OTG_DIEPTSIZ14 (USBOTG_LINK_BASE + 0xAD0) /* R/W Device IN Endpoint 14 Transfer Size Register */ +#define S5P_OTG_DIEPDMA14 (USBOTG_LINK_BASE + 0xAD4) /* R/W Device IN Endpoint 14 DMA Address Register */ +#define S5P_OTG_DIEPCTL15 (USBOTG_LINK_BASE + 0xAE0) /* R/W Device Control IN Endpoint 15 Control Register */ +#define S5P_OTG_DIEPINT15 (USBOTG_LINK_BASE + 0xAE8) /* R/W Device IN Endpoint 15 Interrupt Register */ +#define S5P_OTG_DIEPTSIZ15 (USBOTG_LINK_BASE + 0xAF0) /* R/W Device IN Endpoint 15 Transfer Size Register */ +#define S5P_OTG_DIEPDMA15 (USBOTG_LINK_BASE + 0xAF4) /* R/W Device IN Endpoint 15 DMA Address Register */ + +/* Device Logical OUT Endpoint-Specific Register */ +#define S5P_OTG_DOEPCTL0 (USBOTG_LINK_BASE + 0xB00) /* R/W Device Control OUT Endpoint 0 Control Register */ +#define S5P_OTG_DOEPINT0 (USBOTG_LINK_BASE + 0xB08) /* R/W Device OUT Endpoint 0 Interrupt Register */ +#define S5P_OTG_DOEPTSIZ0 (USBOTG_LINK_BASE + 0xB10) /* R/W Device OUT Endpoint 0 Transfer Size Register */ +#define S5P_OTG_DOEPDMA0 (USBOTG_LINK_BASE + 0xB14) /* R/W Device OUT Endpoint 0 DMA Address Register */ +#define S5P_OTG_DOEPCTL1 (USBOTG_LINK_BASE + 0xB20) /* R/W Device Control OUT Endpoint 1 Control Register */ +#define S5P_OTG_DOEPINT1 (USBOTG_LINK_BASE + 0xB28) /* R/W Device OUT Endpoint 1 Interrupt Register */ +#define S5P_OTG_DOEPTSIZ1 (USBOTG_LINK_BASE + 0xB30) /* R/W Device OUT Endpoint 1 Transfer Size Register */ +#define S5P_OTG_DOEPDMA1 (USBOTG_LINK_BASE + 0xB34) /* R/W Device OUT Endpoint 1 DMA Address Register */ +#define S5P_OTG_DOEPCTL2 (USBOTG_LINK_BASE + 0xB40) /* R/W Device Control OUT Endpoint 2 Control Register */ +#define S5P_OTG_DOEPINT2 (USBOTG_LINK_BASE + 0xB48) /* R/W Device OUT Endpoint 2 Interrupt Register */ +#define S5P_OTG_DOEPTSIZ2 (USBOTG_LINK_BASE + 0xB50) /* R/W Device OUT Endpoint 2 Transfer Size Register */ +#define S5P_OTG_DOEPDMA2 (USBOTG_LINK_BASE + 0xB54) /* R/W Device OUT Endpoint 2 DMA Address Register */ +#define S5P_OTG_DOEPCTL3 (USBOTG_LINK_BASE + 0xB60) /* R/W Device Control OUT Endpoint 3 Control Register */ +#define S5P_OTG_DOEPINT3 (USBOTG_LINK_BASE + 0xB68) /* R/W Device OUT Endpoint 3 Interrupt Register */ +#define S5P_OTG_DOEPTSIZ3 (USBOTG_LINK_BASE + 0xB70) /* R/W Device OUT Endpoint 3 Transfer Size Register */ +#define S5P_OTG_DOEPDMA3 (USBOTG_LINK_BASE + 0xB74) /* R/W Device OUT Endpoint 3 DMA Address Register */ +#define S5P_OTG_DOEPCTL4 (USBOTG_LINK_BASE + 0xB80) /* R/W Device Control OUT Endpoint 4 Control Register */ +#define S5P_OTG_DOEPINT4 (USBOTG_LINK_BASE + 0xB88) /* R/W Device OUT Endpoint 4 Interrupt Register */ +#define S5P_OTG_DOEPTSIZ4 (USBOTG_LINK_BASE + 0xB90) /* R/W Device OUT Endpoint 4 Transfer Size Register */ +#define S5P_OTG_DOEPDMA4 (USBOTG_LINK_BASE + 0xB94) /* R/W Device OUT Endpoint 4 DMA Address Register */ +#define S5P_OTG_DOEPCTL5 (USBOTG_LINK_BASE + 0xBA0) /* R/W Device Control OUT Endpoint 5 Control Register */ +#define S5P_OTG_DOEPINT5 (USBOTG_LINK_BASE + 0xBA8) /* R/W Device OUT Endpoint 5 Interrupt Register */ +#define S5P_OTG_DOEPTSIZ5 (USBOTG_LINK_BASE + 0xBB0) /* R/W Device OUT Endpoint 5 Transfer Size Register */ +#define S5P_OTG_DOEPDMA5 (USBOTG_LINK_BASE + 0xBB4) /* R/W Device OUT Endpoint 5 DMA Address Register */ +#define S5P_OTG_DOEPCTL6 (USBOTG_LINK_BASE + 0xBC0) /* R/W Device Control OUT Endpoint 6 Control Register */ +#define S5P_OTG_DOEPINT6 (USBOTG_LINK_BASE + 0xBC8) /* R/W Device OUT Endpoint 6 Interrupt Register */ +#define S5P_OTG_DOEPTSIZ6 (USBOTG_LINK_BASE + 0xBD0) /* R/W Device OUT Endpoint 6 Transfer Size Register */ +#define S5P_OTG_DOEPDMA6 (USBOTG_LINK_BASE + 0xBD4) /* R/W Device OUT Endpoint 6 DMA Address Register */ +#define S5P_OTG_DOEPCTL7 (USBOTG_LINK_BASE + 0xBE0) /* R/W Device Control OUT Endpoint 7 Control Register */ +#define S5P_OTG_DOEPINT7 (USBOTG_LINK_BASE + 0xBE8) /* R/W Device OUT Endpoint 7 Interrupt Register */ +#define S5P_OTG_DOEPTSIZ7 (USBOTG_LINK_BASE + 0xBF0) /* R/W Device OUT Endpoint 7 Transfer Size Register */ +#define S5P_OTG_DOEPDMA7 (USBOTG_LINK_BASE + 0xBF4) /* R/W Device OUT Endpoint 7 DMA Address Register */ +#define S5P_OTG_DOEPCTL8 (USBOTG_LINK_BASE + 0xC00) /* R/W Device Control OUT Endpoint 8 Control Register */ +#define S5P_OTG_DOEPINT8 (USBOTG_LINK_BASE + 0xC08) /* R/W Device OUT Endpoint 8 Interrupt Register */ +#define S5P_OTG_DOEPTSIZ8 (USBOTG_LINK_BASE + 0xC10) /* R/W Device OUT Endpoint 8 Transfer Size Register */ +#define S5P_OTG_DOEPDMA8 (USBOTG_LINK_BASE + 0xC14) /* R/W Device OUT Endpoint 8 DMA Address Register */ +#define S5P_OTG_DOEPCTL9 (USBOTG_LINK_BASE + 0xC20) /* R/W Device Control OUT Endpoint 9 Control Register */ +#define S5P_OTG_DOEPINT9 (USBOTG_LINK_BASE + 0xC28) /* R/W Device OUT Endpoint 9 Interrupt Register */ +#define S5P_OTG_DOEPTSIZ9 (USBOTG_LINK_BASE + 0xC30) /* R/W Device OUT Endpoint 9 Transfer Size Register */ +#define S5P_OTG_DOEPDMA9 (USBOTG_LINK_BASE + 0xC34) /* R/W Device OUT Endpoint 9 DMA Address Register */ +#define S5P_OTG_DOEPCTL10 (USBOTG_LINK_BASE + 0xC40) /* R/W Device Control OUT Endpoint 10 Control Register */ +#define S5P_OTG_DOEPINT10 (USBOTG_LINK_BASE + 0xC48) /* R/W Device OUT Endpoint 10 Interrupt Register */ +#define S5P_OTG_DOEPTSIZ10 (USBOTG_LINK_BASE + 0xC50) /* R/W Device OUT Endpoint 10 Transfer Size Register */ +#define S5P_OTG_DOEPDMA10 (USBOTG_LINK_BASE + 0xC54) /* R/W Device OUT Endpoint 10 DMA Address Register */ +#define S5P_OTG_DOEPCTL11 (USBOTG_LINK_BASE + 0xC60) /* R/W Device Control OUT Endpoint 11 Control Register */ +#define S5P_OTG_DOEPINT11 (USBOTG_LINK_BASE + 0xC68) /* R/W Device OUT Endpoint 11 Interrupt Register */ +#define S5P_OTG_DOEPTSIZ11 (USBOTG_LINK_BASE + 0xC70) /* R/W Device OUT Endpoint 11 Transfer Size Register */ +#define S5P_OTG_DOEPDMA11 (USBOTG_LINK_BASE + 0xC74) /* R/W Device OUT Endpoint 11 DMA Address Register */ +#define S5P_OTG_DOEPCTL12 (USBOTG_LINK_BASE + 0xC80) /* R/W Device Control OUT Endpoint 12 Control Register */ +#define S5P_OTG_DOEPINT12 (USBOTG_LINK_BASE + 0xC88) /* R/W Device OUT Endpoint 12 Interrupt Register */ +#define S5P_OTG_DOEPTSIZ12 (USBOTG_LINK_BASE + 0xC90) /* R/W Device OUT Endpoint 12 Transfer Size Register */ +#define S5P_OTG_DOEPDMA12 (USBOTG_LINK_BASE + 0xC94) /* R/W Device OUT Endpoint 12 DMA Address Register */ +#define S5P_OTG_DOEPCTL13 (USBOTG_LINK_BASE + 0xCA0) /* R/W Device Control OUT Endpoint 13 Control Register */ +#define S5P_OTG_DOEPINT13 (USBOTG_LINK_BASE + 0xCA8) /* R/W Device OUT Endpoint 13 Interrupt Register */ +#define S5P_OTG_DOEPTSIZ13 (USBOTG_LINK_BASE + 0xCB0) /* R/W Device OUT Endpoint 13 Transfer Size Register */ +#define S5P_OTG_DOEPDMA13 (USBOTG_LINK_BASE + 0xCB4) /* R/W Device OUT Endpoint 13 DMA Address Register */ +#define S5P_OTG_DOEPCTL14 (USBOTG_LINK_BASE + 0xCC0) /* R/W Device Control OUT Endpoint 14 Control Register */ +#define S5P_OTG_DOEPINT14 (USBOTG_LINK_BASE + 0xCC8) /* R/W Device OUT Endpoint 14 Interrupt Register */ +#define S5P_OTG_DOEPTSIZ14 (USBOTG_LINK_BASE + 0xCD0) /* R/W Device OUT Endpoint 14 Transfer Size Register */ +#define S5P_OTG_DOEPDMA14 (USBOTG_LINK_BASE + 0xCD4) /* R/W Device OUT Endpoint 14 DMA Address Register */ +#define S5P_OTG_DOEPCTL15 (USBOTG_LINK_BASE + 0xCE0) /* R/W Device Control OUT Endpoint 15 Control Register */ +#define S5P_OTG_OTG_DOEPINT15 (USBOTG_LINK_BASE + 0xCE8) /* R/W Device OUT Endpoint 15 Interrupt Register */ +#define S5P_OTG_DOEPTSIZ15 (USBOTG_LINK_BASE + 0xCF0) /* R/W Device OUT Endpoint 15 Transfer Size Register */ +#define S5P_OTG_DOEPDMA15 (USBOTG_LINK_BASE + 0xCF4) /* R/W Device OUT Endpoint 15 DMA Address Register */ + +/* Power and Clock Gating Register */ +#define S5P_OTG_PCGCCTL (USBOTG_LINK_BASE + 0xE00) /* R/W Power and Clock Gating Control Register */ + +/* Endpoint FIFO address */ +#define S5P_OTG_EP0_FIFO (USBOTG_LINK_BASE + 0x1000) + +/* USB Global Interrupt Status register(GINTSTS) setting value */ +#define GINTSTS_WkUpInt (1<<31) +#define GINTSTS_OEPInt (1<<19) +#define GINTSTS_IEPInt (1<<18) +#define GINTSTS_EnumDone (1<<13) +#define GINTSTS_USBRst (1<<12) +#define GINTSTS_USBSusp (1<<11) +#define GINTSTS_RXFLvl (1<<4) + +#endif /* _S5PV310_CPU_H */ diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 1d21ffbb9..9e4db373e 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -51,6 +51,7 @@ COBJS-$(CONFIG_SPL_DSU_SUPPORT) += dsuboot.o endif endif +COBJS-y += usbd-otg-hs.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) diff --git a/drivers/usb/gadget/usbd-otg-hs.c b/drivers/usb/gadget/usbd-otg-hs.c new file mode 100644 index 000000000..ec9d34902 --- /dev/null +++ b/drivers/usb/gadget/usbd-otg-hs.c @@ -0,0 +1,1936 @@ +/* + * cpu/s5pc1xx/usbd-otg-hs.c + * + * (C) Copyright 2007 + * Byungjae Lee, Samsung Erectronics, bjlee@samsung.com. + * - only support for S5PC100 + * + * 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> + +#if defined(CONFIG_S5PC110) || defined(CONFIG_S5PC210) || defined(CONFIG_S5PC220) || defined(CONFIG_S5P6450) || defined(CONFIG_ARCH_EXYNOS) +#include <command.h> +#include <asm/errno.h> +#include <asm/io.h> +#include <asm/arch/cpu.h> +#include "../../../common/cpu.h" +#include "usbd-otg-hs.h" + +#if defined(CONFIG_S5P6450) + DECLARE_GLOBAL_DATA_PTR; +#endif + +#undef USB_OTG_DEBUG_SETUP +#ifdef USB_OTG_DEBUG_SETUP +#define DBG_SETUP0(fmt, args...) printf("[%s:%d] " fmt, __FUNCTION__, __LINE__, ##args) +#define DBG_SETUP1(fmt, args...) printf("\t" fmt, ##args) +#define DBG_SETUP2(fmt, args...) printf(fmt, ##args) +#else +#define DBG_SETUP0(fmt, args...) do { } while (0) +#define DBG_SETUP1(fmt, args...) do { } while (0) +#define DBG_SETUP2(fmt, args...) do { } while (0) +#endif + +#undef USB_OTG_DEBUG_BULK +#ifdef USB_OTG_DEBUG_BULK +#define DBG_BULK0(fmt, args...) printf("[%s:%d] " fmt, __FUNCTION__, __LINE__, ##args) +#define DBG_BULK1(fmt, args...) printf("\t" fmt, ##args) +#else +#define DBG_BULK0(fmt, args...) do { } while (0) +#define DBG_BULK1(fmt, args...) do { } while (0) +#endif + +#define USB_CHECKSUM_EN + +#define TRUE 1 +#define FALSE 0 +#define SUSPEND_RESUME_ON FALSE + + +u32 s3c_usbd_dn_addr = 0; +u32 s3c_usbd_dn_cnt = 0; +u32 remode_wakeup; +u16 config_value; + +int DNW; +int is_fastboot = 0; +int s3c_receive_done = 0; +int s3c_got_header = 0; + +USB_OPMODE op_mode = USB_CPU; +USB_SPEED speed = USB_HIGH; + +otg_dev_t otg; +get_status_t get_status; +get_intf_t get_intf; + +enum EP_INDEX +{ + EP0, EP1, EP2, EP3, EP4 +}; + +/*------------------------------------------------*/ +/* EP0 state */ +enum EP0_STATE +{ + EP0_STATE_INIT = 0, + EP0_STATE_GD_DEV_0 = 11, + EP0_STATE_GD_DEV_1 = 12, + EP0_STATE_GD_DEV_2 = 13, + EP0_STATE_GD_CFG_0 = 21, + EP0_STATE_GD_CFG_1 = 22, + EP0_STATE_GD_CFG_2 = 23, + EP0_STATE_GD_CFG_3 = 24, + EP0_STATE_GD_CFG_4 = 25, + EP0_STATE_GD_STR_I0 = 30, + EP0_STATE_GD_STR_I1 = 31, + EP0_STATE_GD_STR_I2 = 32, + EP0_STATE_GD_STR_I3 = 133, + EP0_STATE_GD_DEV_QUALIFIER = 33, + EP0_STATE_INTERFACE_GET = 34, + EP0_STATE_GET_STATUS0 = 35, + EP0_STATE_GET_STATUS1 = 36, + EP0_STATE_GET_STATUS2 = 37, + EP0_STATE_GET_STATUS3 = 38, + EP0_STATE_GET_STATUS4 = 39, + EP0_STATE_GD_OTHER_SPEED = 40, + EP0_STATE_GD_CFG_ONLY_0 = 41, + EP0_STATE_GD_CFG_ONLY_1 = 42, + EP0_STATE_GD_IF_ONLY_0 = 44, + EP0_STATE_GD_IF_ONLY_1 = 45, + EP0_STATE_GD_EP0_ONLY_0 = 46, + EP0_STATE_GD_EP1_ONLY_0 = 47, + EP0_STATE_GD_EP2_ONLY_0 = 48, + EP0_STATE_GD_EP3_ONLY_0 = 49, + EP0_STATE_GD_OTHER_SPEED_HIGH_1 = 51, + EP0_STATE_GD_OTHER_SPEED_HIGH_2 = 52, + EP0_STATE_GD_OTHER_SPEED_HIGH_3 = 53 +}; + +/*definitions related to CSR setting */ + +/* S5P_OTG_GOTGCTL*/ +#define B_SESSION_VALID (0x1<<19) +#define A_SESSION_VALID (0x1<<18) + +/* S5P_OTG_GAHBCFG*/ +#define PTXFE_HALF (0<<8) +#define PTXFE_ZERO (1<<8) +#define NPTXFE_HALF (0<<7) +#define NPTXFE_ZERO (1<<7) +#define MODE_SLAVE (0<<5) +#define MODE_DMA (1<<5) +#define BURST_SINGLE (0<<1) +#define BURST_INCR (1<<1) +#define BURST_INCR4 (3<<1) +#define BURST_INCR8 (5<<1) +#define BURST_INCR16 (7<<1) +#define GBL_INT_UNMASK (1<<0) +#define GBL_INT_MASK (0<<0) + +/* S5P_OTG_GRSTCTL*/ +#define AHB_MASTER_IDLE (1u<<31) +#define CORE_SOFT_RESET (0x1<<0) + +/* S5P_OTG_GINTSTS/S5P_OTG_GINTMSK core interrupt register */ +#define INT_RESUME (1u<<31) +#define INT_DISCONN (0x1<<29) +#define INT_CONN_ID_STS_CNG (0x1<<28) +#define INT_OUT_EP (0x1<<19) +#define INT_IN_EP (0x1<<18) +#define INT_ENUMDONE (0x1<<13) +#define INT_RESET (0x1<<12) +#define INT_SUSPEND (0x1<<11) +#define INT_TX_FIFO_EMPTY (0x1<<5) +#define INT_RX_FIFO_NOT_EMPTY (0x1<<4) +#define INT_SOF (0x1<<3) +#define INT_DEV_MODE (0x0<<0) +#define INT_HOST_MODE (0x1<<1) + +/* S5P_OTG_GRXSTSP STATUS*/ +#define GLOBAL_OUT_NAK (0x1<<17) +#define OUT_PKT_RECEIVED (0x2<<17) +#define OUT_TRNASFER_COMPLETED (0x3<<17) +#define SETUP_TRANSACTION_COMPLETED (0x4<<17) +#define SETUP_PKT_RECEIVED (0x6<<17) + +/* S5P_OTG_DCTL device control register */ +#define NORMAL_OPERATION (0x1<<0) +#define SOFT_DISCONNECT (0x1<<1) +#define TEST_J_MODE (TEST_J<<4) +#define TEST_K_MODE (TEST_K<<4) +#define TEST_SE0_NAK_MODE (TEST_SE0_NAK<<4) +#define TEST_PACKET_MODE (TEST_PACKET<<4) +#define TEST_FORCE_ENABLE_MODE (TEST_FORCE_ENABLE<<4) +#define TEST_CONTROL_FIELD (0x7<<4) + +/* S5P_OTG_DAINT device all endpoint interrupt register */ +#define INT_IN_EP0 (0x1<<0) +#define INT_IN_EP1 (0x1<<1) +#define INT_IN_EP3 (0x1<<3) +#define INT_OUT_EP0 (0x1<<16) +#define INT_OUT_EP2 (0x1<<18) +#define INT_OUT_EP4 (0x1<<20) + +/* S5P_OTG_DIEPCTL0/S5P_OTG_DOEPCTL0 */ +#define DEPCTL_EPENA (0x1<<31) +#define DEPCTL_EPDIS (0x1<<30) +#define DEPCTL_SNAK (0x1<<27) +#define DEPCTL_CNAK (0x1<<26) +#define DEPCTL_CTRL_TYPE (EP_TYPE_CONTROL<<18) +#define DEPCTL_ISO_TYPE (EP_TYPE_ISOCHRONOUS<<18) +#define DEPCTL_BULK_TYPE (EP_TYPE_BULK<<18) +#define DEPCTL_INTR_TYPE (EP_TYPE_INTERRUPT<<18) +#define DEPCTL_USBACTEP (0x1<<15) + +/*ep0 enable, clear nak, next ep0, max 64byte */ +#define EPEN_CNAK_EP0_64 (DEPCTL_EPENA|DEPCTL_CNAK|(CONTROL_EP<<11)|(0<<0)) + +/*ep0 enable, clear nak, next ep0, 8byte */ +#define EPEN_CNAK_EP0_8 (DEPCTL_EPENA|DEPCTL_CNAK|(CONTROL_EP<<11)|(3<<0)) + +/* DIEPCTLn/DOEPCTLn */ +#define BACK2BACK_SETUP_RECEIVED (0x1<<6) +#define INTKN_TXFEMP (0x1<<4) +#define NON_ISO_IN_EP_TIMEOUT (0x1<<3) +#define CTRL_OUT_EP_SETUP_PHASE_DONE (0x1<<3) +#define AHB_ERROR (0x1<<2) +#define TRANSFER_DONE (0x1<<0) + + +/* 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 +}; + +/* Descriptor size */ +enum DESCRIPTOR_SIZE +{ + DEVICE_DESC_SIZE = sizeof(device_desc_t), + CONFIG_DESC_SIZE = sizeof(config_desc_t), + INTERFACE_DESC_SIZE = sizeof(intf_desc_t), + ENDPOINT_DESC_SIZE = sizeof(ep_desc_t), + DEVICE_QUALIFIER_SIZE = sizeof(qualifier_desc), + OTHER_SPEED_CFG_SIZE = 9 + +}; + +/*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 TEST_PKT_SIZE 53 + +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*/ +}; + +int s3c_usbctl_init(void); +void s3c_usb_set_inep_xfersize(EP_TYPE type, u32 pktcnt, u32 xfersize); +void s3c_usb_write_in_fifo(u8 *buf, int num); +void s3c_usb_read_out_fifo(u8 *buf, int num); + + +void s3c_usb_init_phy(void) +{ +#if defined(CONFIG_ARCH_EXYNOS5) + writel(0x0, USB_CFG_REG); + writel(0x7454, EXYNOS5_OTG_SYS); + udelay(10); + writel(0x0454, EXYNOS5_OTG_SYS); + udelay(10); +#else /* EXYNOS4 or under */ +#if defined(CONFIG_S5PC110) + writel(0xa0, S5P_OTG_PHYPWR); + writel(0x3, S5P_OTG_PHYCLK); +#elif defined(CONFIG_S5PC220) + writel(0x0, USB_CFG_REG); + writel(0x7f80, S5P_OTG_PHYPWR); + writel(0x5, S5P_OTG_PHYCLK); +#elif defined(CONFIG_S5PC210) + writel(0x1f80, S5P_OTG_PHYPWR); + writel(0x3, S5P_OTG_PHYCLK); +#elif defined(CONFIG_S5P6450) + writel(0xa0, S5P_OTG_PHYPWR); + writel(0x21, S5P_OTG_PHYCLK); +#endif + writel(0x1, S5P_OTG_RSTCON); + udelay(10); + writel(0x0, S5P_OTG_RSTCON); + udelay(10); +#endif +} + +/* OTG PHY Power Off */ +void s3c_usb_phy_off(void) { +#if defined(CONFIG_ARCH_EXYNOS5) + writel(0x145F, EXYNOS5_OTG_SYS); +#else + writel(readl(S5P_OTG_PHYPWR)|(0x18), S5P_OTG_PHYPWR); +#endif +#if !defined(CONFIG_S5P6450) + writel(readl(USB_PHY_CONTROL)&~(1<<0), USB_PHY_CONTROL); +#else + writel(readl(OTHERS)|(1<<16), OTHERS); +#endif +} + +void s3c_usb_core_soft_reset(void) +{ + u32 tmp; + + writel(CORE_SOFT_RESET, S5P_OTG_GRSTCTL); + + do + { + tmp = readl(S5P_OTG_GRSTCTL); + }while(!(tmp & AHB_MASTER_IDLE)); + +} + +void s3c_usb_wait_cable_insert(void) +{ + u32 tmp; + int ucFirst=1; + + do { + udelay(50); + + tmp = readl(S5P_OTG_GOTGCTL); + + if (tmp & (B_SESSION_VALID|A_SESSION_VALID)) { + printf("OTG cable Connected!\n"); + break; + } else if(ucFirst == 1) { + printf("Insert a OTG cable into the connector!\n"); + ucFirst = 0; + } + } while(1); +} + +void s3c_usb_init_core(void) +{ + writel(PTXFE_HALF|NPTXFE_HALF|MODE_SLAVE|BURST_SINGLE|GBL_INT_UNMASK, + S5P_OTG_GAHBCFG); + + writel( 0<<15 /* PHY Low Power Clock sel */ + |1<<14 /* Non-Periodic TxFIFO Rewind Enable */ + |0x5<<10 /* Turnaround time */ + |0<<9 /* 0:HNP disable, 1:HNP enable */ + |0<<8 /* 0:SRP disable, 1:SRP enable */ + |0<<7 /* ULPI DDR sel */ + |0<<6 /* 0: high speed utmi+, 1: full speed serial */ + |0<<4 /* 0: utmi+, 1:ulpi */ + |1<<3 /* phy i/f 0:8bit, 1:16bit */ + |0x7<<0, /* HS/FS Timeout**/ + S5P_OTG_GUSBCFG ); +} + +void s3c_usb_check_current_mode(u8 *pucMode) +{ + u32 tmp; + + tmp = readl(S5P_OTG_GINTSTS); + *pucMode = tmp & 0x1; +} + +void s3c_usb_set_soft_disconnect(void) +{ + u32 tmp; + + tmp = readl(S5P_OTG_DCTL); + tmp |= SOFT_DISCONNECT; + writel(tmp, S5P_OTG_DCTL); +} + +void s3c_usb_clear_soft_disconnect(void) +{ + u32 tmp; + + tmp = readl(S5P_OTG_DCTL); + tmp &= ~SOFT_DISCONNECT; + writel(tmp, S5P_OTG_DCTL); +} + +void s3c_usb_init_device(void) +{ + writel(1<<18|otg.speed<<0, S5P_OTG_DCFG); /* [][1: full speed(30Mhz) 0:high speed]*/ + + writel(INT_RESUME|INT_OUT_EP|INT_IN_EP|INT_ENUMDONE| + INT_RESET|INT_SUSPEND|INT_RX_FIFO_NOT_EMPTY, + S5P_OTG_GINTMSK); /*gint unmask */ +} + +int s3c_usbctl_init(void) +{ + u8 ucMode; + + DBG_SETUP0("USB Control Init\n"); +#if defined(CONFIG_S5PC110)||defined(CONFIG_S5PV310) || defined(CONFIG_S5PC210) || defined(CONFIG_S5PC220) || defined(CONFIG_ARCH_EXYNOS) + writel(readl(USB_PHY_CONTROL)|(1<<0), USB_PHY_CONTROL); /*USB PHY0 Enable */ // c110 +#elif defined(CONFIG_S5PC100) + writel(readl(OTHERS)|~(1<<16), OTHERS); +#elif defined(CONFIG_S5P6450) + writel(readl(OTHERS)&~(1<<16), OTHERS); +#else +#error "* CFG_ERROR : you have to select proper CPU for Android Fastboot" +#endif + + otg.speed = speed; + otg.set_config = 0; + otg.ep0_state = EP0_STATE_INIT; + otg.ep0_substate = 0; + s3c_usb_init_phy(); + s3c_usb_core_soft_reset(); + s3c_usb_wait_cable_insert(); + s3c_usb_init_core(); + s3c_usb_check_current_mode(&ucMode); + is_fastboot = 0; + + if (ucMode == INT_DEV_MODE) { + s3c_usb_set_soft_disconnect(); + udelay(10); + s3c_usb_clear_soft_disconnect(); + s3c_usb_init_device(); + return 0; + } else { + printf("Error : Current Mode is Host\n"); + return 0; + } +} + +int s3c_usbc_activate (void) +{ + /* dont used in usb high speed, but used in common file cmd_usbd.c */ + return 0; +} + +int s3c_usb_stop (void) +{ + /* dont used in usb high speed, but used in common file cmd_usbd.c */ + s3c_usb_core_soft_reset(); + s3c_usb_phy_off(); + return 0; +} + +void s3c_usb_print_pkt(u8 *pt, u8 count) +{ + int i; + printf("[s3c_usb_print_pkt:"); + + for(i=0;i<count;i++) + printf("%x,", pt[i]); + + printf("]\n"); +} + +void s3c_usb_verify_checksum(void) +{ + u8 *cs_start, *cs_end; + u16 dnCS; + u16 checkSum; + + printf("Checksum is being calculated."); + + /* checksum calculation */ + cs_start = (u8*)otg.dn_addr; + cs_end = (u8*)(otg.dn_addr+otg.dn_filesize-10); + checkSum = 0; + while(cs_start < cs_end) { + checkSum += *cs_start++; + if(((u32)cs_start&0xfffff)==0) printf("."); + } + +#if defined(CONFIG_S5PC110)||defined(CONFIG_S5PV310) || defined(CONFIG_S5PC210) || defined(CONFIG_S5PC220) || defined(CONFIG_ARCH_EXYNOS) + // fixed alignment fault in case when cs_end is odd. + dnCS = (u16)((cs_end[1]<<8) + cs_end[0]); +#elif defined(CONFIG_S5PC100) || defined(CONFIG_S5P6450) + dnCS = *(u16 *)cs_end; +#else +#error "* CFG_ERROR : you have to select proper CPU" +#endif + + if (checkSum == dnCS) + { + printf("\nChecksum O.K.\n"); + } + else + { + printf("\nChecksum Value => MEM:%x DNW:%x\n",checkSum,dnCS); + printf("Checksum failed.\n\n"); + } + +} + +void s3c_usb_set_inep_xfersize(EP_TYPE type, u32 pktcnt, u32 xfersize) +{ + if(type == EP_TYPE_CONTROL) + { + writel((pktcnt<<19)|(xfersize<<0), S5P_OTG_DIEPTSIZ0); + } + else if(type == EP_TYPE_BULK) + { + writel((1<<29)|(pktcnt<<19)|(xfersize<<0), S5P_OTG_DIEPTSIZ_IN); + } +} + +void s3c_usb_set_outep_xfersize(EP_TYPE type, u32 pktcnt, u32 xfersize) +{ + if(type == EP_TYPE_CONTROL) + { + writel((1<<29)|(pktcnt<<19)|(xfersize<<0), S5P_OTG_DOEPTSIZ0); + } + else if(type == EP_TYPE_BULK) + { + writel((pktcnt<<19)|(xfersize<<0), S5P_OTG_DOEPTSIZ_OUT); + } +} + +void s3c_usb_write_ep0_fifo(u8 *buf, int num) +{ + int i; + u32 Wr_Data=0; + + DBG_SETUP1("[s3c_usb_write_ep0_fifo:"); + + for(i=0;i<num;i+=4) + { + Wr_Data = ((*(buf+3))<<24)|((*(buf+2))<<16)|((*(buf+1))<<8)|*buf; + DBG_SETUP2(" 0x%08x,", Wr_Data); + writel(Wr_Data, S5P_OTG_EP0_FIFO); + buf += 4; + } + + DBG_SETUP2("]\n"); +} + + +void s3c_usb_write_in_fifo(u8 *buf, int num) +{ + int i; + u32 data=0; + + for(i=0;i<num;i+=4) + { + data=((*(buf+3))<<24)|((*(buf+2))<<16)|((*(buf+1))<<8)|*buf; + writel(data, S5P_OTG_IN_FIFO); + buf += 4; + } +} + +void s3c_usb_read_out_fifo(u8 *buf, int num) +{ + int i; + u32 data; + + for (i=0;i<num;i+=4) + { + data = readl(S5P_OTG_OUT_FIFO); + + buf[i] = (u8)data; + buf[i+1] = (u8)(data>>8); + buf[i+2] = (u8)(data>>16); + buf[i+3] = (u8)(data>>24); + } +} + +void s3c_usb_get_desc(void) +{ + switch (otg.dev_req.wValue_H) { + case DEVICE_DESCRIPTOR: + otg.req_length = (u32)((otg.dev_req.wLength_H << 8) | + otg.dev_req.wLength_L); + DBG_SETUP1("DEVICE_DESCRIPTOR = 0x%x \n",otg.req_length); + otg.ep0_state = EP0_STATE_GD_DEV_0; + break; + + case CONFIGURATION_DESCRIPTOR: + otg.req_length = (u32)((otg.dev_req.wLength_H << 8) | + otg.dev_req.wLength_L); + DBG_SETUP1("CONFIGURATION_DESCRIPTOR = 0x%x \n",otg.req_length); + + /* GET_DESCRIPTOR:CONFIGURATION+INTERFACE+ENDPOINT0+ENDPOINT1 */ + if (otg.req_length > CONFIG_DESC_SIZE){ + otg.ep0_state = EP0_STATE_GD_CFG_0; + } else + otg.ep0_state = EP0_STATE_GD_CFG_ONLY_0; + break; + + case STRING_DESCRIPTOR : + DBG_SETUP1("STRING_DESCRIPTOR \n"); + + switch(otg.dev_req.wValue_L) { + case 0: + otg.ep0_state = EP0_STATE_GD_STR_I0; + break; + case 1: + otg.ep0_state = EP0_STATE_GD_STR_I1; + break; + case 2: + otg.ep0_state = EP0_STATE_GD_STR_I2; + break; + case 3: + otg.ep0_state = EP0_STATE_GD_STR_I3; + break; + default: + break; + } + break; + + case ENDPOINT_DESCRIPTOR: + DBG_SETUP1("ENDPOINT_DESCRIPTOR \n"); + switch(otg.dev_req.wValue_L&0xf) { + case 0: + otg.ep0_state=EP0_STATE_GD_EP0_ONLY_0; + break; + case 1: + otg.ep0_state=EP0_STATE_GD_EP1_ONLY_0; + break; + default: + break; + } + break; + + case DEVICE_QUALIFIER: + otg.req_length = (u32)((otg.dev_req.wLength_H << 8) | + otg.dev_req.wLength_L); + DBG_SETUP1("DEVICE_QUALIFIER = 0x%x \n",otg.req_length); + otg.ep0_state = EP0_STATE_GD_DEV_QUALIFIER; + break; + + case OTHER_SPEED_CONFIGURATION : + DBG_SETUP1("OTHER_SPEED_CONFIGURATION \n"); + otg.req_length = (u32)((otg.dev_req.wLength_H << 8) | + otg.dev_req.wLength_L); + otg.ep0_state = EP0_STATE_GD_OTHER_SPEED; + break; + + } +} + +void s3c_usb_clear_feature(void) +{ + switch (otg.dev_req.bmRequestType) { + case DEVICE_RECIPIENT: + DBG_SETUP1("DEVICE_RECIPIENT \n"); + if (otg.dev_req.wValue_L == 1) + remode_wakeup = FALSE; + break; + + case ENDPOINT_RECIPIENT: + DBG_SETUP1("ENDPOINT_RECIPIENT \n"); + if (otg.dev_req.wValue_L == 0) { + if ((otg.dev_req.wIndex_L & 0x7f) == CONTROL_EP) + get_status.ep_ctrl= 0; + + /* IN Endpoint */ + if ((otg.dev_req.wIndex_L & 0x7f) == BULK_IN_EP) + get_status.ep_in= 0; + + /* OUT Endpoint */ + if ((otg.dev_req.wIndex_L & 0x7f) == BULK_OUT_EP) + get_status.ep_out= 0; + } + break; + + default: + DBG_SETUP1("\n"); + break; + } + otg.ep0_state = EP0_STATE_INIT; + +} + +void s3c_usb_set_feature(void) +{ + u32 tmp; + + switch (otg.dev_req.bmRequestType) { + case DEVICE_RECIPIENT: + DBG_SETUP1("DEVICE_RECIPIENT \n"); + if (otg.dev_req.wValue_L == 1) + remode_wakeup = TRUE; + break; + + case ENDPOINT_RECIPIENT: + DBG_SETUP1("ENDPOINT_RECIPIENT \n"); + if (otg.dev_req.wValue_L == 0) { + if ((otg.dev_req.wIndex_L & 0x7f) == CONTROL_EP) + get_status.ep_ctrl= 1; + + if ((otg.dev_req.wIndex_L & 0x7f) == BULK_IN_EP) + get_status.ep_in= 1; + + if ((otg.dev_req.wIndex_L & 0x7f) == BULK_OUT_EP) + get_status.ep_out= 1; + } + break; + + default: + DBG_SETUP1("\n"); + break; + } + + switch (otg.dev_req.wValue_L) { + case EP_STALL: + /* TBD: additional processing if required */ + break; + + case TEST_MODE: + if ((0 != otg.dev_req.wIndex_L ) ||(0 != otg.dev_req.bmRequestType)) + break; + + /* Set TEST MODE*/ + tmp = readl(S5P_OTG_DCTL); + tmp = (tmp & ~(TEST_CONTROL_FIELD)) | (TEST_FORCE_ENABLE_MODE); + writel(tmp, S5P_OTG_DCTL); + + switch(otg.dev_req.wIndex_H) { + case TEST_J: + /*Set Test J*/ + tmp = readl(S5P_OTG_DCTL); + tmp = (tmp & ~(TEST_CONTROL_FIELD)) | (TEST_J_MODE); + writel(tmp, S5P_OTG_DCTL); + break; + + case TEST_K: + /*Set Test K*/ + tmp = readl(S5P_OTG_DCTL); + tmp = (tmp & ~(TEST_CONTROL_FIELD)) | (TEST_K_MODE); + writel(tmp, S5P_OTG_DCTL); + break; + + case TEST_SE0_NAK: + /*Set Test SE0NAK*/ + tmp = readl(S5P_OTG_DCTL); + tmp = (tmp & ~(TEST_CONTROL_FIELD)) | (TEST_SE0_NAK_MODE); + writel(tmp, S5P_OTG_DCTL); + break; + + case TEST_PACKET: + DBG_SETUP1 ("Test_packet\n"); + writel(EPEN_CNAK_EP0_64, S5P_OTG_DIEPCTL0); + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, TEST_PKT_SIZE); + s3c_usb_write_ep0_fifo(test_pkt, TEST_PKT_SIZE); + tmp = readl(S5P_OTG_DCTL); + tmp = (tmp & ~(TEST_CONTROL_FIELD)) | (TEST_PACKET_MODE); + writel(tmp, S5P_OTG_DCTL); + DBG_SETUP1 ("S5P_OTG_DCTL=0x%08x\n", tmp); + break; + } + break; + + default: + break; + } + otg.ep0_state = EP0_STATE_INIT; +} + +void s3c_usb_get_status(void) +{ + switch(otg.dev_req.bmRequestType) { + case (0x80): /*device */ + DBG_SETUP1("DEVICE\n"); + get_status.Device=((u8)remode_wakeup<<1)|0x1; /* SelfPowered */ + otg.ep0_state = EP0_STATE_GET_STATUS0; + break; + + case (0x81): /*interface */ + DBG_SETUP1("INTERFACE\n"); + get_status.Interface=0; + otg.ep0_state = EP0_STATE_GET_STATUS1; + break; + + case (0x82): /*endpoint */ + DBG_SETUP1("ENDPOINT\n"); + if ((otg.dev_req.wIndex_L & 0x7f) == CONTROL_EP) + otg.ep0_state = EP0_STATE_GET_STATUS2; + + if ((otg.dev_req.wIndex_L & 0x7f) == BULK_IN_EP) + otg.ep0_state = EP0_STATE_GET_STATUS3; + + if ((otg.dev_req.wIndex_L & 0x7f) == BULK_OUT_EP) + otg.ep0_state = EP0_STATE_GET_STATUS4; + break; + + default: + DBG_SETUP1("\n"); + break; + } +} + +void s3c_usb_ep0_int_hndlr(void) +{ + u16 i; + u32 buf[2]={0x0000, }; + u16 addr; + + DBG_SETUP0("Event EP0\n"); + + if (otg.ep0_state == EP0_STATE_INIT) { + + for(i=0;i<2;i++) + buf[i] = readl(S5P_OTG_EP0_FIFO); + + otg.dev_req.bmRequestType = buf[0]; + otg.dev_req.bRequest = buf[0]>>8; + otg.dev_req.wValue_L = buf[0]>>16; + otg.dev_req.wValue_H = buf[0]>>24; + otg.dev_req.wIndex_L = buf[1]; + otg.dev_req.wIndex_H = buf[1]>>8; + otg.dev_req.wLength_L = buf[1]>>16; + otg.dev_req.wLength_H = buf[1]>>24; + +#ifdef USB_OTG_DEBUG_SETUP + s3c_usb_print_pkt((u8 *)&otg.dev_req, 8); +#endif + + switch (otg.dev_req.bRequest) { + case STANDARD_SET_ADDRESS: + /* Set Address Update bit */ + addr = (otg.dev_req.wValue_L); + writel(1<<18|addr<<4|otg.speed<<0, S5P_OTG_DCFG); + DBG_SETUP1("S5P_OTG_DCFG : %x, STANDARD_SET_ADDRESS : %d\n", + readl(S5P_OTG_DCFG), addr); + otg.ep0_state = EP0_STATE_INIT; + break; + + case STANDARD_SET_DESCRIPTOR: + DBG_SETUP1("STANDARD_SET_DESCRIPTOR \n"); + break; + + case STANDARD_SET_CONFIGURATION: + DBG_SETUP1("STANDARD_SET_CONFIGURATION \n"); + /* Configuration value in configuration descriptor */ + config_value = otg.dev_req.wValue_L; + otg.set_config = 1; + otg.ep0_state = EP0_STATE_INIT; + break; + + case STANDARD_GET_CONFIGURATION: + DBG_SETUP1("STANDARD_GET_CONFIGURATION \n"); + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 1); + + /*ep0 enable, clear nak, next ep0, 8byte */ + writel(EPEN_CNAK_EP0_8, S5P_OTG_DIEPCTL0); + writel(config_value, S5P_OTG_EP0_FIFO); + otg.ep0_state = EP0_STATE_INIT; + break; + + case STANDARD_GET_DESCRIPTOR: + DBG_SETUP1("STANDARD_GET_DESCRIPTOR :"); + s3c_usb_get_desc(); + break; + + case STANDARD_CLEAR_FEATURE: + DBG_SETUP1("STANDARD_CLEAR_FEATURE :"); + s3c_usb_clear_feature(); + break; + + case STANDARD_SET_FEATURE: + DBG_SETUP1("STANDARD_SET_FEATURE :"); + s3c_usb_set_feature(); + break; + + case STANDARD_GET_STATUS: + DBG_SETUP1("STANDARD_GET_STATUS :"); + s3c_usb_get_status(); + break; + + case STANDARD_GET_INTERFACE: + DBG_SETUP1("STANDARD_GET_INTERFACE \n"); + otg.ep0_state = EP0_STATE_INTERFACE_GET; + break; + + case STANDARD_SET_INTERFACE: + DBG_SETUP1("STANDARD_SET_INTERFACE \n"); + get_intf.AlternateSetting= otg.dev_req.wValue_L; + otg.ep0_state = EP0_STATE_INIT; + break; + + case STANDARD_SYNCH_FRAME: + DBG_SETUP1("STANDARD_SYNCH_FRAME \n"); + otg.ep0_state = EP0_STATE_INIT; + break; + + default: + break; + } + } + + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, otg.ctrl_max_pktsize); + + /*clear nak, next ep0, 64byte */ + writel(((1<<26)|(CONTROL_EP<<11)|(0<<0)), S5P_OTG_DIEPCTL0); + +} + +void s3c_usb_set_otherspeed_conf_desc(u32 length) +{ + /* Standard device descriptor */ + if (length ==9) + { + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 9); + writel(EPEN_CNAK_EP0_64, S5P_OTG_DIEPCTL0); + s3c_usb_write_ep0_fifo(((u8 *)&config_full)+0, 9); + } + else if(length ==32) + { + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 32); + writel(EPEN_CNAK_EP0_64, S5P_OTG_DIEPCTL0); + s3c_usb_write_ep0_fifo(((u8 *)&config_full_total)+0, 32); + + } + otg.ep0_state = EP0_STATE_INIT; +} + +void s3c_usb_transfer_ep0(void) +{ + const u8 *string_desc1, *string_desc2, *string_desc3; + u32 string_desc1_size, string_desc2_size, string_desc3_size; + + if (is_fastboot) { +/* string_desc1 = fboot_string_desc1; + string_desc2 = fboot_string_desc2; + string_desc3 = fboot_string_desc3; + + string_desc1_size = sizeof(fboot_string_desc1); + string_desc2_size = sizeof(fboot_string_desc2); + string_desc3_size = sizeof(fboot_string_desc3); +*/ } else { + string_desc1 = dnw_string_desc1; + string_desc2 = dnw_string_desc2; + string_desc3 = dnw_string_desc2; + + string_desc1_size = sizeof(dnw_string_desc1); + string_desc2_size = sizeof(dnw_string_desc2); + string_desc3_size = sizeof(dnw_string_desc2); + } + + DBG_SETUP0("otg.ep0_state = %d\n", otg.ep0_state); + + switch (otg.ep0_state) { + case EP0_STATE_INIT: + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 0); + + /*ep0 enable, clear nak, next ep0, 8byte */ + writel(EPEN_CNAK_EP0_8, S5P_OTG_DIEPCTL0); + DBG_SETUP1("EP0_STATE_INIT\n"); + break; + + /* GET_DESCRIPTOR:DEVICE */ + case EP0_STATE_GD_DEV_0: + DBG_SETUP1("EP0_STATE_GD_DEV_0 :"); + + /*ep0 enable, clear nak, next ep0, max 64byte */ + writel(EPEN_CNAK_EP0_64, S5P_OTG_DIEPCTL0); + if (otg.req_length < DEVICE_DESC_SIZE) { + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, otg.req_length); + s3c_usb_write_ep0_fifo(((u8 *)&(otg.desc.dev))+0, otg.req_length); + } else { + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, DEVICE_DESC_SIZE); + s3c_usb_write_ep0_fifo(((u8 *)&(otg.desc.dev))+0, DEVICE_DESC_SIZE); + } + otg.ep0_state = EP0_STATE_INIT; + break; + + /* GET_DESCRIPTOR:CONFIGURATION+INTERFACE+ENDPOINT0+ENDPOINT1 */ + case EP0_STATE_GD_CFG_0: + DBG_SETUP1("EP0_STATE_GD_CFG_0 :"); + writel(EPEN_CNAK_EP0_64, S5P_OTG_DIEPCTL0); + if(otg.req_length<CONFIG_DESC_TOTAL_SIZE) + { + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, otg.req_length); + s3c_usb_write_ep0_fifo(((u8 *)&(otg.desc.config))+0, otg.req_length); + } + else + { + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, CONFIG_DESC_TOTAL_SIZE); + s3c_usb_write_ep0_fifo(((u8 *)&(otg.desc.config))+0, CONFIG_DESC_TOTAL_SIZE); + } + otg.ep0_state = EP0_STATE_INIT; + break; + + case EP0_STATE_GD_OTHER_SPEED: + DBG_SETUP1("EP0_STATE_GD_OTHER_SPEED\n"); + s3c_usb_set_otherspeed_conf_desc(otg.req_length); + break; + + /* GET_DESCRIPTOR:CONFIGURATION ONLY*/ + case EP0_STATE_GD_CFG_ONLY_0: + DBG_SETUP1("EP0_STATE_GD_CFG_ONLY_0:"); + if(otg.req_length<CONFIG_DESC_SIZE) + { + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, otg.req_length); + writel(EPEN_CNAK_EP0_64, S5P_OTG_DIEPCTL0); + s3c_usb_write_ep0_fifo(((u8 *)&(otg.desc.config))+0, otg.req_length); + } + else + { + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, CONFIG_DESC_SIZE); + writel(EPEN_CNAK_EP0_64, S5P_OTG_DIEPCTL0); + s3c_usb_write_ep0_fifo(((u8 *)&(otg.desc.config))+0, + CONFIG_DESC_SIZE); + } + otg.ep0_state = EP0_STATE_INIT; + break; + + /* GET_DESCRIPTOR:INTERFACE ONLY */ + + case EP0_STATE_GD_IF_ONLY_0: + DBG_SETUP1("EP0_STATE_GD_IF_ONLY_0 :"); + if(otg.req_length<INTERFACE_DESC_SIZE) + { + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, otg.req_length); + writel(EPEN_CNAK_EP0_64, S5P_OTG_DIEPCTL0); + s3c_usb_write_ep0_fifo(((u8 *)&(otg.desc.intf))+0, otg.req_length); + } + else + { + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, INTERFACE_DESC_SIZE); + writel(EPEN_CNAK_EP0_64, S5P_OTG_DIEPCTL0); + s3c_usb_write_ep0_fifo(((u8 *)&(otg.desc.intf))+0, INTERFACE_DESC_SIZE); + } + otg.ep0_state = EP0_STATE_INIT; + break; + + /* GET_DESCRIPTOR:ENDPOINT 1 ONLY */ + case EP0_STATE_GD_EP0_ONLY_0: + DBG_SETUP1("EP0_STATE_GD_EP0_ONLY_0\n"); + writel(EPEN_CNAK_EP0_8, S5P_OTG_DIEPCTL0); + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, ENDPOINT_DESC_SIZE); + s3c_usb_write_ep0_fifo(((u8 *)&(otg.desc.ep1))+0, ENDPOINT_DESC_SIZE); + otg.ep0_state = EP0_STATE_INIT; + break; + + /* GET_DESCRIPTOR:ENDPOINT 2 ONLY */ + case EP0_STATE_GD_EP1_ONLY_0: + DBG_SETUP1("EP0_STATE_GD_EP1_ONLY_0\n"); + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, ENDPOINT_DESC_SIZE); + writel(EPEN_CNAK_EP0_8, S5P_OTG_DIEPCTL0); + s3c_usb_write_ep0_fifo(((u8 *)&(otg.desc.ep2))+0, ENDPOINT_DESC_SIZE); + otg.ep0_state = EP0_STATE_INIT; + break; + + /* GET_DESCRIPTOR:STRING */ + case EP0_STATE_GD_STR_I0: + DBG_SETUP1("EP0_STATE_GD_STR_I0\n"); + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, sizeof(string_desc0)); + writel(EPEN_CNAK_EP0_8, S5P_OTG_DIEPCTL0); + s3c_usb_write_ep0_fifo((u8 *)string_desc0, sizeof(string_desc0)); + otg.ep0_state = EP0_STATE_INIT; + break; + + case EP0_STATE_GD_STR_I1: + DBG_SETUP1("EP0_STATE_GD_STR_I1 %d\n", otg.ep0_substate); + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, string_desc1_size); + if ((otg.ep0_substate*otg.ctrl_max_pktsize+otg.ctrl_max_pktsize) + < string_desc1_size) { + + writel(EPEN_CNAK_EP0_64, S5P_OTG_DIEPCTL0); + s3c_usb_write_ep0_fifo((u8 *)string_desc1+(otg.ep0_substate*otg.ctrl_max_pktsize), + otg.ctrl_max_pktsize); + otg.ep0_state = EP0_STATE_GD_STR_I1; + otg.ep0_substate++; + } else { + writel(EPEN_CNAK_EP0_64, S5P_OTG_DIEPCTL0); + s3c_usb_write_ep0_fifo((u8 *)string_desc1+(otg.ep0_substate*otg.ctrl_max_pktsize), + string_desc1_size-(otg.ep0_substate*otg.ctrl_max_pktsize)); + otg.ep0_state = EP0_STATE_INIT; + otg.ep0_substate = 0; + } + break; + + case EP0_STATE_GD_STR_I2: + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, string_desc2_size); + if ((otg.ep0_substate*otg.ctrl_max_pktsize+otg.ctrl_max_pktsize) + < string_desc2_size) { + + writel(EPEN_CNAK_EP0_64, S5P_OTG_DIEPCTL0); + s3c_usb_write_ep0_fifo((u8 *)string_desc2+(otg.ep0_substate*otg.ctrl_max_pktsize), + otg.ctrl_max_pktsize); + otg.ep0_state = EP0_STATE_GD_STR_I2; + otg.ep0_substate++; + } else { + writel(EPEN_CNAK_EP0_64, S5P_OTG_DIEPCTL0); + s3c_usb_write_ep0_fifo((u8 *)string_desc2+(otg.ep0_substate*otg.ctrl_max_pktsize), + string_desc2_size-(otg.ep0_substate*otg.ctrl_max_pktsize)); + otg.ep0_state = EP0_STATE_INIT; + otg.ep0_substate = 0; + } + DBG_SETUP1("EP0_STATE_GD_STR_I2 %d", otg.ep0_substate); + break; + + case EP0_STATE_GD_STR_I3: + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, string_desc3_size); + if ((otg.ep0_substate*otg.ctrl_max_pktsize+otg.ctrl_max_pktsize) + < string_desc3_size) { + + writel(EPEN_CNAK_EP0_64, S5P_OTG_DIEPCTL0); + s3c_usb_write_ep0_fifo((u8 *)string_desc3+(otg.ep0_substate*otg.ctrl_max_pktsize), + otg.ctrl_max_pktsize); + otg.ep0_state = EP0_STATE_GD_STR_I3; + otg.ep0_substate++; + } else { + writel(EPEN_CNAK_EP0_64, S5P_OTG_DIEPCTL0); + s3c_usb_write_ep0_fifo((u8 *)string_desc3+(otg.ep0_substate*otg.ctrl_max_pktsize), + string_desc3_size-(otg.ep0_substate*otg.ctrl_max_pktsize)); + otg.ep0_state = EP0_STATE_INIT; + otg.ep0_substate = 0; + } + DBG_SETUP1("EP0_STATE_GD_STR_I3 %d", otg.ep0_substate); + break; + + case EP0_STATE_INTERFACE_GET: + DBG_SETUP1("EP0_STATE_INTERFACE_GET\n"); + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 1); + writel(EPEN_CNAK_EP0_8, S5P_OTG_DIEPCTL0); + s3c_usb_write_ep0_fifo((u8 *)&get_intf+0, 1); + otg.ep0_state = EP0_STATE_INIT; + break; + + + case EP0_STATE_GET_STATUS0: + DBG_SETUP1("EP0_STATE_GET_STATUS0\n"); + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 1); + writel(EPEN_CNAK_EP0_8, S5P_OTG_DIEPCTL0); + s3c_usb_write_ep0_fifo((u8 *)&get_status+0, 1); + otg.ep0_state = EP0_STATE_INIT; + break; + + case EP0_STATE_GET_STATUS1: + DBG_SETUP1("EP0_STATE_GET_STATUS1\n"); + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 1); + writel(EPEN_CNAK_EP0_8, S5P_OTG_DIEPCTL0); + s3c_usb_write_ep0_fifo((u8 *)&get_status+1, 1); + otg.ep0_state = EP0_STATE_INIT; + break; + + case EP0_STATE_GET_STATUS2: + DBG_SETUP1("EP0_STATE_GET_STATUS2\n"); + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 1); + writel(EPEN_CNAK_EP0_8, S5P_OTG_DIEPCTL0); + s3c_usb_write_ep0_fifo((u8 *)&get_status+2, 1); + otg.ep0_state = EP0_STATE_INIT; + break; + + case EP0_STATE_GET_STATUS3: + DBG_SETUP1("EP0_STATE_GET_STATUS3\n"); + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 1); + writel(EPEN_CNAK_EP0_8, S5P_OTG_DIEPCTL0); + s3c_usb_write_ep0_fifo((u8 *)&get_status+3, 1); + otg.ep0_state = EP0_STATE_INIT; + break; + + case EP0_STATE_GET_STATUS4: + DBG_SETUP1("EP0_STATE_GET_STATUS4\n"); + s3c_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 1); + writel(EPEN_CNAK_EP0_8, S5P_OTG_DIEPCTL0); + s3c_usb_write_ep0_fifo((u8 *)&get_status+4, 1); + otg.ep0_state = EP0_STATE_INIT; + break; + + default: + break; + } +} + + +void s3c_usb_int_bulkin(void) +{ + u8* bulkin_buf; + u32 remain_cnt; + + DBG_BULK0("Bulk In Function\n"); + + bulkin_buf = (u8*)otg.up_ptr; + remain_cnt = otg.up_size- ((u32)otg.up_ptr - otg.up_addr); + DBG_BULK1("bulkin_buf = 0x%x,remain_cnt = 0x%x \n", bulkin_buf, remain_cnt); + + if (remain_cnt > otg.bulkin_max_pktsize) { + s3c_usb_set_inep_xfersize(EP_TYPE_BULK, 1, otg.bulkin_max_pktsize); + + /*ep3 enable, clear nak, bulk, usb active, next ep3, max pkt 64*/ + writel(1u<<31|1<<26|2<<18|1<<15|otg.bulkin_max_pktsize<<0, + S5P_OTG_DIEPCTL_IN); + + s3c_usb_write_in_fifo(bulkin_buf, otg.bulkin_max_pktsize); + + otg.up_ptr += otg.bulkin_max_pktsize; + + while(readl(S5P_OTG_DIEPCTL_IN) & (1<<31)); + } else if(remain_cnt > 0) { + s3c_usb_set_inep_xfersize(EP_TYPE_BULK, 1, remain_cnt); + + /*ep3 enable, clear nak, bulk, usb active, next ep3, max pkt 64*/ + writel(1u<<31|1<<26|2<<18|1<<15|otg.bulkin_max_pktsize<<0, + S5P_OTG_DIEPCTL_IN); + + s3c_usb_write_in_fifo(bulkin_buf, remain_cnt); + + otg.up_ptr += remain_cnt; + + while(readl(S5P_OTG_DIEPCTL_IN) & (1<<31)); + } else { /*remain_cnt = 0*/ + writel((DEPCTL_SNAK|DEPCTL_BULK_TYPE), S5P_OTG_DIEPCTL_IN); + } +} + +void s3c_usb_upload_start(void) +{ + u8 tmp_buf[12]; + u32 check; + + s3c_usb_read_out_fifo((u8 *)tmp_buf, 10); + check = *((u8 *)(tmp_buf+8)) + (*((u8 *)(tmp_buf+9))<<8); + + if (check==0x1) { + otg.up_addr = + *((u8 *)(tmp_buf+0))+ + (*((u8 *)(tmp_buf+1))<<8)+ + (*((u8 *)(tmp_buf+2))<<16)+ + (*((u8 *)(tmp_buf+3))<<24); + + otg.up_size = + *((u8 *)(tmp_buf+4))+ + (*((u8 *)(tmp_buf+5))<<8)+ + (*((u8 *)(tmp_buf+6))<<16)+ + (*((u8 *)(tmp_buf+7))<<24); + + otg.up_ptr=(u8 *)otg.up_addr; + DBG_BULK1("UploadAddress : 0x%x, UploadSize: %d\n", + otg.up_addr, otg.up_size); + + if (otg.op_mode == USB_CPU) { + if (otg.up_size > otg.bulkin_max_pktsize) { + s3c_usb_set_inep_xfersize(EP_TYPE_BULK, 1, + otg.bulkin_max_pktsize); + } else { + s3c_usb_set_inep_xfersize(EP_TYPE_BULK, 1, + otg.up_size); + } + + /*ep1 enable, clear nak, bulk, usb active, max pkt 64*/ + writel(1u<<31|1<<26|2<<18|1<<15|otg.bulkin_max_pktsize<<0, + S5P_OTG_DIEPCTL_IN); + } else if ((otg.op_mode == USB_DMA) && (otg.up_size > 0)) { + u32 pktcnt, remainder; + + DBG_BULK1("Dma Start for IN PKT \n"); + + writel(MODE_DMA|BURST_INCR4|GBL_INT_UNMASK, + S5P_OTG_GAHBCFG); + writel(INT_RESUME|INT_OUT_EP|INT_IN_EP| INT_ENUMDONE| + INT_RESET|INT_SUSPEND, S5P_OTG_GINTMSK); + + writel((u32)otg.up_ptr, S5P_OTG_DIEPDMA_IN); + + pktcnt = (u32)(otg.up_size/otg.bulkin_max_pktsize); + remainder = (u32)(otg.up_size%otg.bulkin_max_pktsize); + if(remainder != 0) { + pktcnt += 1; + } + + if (pktcnt > 1023) { + s3c_usb_set_inep_xfersize(EP_TYPE_BULK, 1023, + (otg.bulkin_max_pktsize*1023)); + } else { + s3c_usb_set_inep_xfersize(EP_TYPE_BULK, pktcnt, + otg.up_size); + } + + /*ep1 enable, clear nak, bulk, usb active, next ep1, max pkt */ + writel(1u<<31|1<<26|2<<18|1<<15|BULK_IN_EP<<11| + otg.bulkin_max_pktsize<<0, + S5P_OTG_DIEPCTL_IN); + } + } + otg.dn_filesize=0; +} + +void s3c_usb_download_start(u32 fifo_cnt_byte) +{ + u8 tmp_buf[8]; + + s3c_usb_read_out_fifo((u8 *)tmp_buf, 8); + DBG_BULK1("downloadFileSize==0, 1'st BYTE_READ_CNT_REG : %x\n", + fifo_cnt_byte); + + otg.dn_addr=s3c_usbd_dn_addr; + otg.dn_filesize= + *((u8 *)(tmp_buf+4))+ + (*((u8 *)(tmp_buf+5))<<8)+ + (*((u8 *)(tmp_buf+6))<<16)+ + (*((u8 *)(tmp_buf+7))<<24); + + otg.dn_ptr=(u8 *)otg.dn_addr; + DBG_BULK1("downloadAddress : 0x%x, downloadFileSize: %x\n", + otg.dn_addr, otg.dn_filesize); + + /* The first 8-bytes are deleted.*/ + s3c_usb_read_out_fifo((u8 *)otg.dn_ptr, fifo_cnt_byte-8); + otg.dn_ptr += fifo_cnt_byte-8; + + if (otg.op_mode == USB_CPU) { + s3c_usb_set_outep_xfersize(EP_TYPE_BULK, 1, + otg.bulkout_max_pktsize); + + /*ep3 enable, clear nak, bulk, usb active, next ep3, max pkt 64*/ + writel(1u<<31|1<<26|2<<18|1<<15|otg.bulkout_max_pktsize<<0, + S5P_OTG_DOEPCTL_OUT); + } else if (otg.dn_filesize>otg.bulkout_max_pktsize) { + u32 pkt_cnt, remain_cnt; + + DBG_BULK1("downloadFileSize!=0, Dma Start for 2nd OUT PKT \n"); + writel(INT_RESUME|INT_OUT_EP|INT_IN_EP|INT_ENUMDONE| + INT_RESET|INT_SUSPEND, S5P_OTG_GINTMSK); /*gint unmask */ + writel(MODE_DMA|BURST_INCR4|GBL_INT_UNMASK, + S5P_OTG_GAHBCFG); + writel((u32)otg.dn_ptr, S5P_OTG_DOEPDMA_OUT); + pkt_cnt = (u32)(otg.dn_filesize-otg.bulkout_max_pktsize)/otg.bulkout_max_pktsize; + remain_cnt = (u32)((otg.dn_filesize-otg.bulkout_max_pktsize)%otg.bulkout_max_pktsize); + if(remain_cnt != 0) { + pkt_cnt += 1; + } + + if (pkt_cnt > 1023) { + s3c_usb_set_outep_xfersize(EP_TYPE_BULK, 1023, + (otg.bulkout_max_pktsize*1023)); + } else { + s3c_usb_set_outep_xfersize(EP_TYPE_BULK, pkt_cnt, + (otg.dn_filesize-otg.bulkout_max_pktsize)); + } + + /*ep3 enable, clear nak, bulk, usb active, next ep3, max pkt 64*/ + writel(1u<<31|1<<26|2<<18|1<<15|otg.bulkout_max_pktsize<<0, + S5P_OTG_DOEPCTL_OUT); + } +} + +void s3c_usb_download_continue(u32 fifo_cnt_byte) +{ + if (otg.op_mode == USB_CPU) { + s3c_usb_read_out_fifo((u8 *)otg.dn_ptr, fifo_cnt_byte); + otg.dn_ptr += fifo_cnt_byte; + DBG_BULK1("downloadFileSize!=0, 2nd BYTE_READ_CNT_REG = 0x%x, m_pDownPt = 0x%x\n", + fifo_cnt_byte, otg.dn_ptr); + + s3c_usb_set_outep_xfersize(EP_TYPE_BULK, 1, otg.bulkout_max_pktsize); + + /*ep3 enable, clear nak, bulk, usb active, next ep3, max pkt 64*/ + writel(1u<<31|1<<26|2<<18|1<<15|otg.bulkout_max_pktsize<<0, + S5P_OTG_DOEPCTL_OUT); + + /* USB format : addr(4)+size(4)+data(n)+cs(2) */ + if (((u32)otg.dn_ptr - otg.dn_addr) >= (otg.dn_filesize - 8)) { + printf("Download Done!! Download Address: 0x%x, Download Filesize:0x%x\n", + otg.dn_addr, (otg.dn_filesize-10)); + + s3c_usbd_dn_cnt = otg.dn_filesize-10; + s3c_usbd_dn_addr = otg.dn_addr; + +#ifdef USB_CHECKSUM_EN + s3c_usb_verify_checksum(); +#endif + s3c_receive_done = 1; + } + + }\ +} + +void s3c_usb_int_bulkout(u32 fifo_cnt_byte) +{ + DBG_BULK0("Bulk Out Function : otg.dn_filesize=0x%x\n", otg.dn_filesize); + if (otg.dn_filesize==0) { + if (fifo_cnt_byte == 10) { + s3c_usb_upload_start(); + } else { + s3c_usb_download_start(fifo_cnt_byte); + } + } else { + s3c_usb_download_continue(fifo_cnt_byte); + } +} + +void s3c_usb_dma_in_done(void) +{ + s32 remain_cnt; + + DBG_BULK0("DMA IN : Transfer Done\n"); + + otg.up_ptr = (u8 *)readl(S5P_OTG_DIEPDMA_IN); + remain_cnt = otg.up_size- ((u32)otg.up_ptr - otg.up_addr); + + if (remain_cnt>0) { + u32 pktcnt, remainder; + pktcnt = (u32)(remain_cnt/otg.bulkin_max_pktsize); + remainder = (u32)(remain_cnt%otg.bulkin_max_pktsize); + if(remainder != 0) { + pktcnt += 1; + } + DBG_SETUP1("remain_cnt : %d \n", remain_cnt); + if (pktcnt> 1023) { + s3c_usb_set_inep_xfersize(EP_TYPE_BULK, 1023, + (otg.bulkin_max_pktsize*1023)); + } else { + s3c_usb_set_inep_xfersize(EP_TYPE_BULK, pktcnt, + remain_cnt); + } + + /*ep1 enable, clear nak, bulk, usb active, next ep1, max pkt */ + writel(1u<<31|1<<26|2<<18|1<<15|BULK_IN_EP<<11|otg.bulkin_max_pktsize<<0, + S5P_OTG_DIEPCTL_IN); + } else + DBG_SETUP1("DMA IN : Transfer Complete\n"); +} + +void s3c_usb_dma_out_done(void) +{ + s32 remain_cnt; + + DBG_BULK1("DMA OUT : Transfer Done\n"); + otg.dn_ptr = (u8 *)readl(S5P_OTG_DOEPDMA_OUT); + + remain_cnt = otg.dn_filesize - ((u32)otg.dn_ptr - otg.dn_addr + 8); + + if (remain_cnt>0) { + u32 pktcnt, remainder; + pktcnt = (u32)(remain_cnt/otg.bulkout_max_pktsize); + remainder = (u32)(remain_cnt%otg.bulkout_max_pktsize); + if(remainder != 0) { + pktcnt += 1; + } + DBG_BULK1("remain_cnt : %d \n", remain_cnt); + if (pktcnt> 1023) { + s3c_usb_set_outep_xfersize(EP_TYPE_BULK, 1023, + (otg.bulkout_max_pktsize*1023)); + } else { + s3c_usb_set_outep_xfersize(EP_TYPE_BULK, pktcnt, + remain_cnt); + } + + /*ep3 enable, clear nak, bulk, usb active, next ep3, max pkt 64*/ + writel(1u<<31|1<<26|2<<18|1<<15|otg.bulkout_max_pktsize<<0, + S5P_OTG_DOEPCTL_OUT); + } else { + DBG_BULK1("DMA OUT : Transfer Complete\n"); + udelay(500); /*for FPGA ???*/ + } +} + +void s3c_usb_set_all_outep_nak(void) +{ + u8 i; + u32 tmp; + + for(i=0;i<16;i++) + { + tmp = readl(S5P_OTG_DOEPCTL0+0x20*i); + tmp |= DEPCTL_SNAK; + writel(tmp, S5P_OTG_DOEPCTL0+0x20*i); + } +} + +void s3c_usb_clear_all_outep_nak(void) +{ + u8 i; + u32 tmp; + + for(i=0;i<16;i++) + { + tmp = readl(S5P_OTG_DOEPCTL0+0x20*i); + tmp |= (DEPCTL_EPENA|DEPCTL_CNAK); + writel(tmp, S5P_OTG_DOEPCTL0+0x20*i); + } +} + +void s3c_usb_set_max_pktsize(USB_SPEED speed) +{ + if (speed == USB_HIGH) + { + otg.speed = USB_HIGH; + otg.ctrl_max_pktsize = HS_CTRL_PKT_SIZE; + otg.bulkin_max_pktsize = HS_BULK_PKT_SIZE; + otg.bulkout_max_pktsize = HS_BULK_PKT_SIZE; + } + else + { + otg.speed = USB_FULL; + otg.ctrl_max_pktsize = FS_CTRL_PKT_SIZE; + otg.bulkin_max_pktsize = FS_BULK_PKT_SIZE; + otg.bulkout_max_pktsize = FS_BULK_PKT_SIZE; + } +} + +void s3c_usb_set_endpoint(void) +{ + /* Unmask S5P_OTG_DAINT source */ + writel(0xff, S5P_OTG_DIEPINT0); + writel(0xff, S5P_OTG_DOEPINT0); + writel(0xff, S5P_OTG_DIEPINT_IN); + writel(0xff, S5P_OTG_DOEPINT_OUT); + + /* Init For Ep0*/ + /*MPS:64bytes */ + writel(((1<<26)|(CONTROL_EP<<11)|(0<<0)), S5P_OTG_DIEPCTL0); + /*ep0 enable, clear nak */ + writel((1u<<31)|(1<<26)|(0<<0), S5P_OTG_DOEPCTL0); +} + +void s3c_usb_set_descriptors(void) +{ + /* Standard device descriptor */ + otg.desc.dev.bLength=DEVICE_DESC_SIZE; /*0x12*/ + otg.desc.dev.bDescriptorType=DEVICE_DESCRIPTOR; + otg.desc.dev.bDeviceClass=0xFF; /* 0x0*/ + otg.desc.dev.bDeviceSubClass=0x0; + otg.desc.dev.bDeviceProtocol=0x0; + otg.desc.dev.bMaxPacketSize0=otg.ctrl_max_pktsize; + otg.desc.dev.idVendorL=0xE8; /*0x45;*/ + otg.desc.dev.idVendorH=0x04; /*0x53;*/ + otg.desc.dev.idProductL=0x34; /*0x00*/ + otg.desc.dev.idProductH=0x12; /*0x64*/ + otg.desc.dev.bcdDeviceL=0x00; + otg.desc.dev.bcdDeviceH=0x01; + otg.desc.dev.iManufacturer=0x1; /* index of string descriptor */ + otg.desc.dev.iProduct=0x2; /* index of string descriptor */ + otg.desc.dev.iSerialNumber=0x0; + otg.desc.dev.bNumConfigurations=0x1; + if (otg.speed == USB_FULL) { + otg.desc.dev.bcdUSBL=0x10; + otg.desc.dev.bcdUSBH=0x01; /* Ver 1.10*/ + } + else { + otg.desc.dev.bcdUSBL=0x00; + otg.desc.dev.bcdUSBH=0x02; /* Ver 2.0*/ + } + + /* Standard configuration descriptor */ + otg.desc.config.bLength=CONFIG_DESC_SIZE; /* 0x9 bytes */ + otg.desc.config.bDescriptorType=CONFIGURATION_DESCRIPTOR; + otg.desc.config.wTotalLengthL=CONFIG_DESC_TOTAL_SIZE; + otg.desc.config.wTotalLengthH=0; + otg.desc.config.bNumInterfaces=1; +/* dbg descConf.bConfigurationValue=2; // why 2? There's no reason.*/ + otg.desc.config.bConfigurationValue=1; + otg.desc.config.iConfiguration=0; + otg.desc.config.bmAttributes=CONF_ATTR_DEFAULT|CONF_ATTR_SELFPOWERED; /* bus powered only.*/ + otg.desc.config.maxPower=25; /* draws 50mA current from the USB bus.*/ + + /* Standard interface descriptor */ + otg.desc.intf.bLength=INTERFACE_DESC_SIZE; /* 9*/ + otg.desc.intf.bDescriptorType=INTERFACE_DESCRIPTOR; + otg.desc.intf.bInterfaceNumber=0x0; + otg.desc.intf.bAlternateSetting=0x0; /* ?*/ + otg.desc.intf.bNumEndpoints = 2; /* # of endpoints except EP0*/ + otg.desc.intf.bInterfaceClass=0xff; /* 0x0 ?*/ + otg.desc.intf.bInterfaceSubClass=0x0; + otg.desc.intf.bInterfaceProtocol=0x0; + otg.desc.intf.iInterface=0x0; + + /* Standard endpoint0 descriptor */ + otg.desc.ep1.bLength=ENDPOINT_DESC_SIZE; + otg.desc.ep1.bDescriptorType=ENDPOINT_DESCRIPTOR; + otg.desc.ep1.bEndpointAddress=BULK_IN_EP|EP_ADDR_IN; + otg.desc.ep1.bmAttributes=EP_ATTR_BULK; + otg.desc.ep1.wMaxPacketSizeL=(u8)otg.bulkin_max_pktsize; /* 64*/ + otg.desc.ep1.wMaxPacketSizeH=(u8)(otg.bulkin_max_pktsize>>8); + otg.desc.ep1.bInterval=0x0; /* not used */ + + /* Standard endpoint1 descriptor */ + otg.desc.ep2.bLength=ENDPOINT_DESC_SIZE; + otg.desc.ep2.bDescriptorType=ENDPOINT_DESCRIPTOR; + otg.desc.ep2.bEndpointAddress=BULK_OUT_EP|EP_ADDR_OUT; + otg.desc.ep2.bmAttributes=EP_ATTR_BULK; + otg.desc.ep2.wMaxPacketSizeL=(u8)otg.bulkout_max_pktsize; /* 64*/ + otg.desc.ep2.wMaxPacketSizeH=(u8)(otg.bulkout_max_pktsize>>8); + otg.desc.ep2.bInterval=0x0; /* not used */ +} + +void s3c_usb_check_speed(USB_SPEED *speed) +{ + u32 status; + + status = readl(S5P_OTG_DSTS); /* System status read */ + + *speed = (USB_SPEED)((status&0x6) >>1); +} + +void s3c_usb_clear_dnfile_info(void) +{ + otg.dn_addr = 0; + otg.dn_filesize = 0; + otg.dn_ptr = 0; +} + +void s3c_usb_clear_upfile_info(void) +{ + otg.up_addr= 0; + otg.up_size= 0; + otg.up_ptr = 0; +} + + +int s3c_usb_check_setconf(void) +{ + if (otg.set_config == 0) + return FALSE; + else + return TRUE; +} + +void s3c_usb_set_opmode(USB_OPMODE mode) +{ + otg.op_mode = mode; + + writel(INT_RESUME|INT_OUT_EP|INT_IN_EP|INT_ENUMDONE| + INT_RESET|INT_SUSPEND|INT_RX_FIFO_NOT_EMPTY, + S5P_OTG_GINTMSK); /*gint unmask */ + + writel(MODE_SLAVE|BURST_SINGLE|GBL_INT_UNMASK, S5P_OTG_GAHBCFG); + + s3c_usb_set_outep_xfersize(EP_TYPE_BULK, 1, otg.bulkout_max_pktsize); + s3c_usb_set_inep_xfersize(EP_TYPE_BULK, 1, 0); + + /*bulk out ep enable, clear nak, bulk, usb active, next ep3, max pkt */ + writel(1u<<31|1<<26|2<<18|1<<15|otg.bulkout_max_pktsize<<0, + S5P_OTG_DOEPCTL_OUT); + + /*bulk in ep enable, clear nak, bulk, usb active, next ep1, max pkt */ + writel(0u<<31|1<<26|2<<18|1<<15|otg.bulkin_max_pktsize<<0, + S5P_OTG_DIEPCTL_IN); +} + +void s3c_usb_reset(void) +{ + s3c_usb_set_all_outep_nak(); + + otg.ep0_state = EP0_STATE_INIT; + writel(((1<<BULK_OUT_EP)|(1<<CONTROL_EP))<<16|((1<<BULK_IN_EP)|(1<<CONTROL_EP)), + S5P_OTG_DAINTMSK); + writel(CTRL_OUT_EP_SETUP_PHASE_DONE|AHB_ERROR|TRANSFER_DONE, + S5P_OTG_DOEPMSK); + writel(INTKN_TXFEMP|NON_ISO_IN_EP_TIMEOUT|AHB_ERROR|TRANSFER_DONE, + S5P_OTG_DIEPMSK); + + /* Rx FIFO Size */ + writel(RX_FIFO_SIZE, S5P_OTG_GRXFSIZ); + + /* Non Periodic Tx FIFO Size */ + writel(NPTX_FIFO_SIZE<<16| NPTX_FIFO_START_ADDR<<0, S5P_OTG_GNPTXFSIZ); + + s3c_usb_clear_all_outep_nak(); + + /*clear device address */ + writel(readl(S5P_OTG_DCFG)&~(0x7f<<4), S5P_OTG_DCFG); + + if(SUSPEND_RESUME_ON) { + writel(readl(S5P_OTG_PCGCCTL)&~(1<<0), S5P_OTG_PCGCCTL); + } +} +int s3c_usb_set_init(void) +{ + u32 status; + + status = readl(S5P_OTG_DSTS); /* System status read */ + + /* Set if Device is High speed or Full speed */ + if (((status&0x6) >>1) == USB_HIGH) { + DBG_SETUP1("High Speed Detection\n"); + s3c_usb_set_max_pktsize(USB_HIGH); + } + else if(((status&0x6) >>1) == USB_FULL) { + DBG_SETUP1("Full Speed Detec tion\n"); + s3c_usb_set_max_pktsize(USB_FULL); + } + else { + printf("**** Error:Neither High_Speed nor Full_Speed\n"); + return FALSE; + } + + s3c_usb_set_endpoint(); +/* if (is_fastboot) + fboot_usb_set_descriptors(); + else +*/ s3c_usb_set_descriptors(); + s3c_usb_clear_dnfile_info(); + s3c_usb_set_opmode(op_mode); + + return TRUE; +} + +void s3c_usb_pkt_receive(void) +{ + u32 rx_status; + u32 fifo_cnt_byte; + + rx_status = readl(S5P_OTG_GRXSTSP); + DBG_SETUP0("S5P_OTG_GRXSTSP = 0x%x\n", rx_status); + + if ((rx_status & (0xf<<17)) == SETUP_PKT_RECEIVED) { + DBG_SETUP1("SETUP_PKT_RECEIVED\n"); + s3c_usb_ep0_int_hndlr(); + + } else if ((rx_status & (0xf<<17)) == OUT_PKT_RECEIVED) { + fifo_cnt_byte = (rx_status & 0x7ff0)>>4; + DBG_SETUP1("OUT_PKT_RECEIVED\n"); + + if((rx_status & BULK_OUT_EP)&&(fifo_cnt_byte)) { +/* if (is_fastboot) + fboot_usb_int_bulkout(fifo_cnt_byte); + else +*/ s3c_usb_int_bulkout(fifo_cnt_byte); + if( otg.op_mode == USB_CPU ) + writel(INT_RESUME|INT_OUT_EP|INT_IN_EP| + INT_ENUMDONE|INT_RESET|INT_SUSPEND| + INT_RX_FIFO_NOT_EMPTY, + S5P_OTG_GINTMSK); + return; + } + + } else if ((rx_status & (0xf<<17)) == GLOBAL_OUT_NAK) { + DBG_SETUP1("GLOBAL_OUT_NAK\n"); + + } else if ((rx_status & (0xf<<17)) == OUT_TRNASFER_COMPLETED) { + DBG_SETUP1("OUT_TRNASFER_COMPLETED\n"); + + } else if ((rx_status & (0xf<<17)) == SETUP_TRANSACTION_COMPLETED) { + DBG_SETUP1("SETUP_TRANSACTION_COMPLETED\n"); + + } else { + DBG_SETUP1("Reserved\n"); + } +} + +void s3c_usb_transfer(void) +{ + u32 ep_int; + u32 check_dma; + u32 ep_int_status; + + ep_int = readl(S5P_OTG_DAINT); + DBG_SETUP0("S5P_OTG_DAINT = 0x%x", ep_int); + + if (ep_int & (1<<CONTROL_EP)) { + ep_int_status = readl(S5P_OTG_DIEPINT0); + DBG_SETUP1("S5P_OTG_DIEPINT0 : %x \n", ep_int_status); + + if (ep_int_status & INTKN_TXFEMP) { + u32 uNTxFifoSpace; + do { + uNTxFifoSpace=readl(S5P_OTG_GNPTXSTS)&0xffff; + }while(uNTxFifoSpace<otg.ctrl_max_pktsize); + + s3c_usb_transfer_ep0(); + } + + writel(ep_int_status, S5P_OTG_DIEPINT0); /* Interrupt Clear */ + } else if (ep_int & ((1<<CONTROL_EP)<<16)) { + ep_int_status = readl(S5P_OTG_DOEPINT0); + DBG_SETUP1("S5P_OTG_DOEPINT0 : %x \n", ep_int_status); + + s3c_usb_set_outep_xfersize(EP_TYPE_CONTROL, 1, 8); + writel(1u<<31|1<<26, S5P_OTG_DOEPCTL0); /*ep0 enable, clear nak */ + + writel(ep_int_status, S5P_OTG_DOEPINT0); /* Interrupt Clear */ + } else if(ep_int & (1<<BULK_IN_EP)) { + ep_int_status = readl(S5P_OTG_DIEPINT_IN); + DBG_BULK1("S5P_OTG_DIEPINT_IN : %x \n", ep_int_status); + writel(ep_int_status, S5P_OTG_DIEPINT_IN); /* Interrupt Clear */ + + if ( (ep_int_status&INTKN_TXFEMP) && otg.op_mode == USB_CPU) { +/* if (is_fastboot) + fboot_usb_int_bulkin(); + else +*/ s3c_usb_int_bulkin(); + } + + check_dma = readl(S5P_OTG_GAHBCFG); + if ((check_dma&MODE_DMA)&&(ep_int_status&TRANSFER_DONE)) + s3c_usb_dma_in_done(); + } else if (ep_int & ((1<<BULK_OUT_EP)<<16)) { + ep_int_status = readl(S5P_OTG_DOEPINT_OUT); + DBG_BULK1("S5P_OTG_DOEPINT_OUT : 0x%x\n", ep_int_status); + writel(ep_int_status, S5P_OTG_DOEPINT_OUT); /* Interrupt Clear */ + + check_dma = readl(S5P_OTG_GAHBCFG); + if ((check_dma&MODE_DMA)&&(ep_int_status&TRANSFER_DONE)) { + s3c_usb_dma_out_done(); + } + } +} +#define ERROR -1 +#define OK 0 +int s3c_udc_int_hndlr(void) +{ + u32 int_status; + int tmp; + int ret = ERROR; + + int_status = readl(S5P_OTG_GINTSTS); /* Core Interrupt Register */ + writel(int_status, S5P_OTG_GINTSTS); /* Interrupt Clear */ + DBG_SETUP0("*** USB OTG Interrupt(S5P_OTG_GINTSTS: 0x%08x) ****\n", + int_status); + + if (int_status & INT_RESET) { + DBG_SETUP1("INT_RESET\n"); + writel(INT_RESET, S5P_OTG_GINTSTS); /* Interrupt Clear */ + + s3c_usb_reset(); + ret = OK; + } + + if (int_status & INT_ENUMDONE) { + DBG_SETUP1("INT_ENUMDONE :"); + writel(INT_ENUMDONE, S5P_OTG_GINTSTS); /* Interrupt Clear */ + + tmp = s3c_usb_set_init(); + ret = OK; + if (tmp == FALSE) + return ret; + } + + if (int_status & INT_RESUME) { + DBG_SETUP1("INT_RESUME\n"); + writel(INT_RESUME, S5P_OTG_GINTSTS); /* Interrupt Clear */ + + if(SUSPEND_RESUME_ON) { + writel(readl(S5P_OTG_PCGCCTL)&~(1<<0), S5P_OTG_PCGCCTL); + DBG_SETUP1("INT_RESUME\n"); + } + ret = OK; + } + + if (int_status & INT_SUSPEND) { + DBG_SETUP1("INT_SUSPEND\n"); + writel(INT_SUSPEND, S5P_OTG_GINTSTS); /* Interrupt Clear */ + + if(SUSPEND_RESUME_ON) { + writel(readl(S5P_OTG_PCGCCTL)|(1<<0), S5P_OTG_PCGCCTL); + } + ret = OK; + } + + if(int_status & INT_RX_FIFO_NOT_EMPTY) { + DBG_SETUP1("INT_RX_FIFO_NOT_EMPTY\n"); + /* Read only register field */ + + writel(INT_RESUME|INT_OUT_EP|INT_IN_EP| + INT_ENUMDONE|INT_RESET|INT_SUSPEND, + S5P_OTG_GINTMSK); + s3c_usb_pkt_receive(); + writel(INT_RESUME|INT_OUT_EP|INT_IN_EP|INT_ENUMDONE| + INT_RESET |INT_SUSPEND|INT_RX_FIFO_NOT_EMPTY, + S5P_OTG_GINTMSK); /*gint unmask */ + ret = OK; + } + + if ((int_status & INT_IN_EP) || (int_status & INT_OUT_EP)) { + DBG_SETUP1("INT_IN or OUT_EP\n"); + /* Read only register field */ + + s3c_usb_transfer(); + ret = OK; + } + return ret; +} + +#endif diff --git a/drivers/usb/gadget/usbd-otg-hs.h b/drivers/usb/gadget/usbd-otg-hs.h new file mode 100644 index 000000000..f8d460eeb --- /dev/null +++ b/drivers/usb/gadget/usbd-otg-hs.h @@ -0,0 +1,306 @@ +/* + * cpu/s5pc1xx/usbd-otg-hs.h + * + * (C) Copyright 2009 + * Byungjae Lee, Samsung Erectronics, bjlee@samsung.com. + * - only support for S5PC100 + * + * 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 __S3C_OTG_HS_H__ +#define __S3C_OTG_HS_H__ + +#include <asm/byteorder.h> +#include <asm/arch/cpu.h> +#include <asm/io.h> + +#define S3C_USBD_DETECT_IRQ() (readl(S5P_OTG_GINTSTS) & \ + (GINTSTS_WkUpInt|GINTSTS_OEPInt|GINTSTS_IEPInt| \ + GINTSTS_EnumDone|GINTSTS_USBRst|GINTSTS_USBSusp|GINTSTS_RXFLvl)) +#define S3C_USBD_CLEAR_IRQ() do { \ + writel(BIT_ALLMSK, (S5P_OTG_GINTSTS)); \ + } while (0) + +#define CONTROL_EP 0 +#define BULK_IN_EP 1 +#define BULK_OUT_EP 2 + +#define FS_CTRL_PKT_SIZE 64 +#define FS_BULK_PKT_SIZE 64 + +#define HS_CTRL_PKT_SIZE 64 +#define HS_BULK_PKT_SIZE 512 + +#define RX_FIFO_SIZE 512 +#define NPTX_FIFO_START_ADDR RX_FIFO_SIZE +#define NPTX_FIFO_SIZE 512 +#define PTX_FIFO_SIZE 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 S5P_OTG_DIEPCTL_IN (S5P_OTG_DIEPCTL0 + 0x20*BULK_IN_EP) +#define S5P_OTG_DIEPINT_IN (S5P_OTG_DIEPINT0 + 0x20*BULK_IN_EP) +#define S5P_OTG_DIEPTSIZ_IN (S5P_OTG_DIEPTSIZ0 + 0x20*BULK_IN_EP) +#define S5P_OTG_DIEPDMA_IN (S5P_OTG_DIEPDMA0 + 0x20*BULK_IN_EP) +#define S5P_OTG_DOEPCTL_OUT (S5P_OTG_DOEPCTL0 + 0x20*BULK_OUT_EP) +#define S5P_OTG_DOEPINT_OUT (S5P_OTG_DOEPINT0 + 0x20*BULK_OUT_EP) +#define S5P_OTG_DOEPTSIZ_OUT (S5P_OTG_DOEPTSIZ0 + 0x20*BULK_OUT_EP) +#define S5P_OTG_DOEPDMA_OUT (S5P_OTG_DOEPDMA0 + 0x20*BULK_OUT_EP) +#define S5P_OTG_IN_FIFO (S5P_OTG_EP0_FIFO + 0x1000*BULK_IN_EP) +#define S5P_OTG_OUT_FIFO (S5P_OTG_EP0_FIFO + 0x1000*BULK_OUT_EP) + + +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; +} __attribute__ ((packed)) device_desc_t; + +typedef struct +{ + u8 bLength; + u8 bDescriptorType; + u8 wTotalLengthL; + u8 wTotalLengthH; + u8 bNumInterfaces; + u8 bConfigurationValue; + u8 iConfiguration; + u8 bmAttributes; + u8 maxPower; +} __attribute__ ((packed)) config_desc_t; + +typedef struct +{ + u8 bLength; + u8 bDescriptorType; + u8 bInterfaceNumber; + u8 bAlternateSetting; + u8 bNumEndpoints; + u8 bInterfaceClass; + u8 bInterfaceSubClass; + u8 bInterfaceProtocol; + u8 iInterface; +} __attribute__ ((packed)) intf_desc_t; + +typedef struct +{ + u8 bLength; + u8 bDescriptorType; + u8 bEndpointAddress; + u8 bmAttributes; + u8 wMaxPacketSizeL; + u8 wMaxPacketSizeH; + u8 bInterval; +} __attribute__ ((packed)) ep_desc_t; + +typedef struct +{ + u8 bmRequestType; + u8 bRequest; + u8 wValue_L; + u8 wValue_H; + u8 wIndex_L; + u8 wIndex_H; + u8 wLength_L; + u8 wLength_H; +} __attribute__ ((packed)) device_req_t; + +typedef struct +{ + device_desc_t dev; + config_desc_t config; + intf_desc_t intf; + ep_desc_t ep1; + ep_desc_t ep2; + ep_desc_t ep3; + ep_desc_t ep4; +} __attribute__ ((packed)) descriptors_t; + +typedef struct +{ + u8 Device; + u8 Interface; + u8 ep_ctrl; + u8 ep_in; + u8 ep_out; +} __attribute__ ((packed)) get_status_t; + +typedef struct +{ + u8 AlternateSetting; +} __attribute__ ((packed)) get_intf_t; + + +typedef enum +{ + USB_CPU, USB_DMA +} USB_OPMODE; + +typedef enum +{ + USB_HIGH, USB_FULL, USB_LOW +} USB_SPEED; + +typedef enum +{ + EP_TYPE_CONTROL, EP_TYPE_ISOCHRONOUS, EP_TYPE_BULK, EP_TYPE_INTERRUPT +} EP_TYPE; + + +typedef struct +{ + descriptors_t desc; + device_req_t dev_req; + + u32 ep0_state; + u32 ep0_substate; + USB_OPMODE op_mode; + USB_SPEED speed; + u32 ctrl_max_pktsize; + u32 bulkin_max_pktsize; + u32 bulkout_max_pktsize; + u32 dn_addr; + u32 dn_filesize; + u32 up_addr; + u32 up_size; + u8* dn_ptr; + u8* up_ptr; + u32 set_config; + u32 req_length; +} __attribute__ ((packed)) otg_dev_t; + +// SPEC1.1 + +// Standard bmRequestType (direction) +enum DEV_REQUEST_DIRECTION +{ + HOST_TO_DEVICE = 0x00, + DEVICE_TO_HOST = 0x80 +}; + +// Standard bmRequestType (Type) +enum DEV_REQUEST_TYPE +{ + STANDARD_TYPE = 0x00, + CLASS_TYPE = 0x20, + VENDOR_TYPE = 0x40, + RESERVED_TYPE = 0x60 +}; + +// Standard bmRequestType (Recipient) +enum DEV_REQUEST_RECIPIENT +{ + DEVICE_RECIPIENT = 0, + INTERFACE_RECIPIENT = 1, + ENDPOINT_RECIPIENT = 2, + OTHER_RECIPIENT = 3 +}; + +// 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, +}; + +// configuration descriptor: bmAttributes +enum CONFIG_ATTRIBUTES +{ + CONF_ATTR_DEFAULT = 0x80, + 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 +}; + +// 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 +}; + +int s3c_usbctl_init(void); +int s3c_usbc_activate (void); +int s3c_usb_stop( void ); +int s3c_udc_int_hndlr(void); + +/* in usbd-otg-hs.c */ +extern unsigned int s3c_usbd_dn_addr; +extern unsigned int s3c_usbd_dn_cnt; +extern int DNW; +extern int s3c_got_header; +extern int s3c_receive_done; + +#endif diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 6c9479492..d248be237 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk LIB := $(obj)libusb_host.o # ohci +COBJS-$(CONFIG_S3C_USBD) += usb_ohci.o COBJS-$(CONFIG_USB_OHCI_NEW) += ohci-hcd.o COBJS-$(CONFIG_USB_ATMEL) += ohci-at91.o COBJS-$(CONFIG_USB_OHCI_DA8XX) += ohci-da8xx.o diff --git a/drivers/usb/host/usb_ohci.c b/drivers/usb/host/usb_ohci.c new file mode 100644 index 000000000..734709c0c --- /dev/null +++ b/drivers/usb/host/usb_ohci.c @@ -0,0 +1,750 @@ +/* + * URB OHCI HCD (Host Controller Driver) for USB on the S3C24XX. + * + * (C) Copyright 2003 + * Gary Jennejohn, DENX Software Engineering <gj@denx.de> + * + * Note: Much of this code has been derived from Linux 2.4 + * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> + * (C) Copyright 2000-2002 David Brownell + * + * 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 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 + * + */ +/* + * IMPORTANT NOTES + * 1 - you MUST define LITTLEENDIAN in the configuration file for the + * board or this driver will NOT work! + * 2 - this driver is intended for use with USB Mass Storage Devices + * (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes! + */ + +#include <common.h> + +#ifdef CONFIG_USB_OHCI + +#include <malloc.h> +#include <usb.h> + +#include <asm/arch/cpu.h> + +#include "usb_ohci.h" + + +#define OHCI_USE_NPS /* force NoPowerSwitching mode */ +#define OHCI_VERBOSE_DEBUG /* not always helpful */ + + +/* For initializing controller (mask in an HCFS mode too) */ +#define OHCI_CONTROL_INIT \ + (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE + +//#define readl(a) (*((vu_long *)(a))) +//#define writel(a, b) (*((vu_long *)(b)) = ((vu_long)a)) + +#define min_t(type,x,y) ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) + +#undef DEBUG_USB_OHCI +#ifdef DEBUG_USB_OHCI +#define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg) +#else +#define dbg(format, arg...) do {} while(0) +#endif /* DEBUG_USB_OHCI */ +#define err(format, arg...) printf("ERROR: " format "\n", ## arg) +#undef SHOW_INFO +#ifdef SHOW_INFO +#define info(format, arg...) printf("INFO: " format "\n", ## arg) +#else +#define info(format, arg...) do {} while(0) +#endif + +#define m16_swap(x) le16_to_cpu(x) +#define m32_swap(x) le32_to_cpu(x) + +/* global ohci_t */ +static ohci_t gohci; +/* this must be aligned to a 256 byte boundary */ +struct ohci_hcca ghcca[1]; +/* a pointer to the aligned storage */ +struct ohci_hcca *phcca; +/* this allocates EDs for all possible endpoints */ +struct ohci_device ohci_dev; +/* urb_priv */ +urb_priv_t urb_priv; +/* RHSC flag */ +int got_rhsc; +/* device which was disconnected */ +struct usb_device *devgone; + +/*-------------------------------------------------------------------------*/ + +/* AMD-756 (D2 rev) reports corrupt register contents in some cases. + * The erratum (#4) description is incorrect. AMD's workaround waits + * till some bits (mostly reserved) are clear; ok for all revs. + */ +#define OHCI_QUIRK_AMD756 0xabcd +#define read_roothub(hc, register, mask) ({ \ + u32 temp = readl (&hc->regs->roothub.register); \ + if (hc->flags & OHCI_QUIRK_AMD756) \ + while (temp & mask) \ + temp = readl (&hc->regs->roothub.register); \ + temp; }) + + static inline u32 roothub_b (struct ohci *hc) + { return readl (&hc->regs->roothub.b); } +static inline u32 roothub_status (struct ohci *hc) + { return readl (&hc->regs->roothub.status); } + + +/* forward declaration */ +static void +td_submit_job (struct usb_device * dev, unsigned long pipe, void * buffer, + int transfer_len, struct devrequest * setup, urb_priv_t * urb, int interval); + +/*-------------------------------------------------------------------------* + * URB support functions + *-------------------------------------------------------------------------*/ + +/* free HCD-private data associated with this URB */ + +static void urb_free_priv (urb_priv_t * urb) +{ + int i; + int last; + struct td * td; + + last = urb->length - 1; + if (last >= 0) { + for (i = 0; i <= last; i++) { + td = urb->td[i]; + if (td) { + td->usb_dev = NULL; + urb->td[i] = NULL; + } + } + } +} + +/*-------------------------------------------------------------------------*/ + +#ifdef DEBUG_USB_OHCI +static int sohci_get_current_frame_number (struct usb_device * dev); + +/* debug| print the main components of an URB + * small: 0) header + data packets 1) just header */ + +static void pkt_print (struct usb_device * dev, unsigned long pipe, void * buffer, + int transfer_len, struct devrequest * setup, char * str, int small) +{ + urb_priv_t * purb = &urb_priv; + + dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d/%d stat:%#lx", + str, + sohci_get_current_frame_number (dev), + usb_pipedevice (pipe), + usb_pipeendpoint (pipe), + usb_pipeout (pipe)? 'O': 'I', + usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"): + (usb_pipecontrol (pipe)? "CTRL": "BULK"), + purb->actual_length, + transfer_len, dev->status); +#ifdef OHCI_VERBOSE_DEBUG + if (!small) { + int i, len; + + if (usb_pipecontrol (pipe)) { + printf (__FILE__ ": cmd(8):"); + for (i = 0; i < 8 ; i++) + printf (" %02x", ((__u8 *) setup) [i]); + printf ("\n"); + } + if (transfer_len > 0 && buffer) { + printf (__FILE__ ": data(%d/%d):", + purb->actual_length, + transfer_len); + len = usb_pipeout (pipe)? + transfer_len: purb->actual_length; + for (i = 0; i < 16 && i < len; i++) + printf (" %02x", ((__u8 *) buffer) [i]); + printf ("%s\n", i < len? "...": ""); + } + } +#endif +} + +/* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/ +void ep_print_int_eds (ohci_t *ohci, char * str) { + int i, j; + __u32 * ed_p; + for (i= 0; i < 32; i++) { + j = 5; + ed_p = &(ohci->hcca->int_table [i]); + if (*ed_p == 0) + continue; + printf (__FILE__ ": %s branch int %2d(%2x):", str, i, i); + while (*ed_p != 0 && j--) { + ed_t *ed = (ed_t *)m32_swap(ed_p); + printf (" ed: %4x;", ed->hwINFO); + ed_p = &ed->hwNextED; + } + printf ("\n"); + } +} + +static void ohci_dump_intr_mask (char *label, __u32 mask) +{ + dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s", + label, + mask, + (mask & OHCI_INTR_MIE) ? " MIE" : "", + (mask & OHCI_INTR_OC) ? " OC" : "", + (mask & OHCI_INTR_RHSC) ? " RHSC" : "", + (mask & OHCI_INTR_FNO) ? " FNO" : "", + (mask & OHCI_INTR_UE) ? " UE" : "", + (mask & OHCI_INTR_RD) ? " RD" : "", + (mask & OHCI_INTR_SF) ? " SF" : "", + (mask & OHCI_INTR_WDH) ? " WDH" : "", + (mask & OHCI_INTR_SO) ? " SO" : "" + ); +} + +static void maybe_print_eds (char *label, __u32 value) +{ + ed_t *edp = (ed_t *)value; + + if (value) { + dbg ("%s %08x", label, value); + dbg ("%08x", edp->hwINFO); + dbg ("%08x", edp->hwTailP); + dbg ("%08x", edp->hwHeadP); + dbg ("%08x", edp->hwNextED); + } +} + +static char * hcfs2string (int state) +{ + switch (state) { + case OHCI_USB_RESET: return "reset"; + case OHCI_USB_RESUME: return "resume"; + case OHCI_USB_OPER: return "operational"; + case OHCI_USB_SUSPEND: return "suspend"; + } + return "?"; +} + +/* dump control and status registers */ +static void ohci_dump_status (ohci_t *controller) +{ + struct ohci_regs *regs = controller->regs; + __u32 temp; + + temp = readl (®s->revision) & 0xff; + if (temp != 0x10) + dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f)); + + temp = readl (®s->control); + dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, + (temp & OHCI_CTRL_RWE) ? " RWE" : "", + (temp & OHCI_CTRL_RWC) ? " RWC" : "", + (temp & OHCI_CTRL_IR) ? " IR" : "", + hcfs2string (temp & OHCI_CTRL_HCFS), + (temp & OHCI_CTRL_BLE) ? " BLE" : "", + (temp & OHCI_CTRL_CLE) ? " CLE" : "", + (temp & OHCI_CTRL_IE) ? " IE" : "", + (temp & OHCI_CTRL_PLE) ? " PLE" : "", + temp & OHCI_CTRL_CBSR + ); + + temp = readl (®s->cmdstatus); + dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, + (temp & OHCI_SOC) >> 16, + (temp & OHCI_OCR) ? " OCR" : "", + (temp & OHCI_BLF) ? " BLF" : "", + (temp & OHCI_CLF) ? " CLF" : "", + (temp & OHCI_HCR) ? " HCR" : "" + ); + + ohci_dump_intr_mask ("intrstatus", readl (®s->intrstatus)); + ohci_dump_intr_mask ("intrenable", readl (®s->intrenable)); + + maybe_print_eds ("ed_periodcurrent", readl (®s->ed_periodcurrent)); + + maybe_print_eds ("ed_controlhead", readl (®s->ed_controlhead)); + maybe_print_eds ("ed_controlcurrent", readl (®s->ed_controlcurrent)); + + maybe_print_eds ("ed_bulkhead", readl (®s->ed_bulkhead)); + maybe_print_eds ("ed_bulkcurrent", readl (®s->ed_bulkcurrent)); + + maybe_print_eds ("donehead", readl (®s->donehead)); +} + +static void ohci_dump_roothub (ohci_t *controller, int verbose) +{ + __u32 temp, ndp, i; + + temp = roothub_a (controller); + ndp = (temp & RH_A_NDP); + + if (verbose) { + dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, + ((temp & RH_A_POTPGT) >> 24) & 0xff, + (temp & RH_A_NOCP) ? " NOCP" : "", + (temp & RH_A_OCPM) ? " OCPM" : "", + (temp & RH_A_DT) ? " DT" : "", + (temp & RH_A_NPS) ? " NPS" : "", + (temp & RH_A_PSM) ? " PSM" : "", + ndp + ); + temp = roothub_b (controller); + dbg ("roothub.b: %08x PPCM=%04x DR=%04x", + temp, + (temp & RH_B_PPCM) >> 16, + (temp & RH_B_DR) + ); + temp = roothub_status (controller); + dbg ("roothub.status: %08x%s%s%s%s%s%s", + temp, + (temp & RH_HS_CRWE) ? " CRWE" : "", + (temp & RH_HS_OCIC) ? " OCIC" : "", + (temp & RH_HS_LPSC) ? " LPSC" : "", + (temp & RH_HS_DRWE) ? " DRWE" : "", + (temp & RH_HS_OCI) ? " OCI" : "", + (temp & RH_HS_LPS) ? " LPS" : "" + ); + } + + for (i = 0; i < ndp; i++) { + temp = roothub_portstatus (controller, i); + dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", + i, + temp, + (temp & RH_PS_PRSC) ? " PRSC" : "", + (temp & RH_PS_OCIC) ? " OCIC" : "", + (temp & RH_PS_PSSC) ? " PSSC" : "", + (temp & RH_PS_PESC) ? " PESC" : "", + (temp & RH_PS_CSC) ? " CSC" : "", + + (temp & RH_PS_LSDA) ? " LSDA" : "", + (temp & RH_PS_PPS) ? " PPS" : "", + (temp & RH_PS_PRS) ? " PRS" : "", + (temp & RH_PS_POCI) ? " POCI" : "", + (temp & RH_PS_PSS) ? " PSS" : "", + + (temp & RH_PS_PES) ? " PES" : "", + (temp & RH_PS_CCS) ? " CCS" : "" + ); + } +} + +static void ohci_dump (ohci_t *controller, int verbose) +{ + dbg ("OHCI controller usb-%s state", controller->slot_name); + + /* dumps some of the state we know about */ + ohci_dump_status (controller); + if (verbose) + ep_print_int_eds (controller, "hcca"); + dbg ("hcca frame #%04x", controller->hcca->frame_no); + ohci_dump_roothub (controller, 1); +} + + +#endif /* DEBUG_USB_OHCI */ + +/*-------------------------------------------------------------------------* + * Interface functions (URB) + *-------------------------------------------------------------------------*/ + +/* get a transfer request */ + +int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup, int interval) +{ + ohci_t *ohci; + ed_t * ed; + urb_priv_t *purb_priv; + int i, size = 0; + + ohci = &gohci; + + /* when controller's hung, permit only roothub cleanup attempts + * such as powering down ports */ + if (ohci->disabled) { + err("sohci_submit_job: EPIPE"); + return -1; + } + + /* every endpoint has a ed, locate and fill it */ + if (!(ed = ep_add_ed (dev, pipe))) { + err("sohci_submit_job: ENOMEM"); + return -1; + } + + /* for the private part of the URB we need the number of TDs (size) */ + switch (usb_pipetype (pipe)) { + case PIPE_BULK: /* one TD for every 4096 Byte */ + size = (transfer_len - 1) / 4096 + 1; + break; + case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */ + size = (transfer_len == 0)? 2: + (transfer_len - 1) / 4096 + 3; + break; + } + + if (size >= (N_URB_TD - 1)) { + err("need %d TDs, only have %d", size, N_URB_TD); + return -1; + } + purb_priv = &urb_priv; + purb_priv->pipe = pipe; + + /* fill the private part of the URB */ + purb_priv->length = size; + purb_priv->ed = ed; + purb_priv->actual_length = 0; + + /* allocate the TDs */ + /* note that td[0] was allocated in ep_add_ed */ + for (i = 0; i < size; i++) { + purb_priv->td[i] = td_alloc (dev); + if (!purb_priv->td[i]) { + purb_priv->length = i; + urb_free_priv (purb_priv); + err("sohci_submit_job: ENOMEM"); + return -1; + } + } + + if (ed->state == ED_NEW || (ed->state & ED_DEL)) { + urb_free_priv (purb_priv); + err("sohci_submit_job: EINVAL"); + return -1; + } + + /* link the ed into a chain if is not already */ + if (ed->state != ED_OPER) + ep_link (ohci, ed); + + /* fill the TDs and link it to the ed */ + td_submit_job(dev, pipe, buffer, transfer_len, setup, purb_priv, interval); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +#ifdef DEBUG_USB_OHCI +/* tell us the current USB frame number */ + +static int sohci_get_current_frame_number (struct usb_device *usb_dev) +{ + ohci_t *ohci = &gohci; + + return m16_swap (ohci->hcca->frame_no); +} +#endif + +/*-------------------------------------------------------------------------* + * ED handling functions + *-------------------------------------------------------------------------*/ + +/* link an ed into one of the HC chains */ + +static int ep_link (ohci_t *ohci, ed_t *edi) +{ + volatile ed_t *ed = edi; + + ed->state = ED_OPER; + + switch (ed->type) { + case PIPE_CONTROL: + ed->hwNextED = 0; + if (ohci->ed_controltail == NULL) { + writel (ed, &ohci->regs->ed_controlhead); + } else { + ohci->ed_controltail->hwNextED = m32_swap (ed); + } + ed->ed_prev = ohci->ed_controltail; + if (!ohci->ed_controltail && !ohci->ed_rm_list[0] && + !ohci->ed_rm_list[1] && !ohci->sleeping) { + ohci->hc_control |= OHCI_CTRL_CLE; + writel (ohci->hc_control, &ohci->regs->control); + } + ohci->ed_controltail = edi; + break; + + case PIPE_BULK: + ed->hwNextED = 0; + if (ohci->ed_bulktail == NULL) { + writel (ed, &ohci->regs->ed_bulkhead); + } else { + ohci->ed_bulktail->hwNextED = m32_swap (ed); + } + ed->ed_prev = ohci->ed_bulktail; + if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] && + !ohci->ed_rm_list[1] && !ohci->sleeping) { + ohci->hc_control |= OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); + } + ohci->ed_bulktail = edi; + break; + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* unlink an ed from one of the HC chains. + * just the link to the ed is unlinked. + * the link from the ed still points to another operational ed or 0 + * so the HC can eventually finish the processing of the unlinked ed */ + +/*-------------------------------------------------------------------------*/ + +/* add/reinit an endpoint; this should be done once at the usb_set_configuration command, + * but the USB stack is a little bit stateless so we do it at every transaction + * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK + * in all other cases the state is left unchanged + * the ed info fields are setted anyway even though most of them should not change */ + +static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe) +{ + td_t *td; + ed_t *ed_ret; + volatile ed_t *ed; + + ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint (pipe) << 1) | + (usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))]; + + if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) { + err("ep_add_ed: pending delete"); + /* pending delete request */ + return NULL; + } + + if (ed->state == ED_NEW) { + ed->hwINFO = m32_swap (OHCI_ED_SKIP); /* skip ed */ + /* dummy td; end of td list for ed */ + td = td_alloc (usb_dev); + ed->hwTailP = m32_swap (td); + ed->hwHeadP = ed->hwTailP; + ed->state = ED_UNLINK; + ed->type = usb_pipetype (pipe); + ohci_dev.ed_cnt++; + } + + ed->hwINFO = m32_swap (usb_pipedevice (pipe) + | usb_pipeendpoint (pipe) << 7 + | (usb_pipeisoc (pipe)? 0x8000: 0) + | (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) + | usb_pipeslow (pipe) << 13 + | usb_maxpacket (usb_dev, pipe) << 16); + + return ed_ret; +} + +/*-------------------------------------------------------------------------* + * TD handling functions + *-------------------------------------------------------------------------*/ + +/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ + +static void td_fill (ohci_t *ohci, unsigned int info, + void *data, int len, + struct usb_device *dev, int index, urb_priv_t *urb_priv) +{ + volatile td_t *td, *td_pt; +#ifdef OHCI_FILL_TRACE + int i; +#endif + + if (index > urb_priv->length) { + err("index > length"); + return; + } + /* use this td as the next dummy */ + td_pt = urb_priv->td [index]; + td_pt->hwNextTD = 0; + + /* fill the old dummy TD */ + td = urb_priv->td [index] = (td_t *)(m32_swap (urb_priv->ed->hwTailP) & ~0xf); + + td->ed = urb_priv->ed; + td->next_dl_td = NULL; + td->index = index; + td->data = (__u32)data; +#ifdef OHCI_FILL_TRACE + if ((usb_pipetype(urb_priv->pipe) == PIPE_BULK) && usb_pipeout(urb_priv->pipe)) { + for (i = 0; i < len; i++) + printf("td->data[%d] %#2x ",i, ((unsigned char *)td->data)[i]); + printf("\n"); + } +#endif + if (!len) + data = 0; + + td->hwINFO = m32_swap (info); + td->hwCBP = m32_swap (data); + if (data) + td->hwBE = m32_swap (data + len - 1); + else + td->hwBE = 0; + td->hwNextTD = m32_swap (td_pt); + td->hwPSW [0] = m16_swap (((__u32)data & 0x0FFF) | 0xE000); + + /* append to queue */ + td->ed->hwTailP = td->hwNextTD; +} + +/*-------------------------------------------------------------------------*/ + +/* prepare all TDs of a transfer */ +static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup, urb_priv_t *urb, int interval) +{ + ohci_t *ohci = &gohci; + int data_len = transfer_len; + void *data; + int cnt = 0; + __u32 info = 0; + unsigned int toggle = 0; + + /* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */ + if(usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) { + toggle = TD_T_TOGGLE; + } else { + toggle = TD_T_DATA0; + usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 1); + } + urb->td_cnt = 0; + if (data_len) + data = buffer; + else + data = 0; + + switch (usb_pipetype (pipe)) { + case PIPE_BULK: + info = usb_pipeout (pipe)? + TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ; + while(data_len > 4096) { + td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, 4096, dev, cnt, urb); + data += 4096; data_len -= 4096; cnt++; + } + info = usb_pipeout (pipe)? + TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ; + td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, dev, cnt, urb); + cnt++; + + if (!ohci->sleeping) + writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ + break; + + case PIPE_CONTROL: + info = TD_CC | TD_DP_SETUP | TD_T_DATA0; + td_fill (ohci, info, setup, 8, dev, cnt++, urb); + if (data_len > 0) { + info = usb_pipeout (pipe)? + TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; + /* NOTE: mishandles transfers >8K, some >4K */ + td_fill (ohci, info, data, data_len, dev, cnt++, urb); + } + info = usb_pipeout (pipe)? + TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1; + td_fill (ohci, info, data, 0, dev, cnt++, urb); + if (!ohci->sleeping) + writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ + break; + } + if (urb->length != cnt) + dbg("TD LENGTH %d != CNT %d", urb->length, cnt); +} + +/*-------------------------------------------------------------------------* + * Done List handling functions + *-------------------------------------------------------------------------*/ +/* Hub class-specific descriptor is constructed dynamically */ + + +/*-------------------------------------------------------------------------*/ + +#define OK(x) len = (x); break +#ifdef DEBUG_USB_OHCI +#define WR_RH_STAT(x) {info("WR:status %#8x", (x));writel((x), &gohci.regs->roothub.status);} +#define WR_RH_PORTSTAT(x) {info("WR:portstatus[%d] %#8x", wIndex-1, (x));writel((x), &gohci.regs->roothub.portstatus[wIndex-1]);} +#else +#define WR_RH_STAT(x) writel((x), &gohci.regs->roothub.status) +#define WR_RH_PORTSTAT(x) writel((x), &gohci.regs->roothub.portstatus[wIndex-1]) +#endif +#define RD_RH_STAT roothub_status(&gohci) +#define RD_RH_PORTSTAT roothub_portstatus(&gohci,wIndex-1) + +/* request to virtual root hub */ + +int rh_check_port_status(ohci_t *controller) +{ + return 0; +} + + /*-------------------------------------------------------------------------*/ + +/* common code for handling submit messages - used for all but root hub */ +/* accesses. */ +int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup, int interval) +{ + return 0; +} + +/* submit routines called from usb.c */ +int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len) +{ + info("submit_bulk_msg"); + return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0); +} + +int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup) +{ + return 0; +} + +int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, int interval) +{ + info("submit_int_msg"); + return -1; +} + +/*-------------------------------------------------------------------------* + * HC functions + *-------------------------------------------------------------------------*/ + +/* reset the HC and BUS */ +int usb_lowlevel_init(int index, void **controller) +{ + return 0; +} + +int usb_lowlevel_stop(int index) +{ + return 0; +} + +#endif /* CONFIG_USB_OHCI */ diff --git a/drivers/usb/host/usb_ohci.h b/drivers/usb/host/usb_ohci.h new file mode 100644 index 000000000..cadef9e22 --- /dev/null +++ b/drivers/usb/host/usb_ohci.h @@ -0,0 +1,397 @@ +/* + * URB OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> + * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net> + * + * usb-ohci.h + */ + +#include <asm/byteorder.h> + +/* ED States */ +#define ED_NEW 0x00 +#define ED_UNLINK 0x01 +#define ED_OPER 0x02 +#define ED_DEL 0x04 +#define ED_URB_DEL 0x08 + +/* usb_ohci_ed */ +struct ed { + __u32 hwINFO; + __u32 hwTailP; + __u32 hwHeadP; + __u32 hwNextED; + + struct ed *ed_prev; + __u8 int_period; + __u8 int_branch; + __u8 int_load; + __u8 int_interval; + __u8 state; + __u8 type; + __u16 last_iso; + struct ed *ed_rm_list; + + struct usb_device *usb_dev; + __u32 unused[3]; +} __attribute((aligned(16))); +typedef struct ed ed_t; + + +/* TD info field */ +#define TD_CC 0xf0000000 +#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) +#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28) +#define TD_EC 0x0C000000 +#define TD_T 0x03000000 +#define TD_T_DATA0 0x02000000 +#define TD_T_DATA1 0x03000000 +#define TD_T_TOGGLE 0x00000000 +#define TD_R 0x00040000 +#define TD_DI 0x00E00000 +#define TD_DI_SET(X) (((X) & 0x07)<< 21) +#define TD_DP 0x00180000 +#define TD_DP_SETUP 0x00000000 +#define TD_DP_IN 0x00100000 +#define TD_DP_OUT 0x00080000 + +#define TD_ISO 0x00010000 +#define TD_DEL 0x00020000 + +/* CC Codes */ +#define TD_CC_NOERROR 0x00 +#define TD_CC_CRC 0x01 +#define TD_CC_BITSTUFFING 0x02 +#define TD_CC_DATATOGGLEM 0x03 +#define TD_CC_STALL 0x04 +#define TD_DEVNOTRESP 0x05 +#define TD_PIDCHECKFAIL 0x06 +#define TD_UNEXPECTEDPID 0x07 +#define TD_DATAOVERRUN 0x08 +#define TD_DATAUNDERRUN 0x09 +#define TD_BUFFEROVERRUN 0x0C +#define TD_BUFFERUNDERRUN 0x0D +#define TD_NOTACCESSED 0x0F + + +#define MAXPSW 1 + +struct td { + __u32 hwINFO; + __u32 hwCBP; /* Current Buffer Pointer */ + __u32 hwNextTD; /* Next TD Pointer */ + __u32 hwBE; /* Memory Buffer End Pointer */ + + __u16 hwPSW[MAXPSW]; + __u8 unused; + __u8 index; + struct ed *ed; + struct td *next_dl_td; + struct usb_device *usb_dev; + int transfer_len; + __u32 data; + + __u32 unused2[2]; +} __attribute((aligned(32))); +typedef struct td td_t; + +#define OHCI_ED_SKIP (1 << 14) + +/* + * The HCCA (Host Controller Communications Area) is a 256 byte + * structure defined in the OHCI spec. that the host controller is + * told the base address of. It must be 256-byte aligned. + */ + +#define NUM_INTS 32 /* part of the OHCI standard */ +struct ohci_hcca { + __u32 int_table[NUM_INTS]; /* Interrupt ED table */ + __u16 frame_no; /* current frame number */ + __u16 pad1; /* set to 0 on each frame_no change */ + __u32 done_head; /* info returned for an interrupt */ + u8 reserved_for_hc[116]; +} __attribute((aligned(256))); + + +/* + * Maximum number of root hub ports. + */ +#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */ + +/* + * This is the structure of the OHCI controller's memory mapped I/O + * region. This is Memory Mapped I/O. You must use the readl() and + * writel() macros defined in asm/io.h to access these!! + */ +struct ohci_regs { + /* control and status registers */ + __u32 revision; + __u32 control; + __u32 cmdstatus; + __u32 intrstatus; + __u32 intrenable; + __u32 intrdisable; + /* memory pointers */ + __u32 hcca; + __u32 ed_periodcurrent; + __u32 ed_controlhead; + __u32 ed_controlcurrent; + __u32 ed_bulkhead; + __u32 ed_bulkcurrent; + __u32 donehead; + /* frame counters */ + __u32 fminterval; + __u32 fmremaining; + __u32 fmnumber; + __u32 periodicstart; + __u32 lsthresh; + /* Root hub ports */ + struct ohci_roothub_regs { + __u32 a; + __u32 b; + __u32 status; + __u32 portstatus[MAX_ROOT_PORTS]; + } roothub; +} __attribute((aligned(32))); + + +/* OHCI CONTROL AND STATUS REGISTER MASKS */ + +/* + * HcControl (control) register masks + */ +#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */ +#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */ +#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */ +#define OHCI_CTRL_CLE (1 << 4) /* control list enable */ +#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */ +#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */ +#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ +#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ +#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */ + +/* pre-shifted values for HCFS */ +# define OHCI_USB_RESET (0 << 6) +# define OHCI_USB_RESUME (1 << 6) +# define OHCI_USB_OPER (2 << 6) +# define OHCI_USB_SUSPEND (3 << 6) + +/* + * HcCommandStatus (cmdstatus) register masks + */ +#define OHCI_HCR (1 << 0) /* host controller reset */ +#define OHCI_CLF (1 << 1) /* control list filled */ +#define OHCI_BLF (1 << 2) /* bulk list filled */ +#define OHCI_OCR (1 << 3) /* ownership change request */ +#define OHCI_SOC (3 << 16) /* scheduling overrun count */ + +/* + * masks used with interrupt registers: + * HcInterruptStatus (intrstatus) + * HcInterruptEnable (intrenable) + * HcInterruptDisable (intrdisable) + */ +#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */ +#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */ +#define OHCI_INTR_SF (1 << 2) /* start frame */ +#define OHCI_INTR_RD (1 << 3) /* resume detect */ +#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */ +#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */ +#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */ +#define OHCI_INTR_OC (1 << 30) /* ownership change */ +#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */ + + +/* Virtual Root HUB */ +struct virt_root_hub { + int devnum; /* Address of Root Hub endpoint */ + void *dev; /* was urb */ + void *int_addr; + int send; + int interval; +}; + +/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */ + +/* destination of request */ +#define RH_INTERFACE 0x01 +#define RH_ENDPOINT 0x02 +#define RH_OTHER 0x03 + +#define RH_CLASS 0x20 +#define RH_VENDOR 0x40 + +/* Requests: bRequest << 8 | bmRequestType */ +#define RH_GET_STATUS 0x0080 +#define RH_CLEAR_FEATURE 0x0100 +#define RH_SET_FEATURE 0x0300 +#define RH_SET_ADDRESS 0x0500 +#define RH_GET_DESCRIPTOR 0x0680 +#define RH_SET_DESCRIPTOR 0x0700 +#define RH_GET_CONFIGURATION 0x0880 +#define RH_SET_CONFIGURATION 0x0900 +#define RH_GET_STATE 0x0280 +#define RH_GET_INTERFACE 0x0A80 +#define RH_SET_INTERFACE 0x0B00 +#define RH_SYNC_FRAME 0x0C80 +/* Our Vendor Specific Request */ +#define RH_SET_EP 0x2000 + + +/* Hub port features */ +#define RH_PORT_CONNECTION 0x00 +#define RH_PORT_ENABLE 0x01 +#define RH_PORT_SUSPEND 0x02 +#define RH_PORT_OVER_CURRENT 0x03 +#define RH_PORT_RESET 0x04 +#define RH_PORT_POWER 0x08 +#define RH_PORT_LOW_SPEED 0x09 + +#define RH_C_PORT_CONNECTION 0x10 +#define RH_C_PORT_ENABLE 0x11 +#define RH_C_PORT_SUSPEND 0x12 +#define RH_C_PORT_OVER_CURRENT 0x13 +#define RH_C_PORT_RESET 0x14 + +/* Hub features */ +#define RH_C_HUB_LOCAL_POWER 0x00 +#define RH_C_HUB_OVER_CURRENT 0x01 + +#define RH_DEVICE_REMOTE_WAKEUP 0x00 +#define RH_ENDPOINT_STALL 0x01 + +#define RH_ACK 0x01 +#define RH_REQ_ERR -1 +#define RH_NACK 0x00 + + +/* OHCI ROOT HUB REGISTER MASKS */ + +/* roothub.portstatus [i] bits */ +#define RH_PS_CCS 0x00000001 /* current connect status */ +#define RH_PS_PES 0x00000002 /* port enable status*/ +#define RH_PS_PSS 0x00000004 /* port suspend status */ +#define RH_PS_POCI 0x00000008 /* port over current indicator */ +#define RH_PS_PRS 0x00000010 /* port reset status */ +#define RH_PS_PPS 0x00000100 /* port power status */ +#define RH_PS_LSDA 0x00000200 /* low speed device attached */ +#define RH_PS_CSC 0x00010000 /* connect status change */ +#define RH_PS_PESC 0x00020000 /* port enable status change */ +#define RH_PS_PSSC 0x00040000 /* port suspend status change */ +#define RH_PS_OCIC 0x00080000 /* over current indicator change */ +#define RH_PS_PRSC 0x00100000 /* port reset status change */ + +/* roothub.status bits */ +#define RH_HS_LPS 0x00000001 /* local power status */ +#define RH_HS_OCI 0x00000002 /* over current indicator */ +#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ +#define RH_HS_LPSC 0x00010000 /* local power status change */ +#define RH_HS_OCIC 0x00020000 /* over current indicator change */ +#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ + +/* roothub.b masks */ +#define RH_B_DR 0x0000ffff /* device removable flags */ +#define RH_B_PPCM 0xffff0000 /* port power control mask */ + +/* roothub.a masks */ +#define RH_A_NDP (0xff << 0) /* number of downstream ports */ +#define RH_A_PSM (1 << 8) /* power switching mode */ +#define RH_A_NPS (1 << 9) /* no power switching */ +#define RH_A_DT (1 << 10) /* device type (mbz) */ +#define RH_A_OCPM (1 << 11) /* over current protection mode */ +#define RH_A_NOCP (1 << 12) /* no over current protection */ +#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ + +/* urb */ +#define N_URB_TD 48 +typedef struct +{ + ed_t *ed; + __u16 length; /* number of tds associated with this request */ + __u16 td_cnt; /* number of tds already serviced */ + int state; + unsigned long pipe; + int actual_length; + td_t *td[N_URB_TD]; /* list pointer to all corresponding TDs associated with this request */ +} urb_priv_t; +#define URB_DEL 1 + +/* + * This is the full ohci controller description + * + * Note how the "proper" USB information is just + * a subset of what the full implementation needs. (Linus) + */ + + +typedef struct ohci { + struct ohci_hcca *hcca; /* hcca */ + /*dma_addr_t hcca_dma;*/ + + int irq; + int disabled; /* e.g. got a UE, we're hung */ + int sleeping; + unsigned long flags; /* for HC bugs */ + + struct ohci_regs *regs; /* OHCI controller's memory */ + + ed_t *ed_rm_list[2]; /* lists of all endpoints to be removed */ + ed_t *ed_bulktail; /* last endpoint of bulk list */ + ed_t *ed_controltail; /* last endpoint of control list */ + int intrstatus; + __u32 hc_control; /* copy of the hc control reg */ + struct usb_device *dev[32]; + struct virt_root_hub rh; + + const char *slot_name; +} ohci_t; + +#define NUM_EDS 8 /* num of preallocated endpoint descriptors */ + +struct ohci_device { + ed_t ed[NUM_EDS]; + int ed_cnt; +}; + +/* hcd */ +/* endpoint */ +static int ep_link(ohci_t * ohci, ed_t * ed); +static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned long pipe); + +/*-------------------------------------------------------------------------*/ + +/* we need more TDs than EDs */ +#define NUM_TD 64 + +/* +1 so we can align the storage */ +td_t gtd[NUM_TD+1]; +/* pointers to aligned storage */ +td_t *ptd; + +/* TDs ... */ +static inline struct td * +td_alloc (struct usb_device *usb_dev) +{ + int i; + struct td *td; + + td = NULL; + for (i = 0; i < NUM_TD; i++) + { + if (ptd[i].usb_dev == NULL) + { + td = &ptd[i]; + td->usb_dev = usb_dev; + break; + } + } + + return td; +} + +static inline void +ed_free (struct ed *ed) +{ + ed->usb_dev = NULL; +} diff --git a/include/configs/origen_quad.h b/include/configs/origen_quad.h index 7e39ee1d3..4e09359a6 100644 --- a/include/configs/origen_quad.h +++ b/include/configs/origen_quad.h @@ -30,6 +30,7 @@ /* * High Level Configuration Options */ +#define CONFIG_CMD_BOOTZ #define CONFIG_SAMSUNG /* in a SAMSUNG core */ #define CONFIG_S5P /* S5P Family */ #define CONFIG_EXYNOS4 /* which is in a Exynos4 series */ @@ -39,6 +40,15 @@ #define CONFIG_IDENT_STRING " for Insignal Origen" #define CONFIG_MACH_TYPE 3455 +#define CONFIG_ARMV7 1 /* This is an ARM V7 CPU core */ +#define CONFIG_CPU_EXYNOS4X12 1 /* which is in a Exynos4X12 */ +#define CONFIG_S5PC210 1 /* which is in a S5PC210 */ +#define CONFIG_S5PC220 1 /* which is in a S5PC220 */ +#define CONFIG_SMDKC210 1 +#define CONFIG_SMDKC220 1 +#define CONFIG_EXYNOS4212 1 +#define CONFIG_EXYNOS4412_EVT1 1 + #include <asm/arch/cpu.h> /* get chip and board defs */ /* @@ -144,7 +154,6 @@ #include <config_cmd_default.h> #undef CONFIG_CMD_NET #undef CONFIG_CMD_NFS - /* * Environment */ @@ -179,5 +188,13 @@ #define CONFIG_OF_LIBFDT /* Boot Argument Buffer Size */ #define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE +/* USB Options */ +#define CONFIG_CMD_USB +#ifdef CONFIG_CMD_USB +#define CONFIG_USB_OHCI +#define CONFIG_S3C_USBD +#define USBD_DOWN_ADDR 0xC0000000 +#endif +#define CONFIG_OF_LIBFDT -#endif /* __CONFIG_ORIGEN_QUAD_H */ +#endif |