U-Boot
Threads by month
- ----- 2025 -----
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2000 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
February 2014
- 171 participants
- 544 discussions
Implement env_export() wrapper, so that all implementers of saveenv() don't
have to call hexport_r(), crc32() etc. sequence . This trims down a bit of
code duplication.
Signed-off-by: Marek Vasut <marex(a)denx.de>
---
common/env_common.c | 17 +++++++++++++++++
common/env_dataflash.c | 17 ++++++-----------
common/env_eeprom.c | 12 +++---------
common/env_fat.c | 12 +++---------
common/env_flash.c | 21 ++++++---------------
common/env_mmc.c | 12 ++----------
common/env_nand.c | 13 ++++---------
common/env_nvram.c | 12 +++---------
common/env_onenand.c | 13 ++++---------
common/env_sf.c | 24 +++++++-----------------
common/env_ubi.c | 27 ++++++++-------------------
include/environment.h | 3 +++
12 files changed, 66 insertions(+), 117 deletions(-)
diff --git a/common/env_common.c b/common/env_common.c
index c0bfc2f..fe35ff4 100644
--- a/common/env_common.c
+++ b/common/env_common.c
@@ -172,6 +172,23 @@ int env_import(const char *buf, int check)
return 0;
}
+/* Emport the environment and generate CRC for it. */
+int env_export(env_t *env_out)
+{
+ char *res;
+ ssize_t len;
+
+ res = (char *)env_out->data;
+ len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
+ if (len < 0) {
+ error("Cannot export environment: errno = %d\n", errno);
+ return 1;
+ }
+ env_out->crc = crc32(0, env_out->data, ENV_SIZE);
+
+ return 0;
+}
+
void env_relocate(void)
{
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
diff --git a/common/env_dataflash.c b/common/env_dataflash.c
index b53b87e..034e323 100644
--- a/common/env_dataflash.c
+++ b/common/env_dataflash.c
@@ -56,17 +56,12 @@ void env_relocate_spec(void)
int saveenv(void)
{
- env_t env_new;
- ssize_t len;
- char *res;
-
- res = (char *)&env_new.data;
- len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
- if (len < 0) {
- error("Cannot export environment: errno = %d\n", errno);
- return 1;
- }
- env_new.crc = crc32(0, env_new.data, ENV_SIZE);
+ env_t env_new;
+ int ret;
+
+ ret = env_export(&env_new);
+ if (ret)
+ return ret;
return write_dataflash(CONFIG_ENV_ADDR,
(unsigned long)&env_new,
diff --git a/common/env_eeprom.c b/common/env_eeprom.c
index 0db2bb6..490ac73 100644
--- a/common/env_eeprom.c
+++ b/common/env_eeprom.c
@@ -98,8 +98,6 @@ void env_relocate_spec(void)
int saveenv(void)
{
env_t env_new;
- ssize_t len;
- char *res;
int rc;
unsigned int off = CONFIG_ENV_OFFSET;
#ifdef CONFIG_ENV_OFFSET_REDUND
@@ -109,13 +107,9 @@ int saveenv(void)
BUG_ON(env_ptr != NULL);
- res = (char *)&env_new.data;
- len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
- if (len < 0) {
- error("Cannot export environment: errno = %d\n", errno);
- return 1;
- }
- env_new.crc = crc32(0, env_new.data, ENV_SIZE);
+ rc = env_export(&env_new);
+ if (rc)
+ return rc;
#ifdef CONFIG_ENV_OFFSET_REDUND
if (gd->env_valid == 1) {
diff --git a/common/env_fat.c b/common/env_fat.c
index 708fd13..aad0487 100644
--- a/common/env_fat.c
+++ b/common/env_fat.c
@@ -37,19 +37,14 @@ int env_init(void)
int saveenv(void)
{
env_t env_new;
- ssize_t len;
- char *res;
block_dev_desc_t *dev_desc = NULL;
int dev = FAT_ENV_DEVICE;
int part = FAT_ENV_PART;
int err;
- res = (char *)&env_new.data;
- len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
- if (len < 0) {
- error("Cannot export environment: errno = %d\n", errno);
- return 1;
- }
+ err = env_export(&env_new);
+ if (err)
+ return err;
#ifdef CONFIG_MMC
if (strcmp(FAT_ENV_INTERFACE, "mmc") == 0) {
@@ -79,7 +74,6 @@ int saveenv(void)
return 1;
}
- env_new.crc = crc32(0, env_new.data, ENV_SIZE);
err = file_fat_write(FAT_ENV_FILE, (void *)&env_new, sizeof(env_t));
if (err == -1) {
printf("\n** Unable to write \"%s\" from %s%d:%d **\n",
diff --git a/common/env_flash.c b/common/env_flash.c
index 7d5a4cf..b3ad908 100644
--- a/common/env_flash.c
+++ b/common/env_flash.c
@@ -106,8 +106,7 @@ int env_init(void)
int saveenv(void)
{
env_t env_new;
- ssize_t len;
- char *res, *saved_data = NULL;
+ char *saved_data = NULL;
char flag = OBSOLETE_FLAG, new_flag = ACTIVE_FLAG;
int rc = 1;
#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
@@ -125,13 +124,9 @@ int saveenv(void)
if (flash_sect_protect(0, (ulong)flash_addr_new, end_addr_new))
goto done;
- res = (char *)&env_new.data;
- len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
- if (len < 0) {
- error("Cannot export environment: errno = %d\n", errno);
- goto done;
- }
- env_new.crc = crc32(0, env_new.data, ENV_SIZE);
+ rc = env_export(&env_new);
+ if (rc)
+ return rc;
env_new.flags = new_flag;
#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
@@ -258,13 +253,9 @@ int saveenv(void)
if (flash_sect_protect(0, (long)flash_addr, end_addr))
goto done;
- res = (char *)&env_new.data;
- len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
- if (len < 0) {
- error("Cannot export environment: errno = %d\n", errno);
+ rc = env_export(&env_new);
+ if (rc)
goto done;
- }
- env_new.crc = crc32(0, env_new.data, ENV_SIZE);
puts("Erasing Flash...");
if (flash_sect_erase((long)flash_addr, end_addr))
diff --git a/common/env_mmc.c b/common/env_mmc.c
index 045428c..c99fc75 100644
--- a/common/env_mmc.c
+++ b/common/env_mmc.c
@@ -118,8 +118,6 @@ static unsigned char env_flags;
int saveenv(void)
{
ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
- ssize_t len;
- char *res;
struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
u32 offset;
int ret, copy = 0;
@@ -127,15 +125,9 @@ int saveenv(void)
if (init_mmc_for_env(mmc))
return 1;
- res = (char *)&env_new->data;
- len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
- if (len < 0) {
- error("Cannot export environment: errno = %d\n", errno);
- ret = 1;
+ ret = env_export(env_new);
+ if (ret)
goto fini;
- }
-
- env_new->crc = crc32(0, &env_new->data[0], ENV_SIZE);
#ifdef CONFIG_ENV_OFFSET_REDUND
env_new->flags = ++env_flags; /* increase the serial */
diff --git a/common/env_nand.c b/common/env_nand.c
index 695a9ee..b94545d 100644
--- a/common/env_nand.c
+++ b/common/env_nand.c
@@ -181,8 +181,6 @@ int saveenv(void)
{
int ret = 0;
ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
- ssize_t len;
- char *res;
int env_idx = 0;
static const struct env_location location[] = {
{
@@ -207,13 +205,10 @@ int saveenv(void)
if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE)
return 1;
- res = (char *)&env_new->data;
- len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
- if (len < 0) {
- error("Cannot export environment: errno = %d\n", errno);
- return 1;
- }
- env_new->crc = crc32(0, env_new->data, ENV_SIZE);
+ ret = env_export(&env_new);
+ if (ret)
+ return ret;
+
#ifdef CONFIG_ENV_OFFSET_REDUND
env_new->flags = ++env_flags; /* increase the serial */
env_idx = (gd->env_valid == 1);
diff --git a/common/env_nvram.c b/common/env_nvram.c
index 0866cde..524f07d 100644
--- a/common/env_nvram.c
+++ b/common/env_nvram.c
@@ -69,17 +69,11 @@ void env_relocate_spec(void)
int saveenv(void)
{
env_t env_new;
- ssize_t len;
- char *res;
int rcode = 0;
- res = (char *)&env_new.data;
- len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
- if (len < 0) {
- error("Cannot export environment: errno = %d\n", errno);
- return 1;
- }
- env_new.crc = crc32(0, env_new.data, ENV_SIZE);
+ rcode = env_export(&env_new);
+ if (rcode)
+ return rcode;
#ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE
nvram_write(CONFIG_ENV_ADDR, &env_new, CONFIG_ENV_SIZE);
diff --git a/common/env_onenand.c b/common/env_onenand.c
index 4b44632..cc3d670 100644
--- a/common/env_onenand.c
+++ b/common/env_onenand.c
@@ -66,8 +66,7 @@ void env_relocate_spec(void)
int saveenv(void)
{
env_t env_new;
- ssize_t len;
- char *res;
+ int ret;
struct mtd_info *mtd = &onenand_mtd;
#ifdef CONFIG_ENV_ADDR_FLEX
struct onenand_chip *this = &onenand_chip;
@@ -78,13 +77,9 @@ int saveenv(void)
.callback = NULL,
};
- res = (char *)&env_new.data;
- len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
- if (len < 0) {
- error("Cannot export environment: errno = %d\n", errno);
- return 1;
- }
- env_new.crc = crc32(0, env_new.data, ENV_SIZE);
+ ret = env_export(&env_new);
+ if (ret)
+ return ret;
instr.len = CONFIG_ENV_SIZE;
#ifdef CONFIG_ENV_ADDR_FLEX
diff --git a/common/env_sf.c b/common/env_sf.c
index 9f806fb..3395684 100644
--- a/common/env_sf.c
+++ b/common/env_sf.c
@@ -47,8 +47,7 @@ static struct spi_flash *env_flash;
int saveenv(void)
{
env_t env_new;
- ssize_t len;
- char *res, *saved_buffer = NULL, flag = OBSOLETE_FLAG;
+ char *saved_buffer = NULL, flag = OBSOLETE_FLAG;
u32 saved_size, saved_offset, sector = 1;
int ret;
@@ -62,13 +61,9 @@ int saveenv(void)
}
}
- res = (char *)&env_new.data;
- len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
- if (len < 0) {
- error("Cannot export environment: errno = %d\n", errno);
- return 1;
- }
- env_new.crc = crc32(0, env_new.data, ENV_SIZE);
+ ret = env_export(&env_new);
+ if (ret)
+ return ret;
env_new.flags = ACTIVE_FLAG;
if (gd->env_valid == 1) {
@@ -225,10 +220,9 @@ out:
int saveenv(void)
{
u32 saved_size, saved_offset, sector = 1;
- char *res, *saved_buffer = NULL;
+ char *saved_buffer = NULL;
int ret = 1;
env_t env_new;
- ssize_t len;
if (!env_flash) {
env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS,
@@ -260,13 +254,9 @@ int saveenv(void)
sector++;
}
- res = (char *)&env_new.data;
- len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
- if (len < 0) {
- error("Cannot export environment: errno = %d\n", errno);
+ ret = env_export(&env_new);
+ if (ret)
goto done;
- }
- env_new.crc = crc32(0, env_new.data, ENV_SIZE);
puts("Erasing SPI flash...");
ret = spi_flash_erase(env_flash, CONFIG_ENV_OFFSET,
diff --git a/common/env_ubi.c b/common/env_ubi.c
index c0828a4..77bbfa6 100644
--- a/common/env_ubi.c
+++ b/common/env_ubi.c
@@ -37,15 +37,11 @@ static unsigned char env_flags;
int saveenv(void)
{
ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
- ssize_t len;
- char *res;
+ int ret;
- res = (char *)&env_new->data;
- len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
- if (len < 0) {
- error("Cannot export environment: errno = %d\n", errno);
- return 1;
- }
+ ret = env_export(env_new);
+ if (ret)
+ return ret;
if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) {
printf("\n** Cannot find mtd partition \"%s\"\n",
@@ -53,7 +49,6 @@ int saveenv(void)
return 1;
}
- env_new->crc = crc32(0, env_new->data, ENV_SIZE);
env_new->flags = ++env_flags; /* increase the serial */
if (gd->env_valid == 1) {
@@ -86,15 +81,11 @@ int saveenv(void)
int saveenv(void)
{
ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
- ssize_t len;
- char *res;
+ int ret;
- res = (char *)&env_new->data;
- len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
- if (len < 0) {
- error("Cannot export environment: errno = %d\n", errno);
- return 1;
- }
+ ret = env_export(env_new);
+ if (ret)
+ return ret;
if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) {
printf("\n** Cannot find mtd partition \"%s\"\n",
@@ -102,8 +93,6 @@ int saveenv(void)
return 1;
}
- env_new->crc = crc32(0, env_new->data, ENV_SIZE);
-
if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, (void *)env_new,
CONFIG_ENV_SIZE)) {
printf("\n** Unable to write env to %s:%s **\n",
diff --git a/include/environment.h b/include/environment.h
index 46a3554..f797595 100644
--- a/include/environment.h
+++ b/include/environment.h
@@ -201,6 +201,9 @@ int set_default_vars(int nvars, char * const vars[]);
/* Import from binary representation into hash table */
int env_import(const char *buf, int check);
+/* Export from hash table into binary representation */
+int env_export(env_t *env_out);
+
#endif /* DO_DEPS_ONLY */
#endif /* _ENVIRONMENT_H_ */
--
1.8.5.3
2
5
I followed the following commands to achieve a successful booting of i.mx6
board using SD card
dd if=u-boot.imx of=/dev/sdb bs=1k seek=1
The above command burnt the u-boot.imx image on the SD card though nothing
was seen on SD card.
Next the gtkterm configurations were set and after the board was started
serial console output was interrupted(by pressing a key).
U-Boot>> sf probe (to probe the flash memory)
U-Boot>> sf erase 0 0x80000 (to erase the flash)
U-Boot>>fatload mmc 1 12000000 u-boot.imx
The above command throws an error -"Unable to read file u-boot.imx"
SO what can be the problem behind it and how can we overcome it?
2
1
Hi ,
I am new to u-boot code. I had a requirement for running memory, cpu and
cache tests as part of diagnostics, on an ARM based platform. After
going through the code, I found that only PPC variants are available for
cpu and cache post tests.
Please help me...
Thanks,
shobin.b
1
0

06 Feb '14
From: rick <rick(a)andestech.com>
can not execute get_ram_size(), because the
text/data will be corrupted by itself
in specific case.
Signed-off-by: rick <rick(a)andestech.com>
Cc: Andes <uboot(a)andestech.com>
---
board/AndesTech/adp-ag101p/adp-ag101p.c | 18 +++++++-----------
1 files changed, 7 insertions(+), 11 deletions(-)
diff --git a/board/AndesTech/adp-ag101p/adp-ag101p.c b/board/AndesTech/adp-ag101p/adp-ag101p.c
index dd8a6653..9866431 100644
--- a/board/AndesTech/adp-ag101p/adp-ag101p.c
+++ b/board/AndesTech/adp-ag101p/adp-ag101p.c
@@ -34,18 +34,14 @@ int board_init(void)
int dram_init(void)
{
- unsigned long sdram_base = PHYS_SDRAM_0;
- unsigned long expected_size = PHYS_SDRAM_0_SIZE + PHYS_SDRAM_1_SIZE;
- unsigned long actual_size;
-
- actual_size = get_ram_size((void *)sdram_base, expected_size);
-
- gd->ram_size = actual_size;
+ /*
+ * can not execute get_ram_size(), because the
+ * text will be corrupted by itself
+ * in specific case
+ */
- if (expected_size != actual_size) {
- printf("Warning: Only %lu of %lu MiB SDRAM is working\n",
- actual_size >> 20, expected_size >> 20);
- }
+ unsigned long expected_size = PHYS_SDRAM_0_SIZE + PHYS_SDRAM_1_SIZE;
+ gd->ram_size = expected_size;
return 0;
}
--
1.7.6
2
1
Hi,
I am trying to get u-boot snow (2014.01) running on a chromebook ARM (chainloaded u-boot).
It seems to be running because if I enter the 'reset' command, then it reboots.
But the problem is I only have a black screen, a white flash and again the black screen.
Is it expected that LCD stay black?
Are there any patches pending?
Guillaume
1
0

06 Feb '14
This patch series comprises several improvements for Exynos4 USB code.
The most notable is transmission speed improvement (measured on Trats):
From: 9.51 MiB/s up to 27 MiB/s
This is due to UDC driver optimizations.
Also a code cleanup for THOR gadget has been included.
Lukasz Majewski (6):
usb:gadget:ums: Replace malloc calls with memalign to fix cache
buffer alignment
usb:udc:samsung: Remove redundant cache operation from Samsung UDC
driver
usb:udc:samsung: Allow burst transfers for non EP0 endpints
usb:udc:samsung: Zero copy approach for data passed to Samsung's UDC
driver
usb:gadget:f_thor: Allocate request up to THOR_PACKET_SIZE not
ep->maxpacket
usb:gadget:f_thor: cosmetic: Remove debug memset
drivers/usb/gadget/f_mass_storage.c | 4 +-
drivers/usb/gadget/f_thor.c | 4 +-
drivers/usb/gadget/s3c_udc_otg.c | 19 ++++----
drivers/usb/gadget/s3c_udc_otg_xfer_dma.c | 74 ++++++++++-------------------
include/usb/s3c_udc.h | 5 +-
5 files changed, 38 insertions(+), 68 deletions(-)
--
1.7.10.4
3
35

06 Feb '14
From: Oleksandr Tymoshenko <gonzo(a)bluezbox.com>
This is the USB host controller used on the Raspbery Pi.
swarren changelog:
* Fixed prototype of usb_lowlevel_init() to match upstream change.
* Fixed a number of unused variable warnings.
* Replaced license headers with SPDX tags.
* Renamed files DWC -> DWC2 to make it clear which HW it's for.
* Many hundreds of checkpatch fixes.
Signed-off-by: Oleksandr Tymoshenko <gonzo(a)bluezbox.com>
Signed-off-by: Stephen Warren <swarren(a)wwdotorg.org>
---
I've fixed all the checkpatch errors. There are hundreds of warnings left.
Still, I figured it was a good idea to post the patch for review of any
other aspects.
---
drivers/usb/host/Makefile | 2 +
drivers/usb/host/dwc2_otg-hcd.c | 730 ++++++++++++
drivers/usb/host/dwc2_otg.c | 2179 +++++++++++++++++++++++++++++++++++
drivers/usb/host/dwc2_otg.h | 130 +++
drivers/usb/host/dwc2_otg_core_if.h | 1001 ++++++++++++++++
drivers/usb/host/dwc2_otg_regs.h | 1625 ++++++++++++++++++++++++++
include/usb.h | 3 +-
7 files changed, 5669 insertions(+), 1 deletion(-)
create mode 100644 drivers/usb/host/dwc2_otg-hcd.c
create mode 100644 drivers/usb/host/dwc2_otg.c
create mode 100644 drivers/usb/host/dwc2_otg.h
create mode 100644 drivers/usb/host/dwc2_otg_core_if.h
create mode 100644 drivers/usb/host/dwc2_otg_regs.h
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 1417028..75bd615 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -42,3 +42,5 @@ obj-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o
obj-$(CONFIG_USB_XHCI) += xhci.o xhci-mem.o xhci-ring.o
obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o
obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o
+
+obj-$(CONFIG_USB_DWC2_OTG) += dwc2_otg.o dwc2_otg-hcd.o
diff --git a/drivers/usb/host/dwc2_otg-hcd.c b/drivers/usb/host/dwc2_otg-hcd.c
new file mode 100644
index 0000000..c7d45c7
--- /dev/null
+++ b/drivers/usb/host/dwc2_otg-hcd.c
@@ -0,0 +1,730 @@
+/*
+ * Copyright (C) 2012 Oleksandr Tymoshenko <gonzo(a)freebsd.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <usb.h>
+#include <malloc.h>
+#include "dwc2_otg.h"
+#include "dwc2_otg_regs.h"
+#include "dwc2_otg_core_if.h"
+
+#define STATUS_ACK_HLT_COMPL 0x23
+#define CHANNEL 0
+
+#define DWC_OTG_HCD_STATUS_BUF_SIZE 64
+#define DWC_OTG_HCD_DATA_BUF_SIZE (64 * 1024)
+
+static int root_hub_devnum;
+
+static uint8_t *allocated_buffer;
+static uint8_t *aligned_buffer;
+static uint8_t *status_buffer;
+
+static dwc_otg_core_if_t g_core_if;
+
+#define MAX_DEVICE 16
+#define MAX_ENDPOINT 8
+int bulk_data_toggle[MAX_DEVICE][MAX_ENDPOINT];
+int control_data_toggle[MAX_DEVICE][MAX_ENDPOINT];
+
+void do_hang(int line, uint32_t d)
+{
+ printf("DWC OTG: hang at line %d: %08x\n", line, d);
+ while (1)
+ udelay(10);
+}
+
+void handle_error(int line, uint32_t d)
+{
+ hcint_data_t hcint;
+ hcint.d32 = d;
+
+ printf("Error condition at line %d: ", line);
+ if (hcint.b.ahberr)
+ printf(" AHBERR");
+ if (hcint.b.stall)
+ printf(" STALL");
+ if (hcint.b.bblerr)
+ printf(" NAK");
+ if (hcint.b.ack)
+ printf(" ACK");
+ if (hcint.b.nyet)
+ printf(" NYET");
+ if (hcint.b.xacterr)
+ printf(" XACTERR");
+ if (hcint.b.datatglerr)
+ printf(" DATATGLERR");
+ printf("\n");
+}
+
+/*
+ * U-Boot USB interface
+ */
+int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
+{
+ /*
+ * We need doubleword-aligned buffers for DMA transfers
+ */
+ allocated_buffer = (uint8_t *)malloc(DWC_OTG_HCD_STATUS_BUF_SIZE + DWC_OTG_HCD_DATA_BUF_SIZE + 8);
+ uint32_t addr = (uint32_t)allocated_buffer;
+ aligned_buffer = (uint8_t *) ((addr + 7) & ~7);
+ status_buffer = (uint8_t *)((uint32_t)aligned_buffer + DWC_OTG_HCD_DATA_BUF_SIZE);
+ int i, j;
+ hprt0_data_t hprt0 = {.d32 = 0 };
+
+ root_hub_devnum = 0;
+ memset(&g_core_if, 0, sizeof(g_core_if));
+ dwc_otg_cil_init(&g_core_if, (uint32_t *)0x20980000);
+
+ if ((g_core_if.snpsid & 0xFFFFF000) !=
+ 0x4F542000) {
+ printf("SNPSID is invalid (not DWC OTG device): %08x\n", g_core_if.snpsid);
+ return -1;
+ }
+
+ dwc_otg_core_init(&g_core_if);
+ dwc_otg_core_host_init(&g_core_if);
+
+ hprt0.d32 = dwc_otg_read_hprt0(&g_core_if);
+ hprt0.b.prtrst = 1;
+ dwc_write_reg32(g_core_if.host_if->hprt0, hprt0.d32);
+ udelay(50000);
+ hprt0.b.prtrst = 0;
+ dwc_write_reg32(g_core_if.host_if->hprt0, hprt0.d32);
+
+ udelay(50000);
+ hprt0.d32 = dwc_read_reg32(g_core_if.host_if->hprt0);
+
+ for (i = 0; i < MAX_DEVICE; i++) {
+ for (j = 0; j < MAX_ENDPOINT; j++) {
+ control_data_toggle[i][j] = DWC_OTG_HC_PID_DATA1;
+ bulk_data_toggle[i][j] = DWC_OTG_HC_PID_DATA0;
+ }
+ }
+
+ return 0;
+}
+
+int usb_lowlevel_stop(int index)
+{
+ free(allocated_buffer);
+
+ return 0;
+}
+
+/* based on usb_ohci.c */
+#define min_t(type, x, y) \
+ ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; })
+/*-------------------------------------------------------------------------*
+ * Virtual Root Hub
+ *-------------------------------------------------------------------------*/
+
+/* Device descriptor */
+static __u8 root_hub_dev_des[] = {
+ 0x12, /* __u8 bLength; */
+ 0x01, /* __u8 bDescriptorType; Device */
+ 0x10, /* __u16 bcdUSB; v1.1 */
+ 0x01,
+ 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 bDeviceSubClass; */
+ 0x00, /* __u8 bDeviceProtocol; */
+ 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
+ 0x00, /* __u16 idVendor; */
+ 0x00,
+ 0x00, /* __u16 idProduct; */
+ 0x00,
+ 0x00, /* __u16 bcdDevice; */
+ 0x00,
+ 0x01, /* __u8 iManufacturer; */
+ 0x02, /* __u8 iProduct; */
+ 0x00, /* __u8 iSerialNumber; */
+ 0x01 /* __u8 bNumConfigurations; */
+};
+
+/* Configuration descriptor */
+static __u8 root_hub_config_des[] = {
+ 0x09, /* __u8 bLength; */
+ 0x02, /* __u8 bDescriptorType; Configuration */
+ 0x19, /* __u16 wTotalLength; */
+ 0x00,
+ 0x01, /* __u8 bNumInterfaces; */
+ 0x01, /* __u8 bConfigurationValue; */
+ 0x00, /* __u8 iConfiguration; */
+ 0x40, /* __u8 bmAttributes; */
+
+ 0x00, /* __u8 MaxPower; */
+
+ /* interface */
+ 0x09, /* __u8 if_bLength; */
+ 0x04, /* __u8 if_bDescriptorType; Interface */
+ 0x00, /* __u8 if_bInterfaceNumber; */
+ 0x00, /* __u8 if_bAlternateSetting; */
+ 0x01, /* __u8 if_bNumEndpoints; */
+ 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 if_bInterfaceSubClass; */
+ 0x00, /* __u8 if_bInterfaceProtocol; */
+ 0x00, /* __u8 if_iInterface; */
+
+ /* endpoint */
+ 0x07, /* __u8 ep_bLength; */
+ 0x05, /* __u8 ep_bDescriptorType; Endpoint */
+ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
+ 0x03, /* __u8 ep_bmAttributes; Interrupt */
+ 0x08, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
+ 0x00,
+ 0xff /* __u8 ep_bInterval; 255 ms */
+};
+
+static unsigned char root_hub_str_index0[] = {
+ 0x04, /* __u8 bLength; */
+ 0x03, /* __u8 bDescriptorType; String-descriptor */
+ 0x09, /* __u8 lang ID */
+ 0x04, /* __u8 lang ID */
+};
+
+static unsigned char root_hub_str_index1[] = {
+ 32, /* __u8 bLength; */
+ 0x03, /* __u8 bDescriptorType; String-descriptor */
+ 'D', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'W', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'C', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ ' ', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'O', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'T', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'G', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ ' ', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'R', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'o', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'o', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 't', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'H', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'u', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'b', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+};
+
+static int dwc_otg_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
+ void *buffer, int transfer_len,
+ struct devrequest *cmd)
+{
+ int leni = transfer_len;
+ int len = 0;
+ int stat = 0;
+ __u16 bmRType_bReq;
+ __u16 wValue;
+ __u16 wLength;
+ unsigned char data[32];
+ hprt0_data_t hprt0 = {.d32 = 0 };
+
+ if (usb_pipeint(pipe)) {
+ printf("Root-Hub submit IRQ: NOT implemented");
+ return 0;
+ }
+
+ bmRType_bReq = cmd->requesttype | (cmd->request << 8);
+ wValue = cpu_to_le16 (cmd->value);
+ wLength = cpu_to_le16 (cmd->length);
+
+ switch (bmRType_bReq) {
+ case RH_GET_STATUS:
+ *(__u16 *)buffer = cpu_to_le16(1);
+ len = 2;
+ break;
+ case RH_GET_STATUS | RH_INTERFACE:
+ *(__u16 *)buffer = cpu_to_le16(0);
+ len = 2;
+ break;
+ case RH_GET_STATUS | RH_ENDPOINT:
+ *(__u16 *)buffer = cpu_to_le16(0);
+ len = 2;
+ break;
+ case RH_GET_STATUS | RH_CLASS:
+ *(__u32 *)buffer = cpu_to_le32(0);
+ len = 4;
+ break;
+ case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+ {
+ uint32_t port_status = 0;
+ uint32_t port_change = 0;
+ hprt0.d32 = dwc_read_reg32(g_core_if.host_if->hprt0);
+ if (hprt0.b.prtconnsts)
+ port_status |= USB_PORT_STAT_CONNECTION;
+ if (hprt0.b.prtena)
+ port_status |= USB_PORT_STAT_ENABLE;
+ if (hprt0.b.prtsusp)
+ port_status |= USB_PORT_STAT_SUSPEND;
+ if (hprt0.b.prtovrcurract)
+ port_status |= USB_PORT_STAT_OVERCURRENT;
+ if (hprt0.b.prtrst)
+ port_status |= USB_PORT_STAT_RESET;
+ if (hprt0.b.prtpwr)
+ port_status |= USB_PORT_STAT_POWER;
+
+ port_status |= USB_PORT_STAT_HIGH_SPEED;
+
+ if (hprt0.b.prtenchng)
+ port_change |= USB_PORT_STAT_C_ENABLE;
+ if (hprt0.b.prtconndet)
+ port_change |= USB_PORT_STAT_C_CONNECTION;
+ if (hprt0.b.prtovrcurrchng)
+ port_change |= USB_PORT_STAT_C_OVERCURRENT;
+
+ *(__u32 *)buffer = cpu_to_le32(port_status |
+ (port_change << 16));
+ len = 4;
+ }
+ break;
+ case RH_CLEAR_FEATURE | RH_ENDPOINT:
+ case RH_CLEAR_FEATURE | RH_CLASS:
+ break;
+
+ case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+ switch (wValue) {
+ case RH_C_PORT_CONNECTION:
+ hprt0.d32 = dwc_read_reg32(g_core_if.host_if->hprt0);
+ hprt0.b.prtconndet = 1;
+ dwc_write_reg32(g_core_if.host_if->hprt0, hprt0.d32);
+ break;
+ }
+ break;
+
+ case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+ switch (wValue) {
+ case (RH_PORT_SUSPEND):
+ break;
+
+ case (RH_PORT_RESET):
+ hprt0.d32 = dwc_otg_read_hprt0(&g_core_if);
+ hprt0.b.prtrst = 1;
+ dwc_write_reg32(g_core_if.host_if->hprt0, hprt0.d32);
+ udelay(500);
+ hprt0.b.prtrst = 0;
+ dwc_write_reg32(g_core_if.host_if->hprt0, hprt0.d32);
+
+ udelay(500);
+ hprt0.d32 = dwc_read_reg32(g_core_if.host_if->hprt0);
+
+ break;
+
+ case (RH_PORT_POWER):
+ hprt0.d32 = dwc_otg_read_hprt0(&g_core_if);
+ hprt0.b.prtpwr = 1;
+ dwc_write_reg32(g_core_if.host_if->hprt0, hprt0.d32);
+ break;
+
+ case (RH_PORT_ENABLE):
+ break;
+ }
+ break;
+ case RH_SET_ADDRESS:
+ root_hub_devnum = wValue;
+ break;
+ case RH_GET_DESCRIPTOR:
+ switch ((wValue & 0xff00) >> 8) {
+ case (0x01): /* device descriptor */
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof(root_hub_dev_des),
+ wLength));
+ memcpy(buffer, root_hub_dev_des, len);
+ break;
+ case (0x02): /* configuration descriptor */
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof(root_hub_config_des),
+ wLength));
+ memcpy(buffer, root_hub_config_des, len);
+ break;
+ case (0x03): /* string descriptors */
+ if (wValue == 0x0300) {
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof(root_hub_str_index0),
+ wLength));
+ memcpy(buffer, root_hub_str_index0, len);
+ }
+ if (wValue == 0x0301) {
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof(root_hub_str_index1),
+ wLength));
+ memcpy(buffer, root_hub_str_index1, len);
+ }
+ break;
+ default:
+ stat = USB_ST_STALLED;
+ }
+ break;
+
+ case RH_GET_DESCRIPTOR | RH_CLASS:
+ {
+ __u32 temp = 0x00000001;
+
+ data[0] = 9; /* min length; */
+ data[1] = 0x29;
+ data[2] = temp & RH_A_NDP;
+ data[3] = 0;
+ if (temp & RH_A_PSM)
+ data[3] |= 0x1;
+ if (temp & RH_A_NOCP)
+ data[3] |= 0x10;
+ else if (temp & RH_A_OCPM)
+ data[3] |= 0x8;
+
+ /* corresponds to data[4-7] */
+ data[5] = (temp & RH_A_POTPGT) >> 24;
+ data[7] = temp & RH_B_DR;
+ if (data[2] < 7) {
+ data[8] = 0xff;
+ } else {
+ data[0] += 2;
+ data[8] = (temp & RH_B_DR) >> 8;
+ data[10] = data[9] = 0xff;
+ }
+
+ len = min_t(unsigned int, leni,
+ min_t(unsigned int, data[0], wLength));
+ memcpy(buffer, data, len);
+ break;
+ }
+
+ case RH_GET_CONFIGURATION:
+ *(__u8 *) buffer = 0x01;
+ len = 1;
+ break;
+ case RH_SET_CONFIGURATION:
+ break;
+ default:
+ printf("unsupported root hub command\n");
+ stat = USB_ST_STALLED;
+ }
+
+ mdelay(1);
+
+ len = min_t(int, len, leni);
+
+ dev->act_len = len;
+ dev->status = stat;
+
+ return stat;
+
+}
+
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int len)
+{
+ int devnum = usb_pipedevice(pipe);
+ int ep = usb_pipeendpoint(pipe);
+ int max = usb_maxpacket(dev, pipe);
+ int done = 0;
+ hctsiz_data_t hctsiz;
+ dwc_otg_host_if_t *host_if = g_core_if.host_if;
+ dwc_otg_hc_regs_t *hc_regs;
+ hcint_data_t hcint;
+ hcint_data_t hcint_new;
+ uint32_t max_hc_xfer_size = g_core_if.core_params->max_transfer_size;
+ uint16_t max_hc_pkt_count = g_core_if.core_params->max_packet_count;
+ uint32_t xfer_len;
+ uint32_t num_packets;
+ int stop_transfer = 0;
+
+ if (len > DWC_OTG_HCD_DATA_BUF_SIZE) {
+ printf("submit_bulk_msg: %d is more then available buffer size(%d)\n", len, DWC_OTG_HCD_DATA_BUF_SIZE);
+ dev->status = 0;
+ dev->act_len = done;
+ return -1;
+ }
+
+ hc_regs = host_if->hc_regs[CHANNEL];
+
+ if (devnum == root_hub_devnum) {
+ dev->status = 0;
+ return -1;
+ }
+
+ while ((done < len) && !stop_transfer) {
+ /* Initialize channel */
+ dwc_otg_hc_init(&g_core_if, CHANNEL, devnum, ep, usb_pipein(pipe), DWC_OTG_EP_TYPE_BULK, max);
+
+ xfer_len = (len - done);
+ if (xfer_len > max_hc_xfer_size)
+ /* Make sure that xfer_len is a multiple of max packet size. */
+ xfer_len = max_hc_xfer_size - max + 1;
+
+ if (xfer_len > 0) {
+ num_packets = (xfer_len + max - 1) / max;
+ if (num_packets > max_hc_pkt_count) {
+ num_packets = max_hc_pkt_count;
+ xfer_len = num_packets * max;
+ }
+ } else
+ num_packets = 1;
+
+ if (usb_pipein(pipe))
+ xfer_len = num_packets * max;
+
+ hctsiz.d32 = 0;
+
+ hctsiz.b.xfersize = xfer_len;
+ hctsiz.b.pktcnt = num_packets;
+ hctsiz.b.pid = bulk_data_toggle[devnum][ep];
+
+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32);
+
+ memcpy(aligned_buffer, (char *)buffer + done, len - done);
+ dwc_write_reg32(&hc_regs->hcdma, (uint32_t)aligned_buffer);
+
+ hcchar_data_t hcchar;
+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
+ hcchar.b.multicnt = 1;
+
+ /* Remember original int status */
+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
+
+ /* Set host channel enable after all other setup is complete. */
+ hcchar.b.chen = 1;
+ hcchar.b.chdis = 0;
+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
+
+ /* TODO: no endless loop */
+ while (1) {
+ hcint_new.d32 = dwc_read_reg32(&hc_regs->hcint);
+ if (hcint.d32 != hcint_new.d32) {
+ hcint.d32 = hcint_new.d32;
+ }
+
+ if (hcint_new.b.ack) {
+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
+
+ if (hctsiz.b.pid == DWC_OTG_HC_PID_DATA1)
+ bulk_data_toggle[devnum][ep] = DWC_OTG_HC_PID_DATA1;
+ else
+ bulk_data_toggle[devnum][ep] = DWC_OTG_HC_PID_DATA0;
+ }
+
+ if (hcint_new.b.chhltd) {
+ if (hcint_new.b.xfercomp) {
+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
+ if (usb_pipein(pipe)) {
+ done += xfer_len - hctsiz.b.xfersize;
+ if (hctsiz.b.xfersize)
+ stop_transfer = 1;
+ } else {
+ done += xfer_len;
+ }
+
+ if (hcint_new.d32 != STATUS_ACK_HLT_COMPL) {
+ handle_error(__LINE__, hcint_new.d32);
+ goto out;
+ }
+
+ break;
+ } else if (hcint_new.b.stall) {
+ printf("DWC OTG: Channel halted\n");
+ bulk_data_toggle[devnum][ep] = DWC_OTG_HC_PID_DATA0;
+
+ stop_transfer = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if (done && usb_pipein(pipe))
+ memcpy(buffer, aligned_buffer, done);
+
+ dwc_write_reg32(&hc_regs->hcintmsk, 0);
+ dwc_write_reg32(&hc_regs->hcint, 0xFFFFFFFF);
+out:
+ dev->status = 0;
+ dev->act_len = done;
+
+ return 0;
+}
+
+int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int len, struct devrequest *setup)
+{
+ int done = 0;
+ int devnum = usb_pipedevice(pipe);
+ int ep = usb_pipeendpoint(pipe);
+ int max = usb_maxpacket(dev, pipe);
+ hctsiz_data_t hctsiz;
+ dwc_otg_host_if_t *host_if = g_core_if.host_if;
+ dwc_otg_hc_regs_t *hc_regs = host_if->hc_regs[CHANNEL];
+ hcint_data_t hcint_new;
+ /* For CONTROL endpoint pid should start with DATA1 */
+ int status_direction;
+
+ if (devnum == root_hub_devnum) {
+ dev->status = 0;
+ dev->speed = USB_SPEED_HIGH;
+ return dwc_otg_submit_rh_msg(dev, pipe, buffer, len, setup);
+ }
+
+ if (len > DWC_OTG_HCD_DATA_BUF_SIZE) {
+ printf("submit_control_msg: %d is more then available buffer size(%d)\n", len, DWC_OTG_HCD_DATA_BUF_SIZE);
+ dev->status = 0;
+ dev->act_len = done;
+ return -1;
+ }
+
+ /* Initialize channel, OUT for setup buffer */
+ dwc_otg_hc_init(&g_core_if, CHANNEL, devnum, ep, 0, DWC_OTG_EP_TYPE_CONTROL, max);
+
+ /* SETUP stage */
+ hctsiz.d32 = 0;
+ hctsiz.b.xfersize = 8;
+ hctsiz.b.pktcnt = 1;
+ hctsiz.b.pid = DWC_OTG_HC_PID_SETUP;
+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32);
+
+ dwc_write_reg32(&hc_regs->hcdma, (uint32_t)setup);
+
+ hcchar_data_t hcchar;
+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
+ hcchar.b.multicnt = 1;
+
+ /* Set host channel enable after all other setup is complete. */
+ hcchar.b.chen = 1;
+ hcchar.b.chdis = 0;
+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
+
+ /* TODO: no endless loop */
+ while (1) {
+ hcint_new.d32 = dwc_read_reg32(&hc_regs->hcint);
+ if (hcint_new.b.chhltd) {
+ break;
+ }
+ }
+
+ /* TODO: check for error */
+ if (!(hcint_new.b.chhltd && hcint_new.b.xfercomp)) {
+ handle_error(__LINE__, hcint_new.d32);
+ goto out;
+ }
+
+ /* Clear interrupts */
+ dwc_write_reg32(&hc_regs->hcintmsk, 0);
+ dwc_write_reg32(&hc_regs->hcint, 0xFFFFFFFF);
+
+ if (buffer) {
+ /* DATA stage */
+ dwc_otg_hc_init(&g_core_if, CHANNEL, devnum, ep, usb_pipein(pipe), DWC_OTG_EP_TYPE_CONTROL, max);
+
+ /* TODO: check if len < 64 */
+ hctsiz.d32 = 0;
+ hctsiz.b.xfersize = len;
+ hctsiz.b.pktcnt = 1;
+
+ control_data_toggle[devnum][ep] = DWC_OTG_HC_PID_DATA1;
+ hctsiz.b.pid = control_data_toggle[devnum][ep];
+
+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32);
+
+ dwc_write_reg32(&hc_regs->hcdma, (uint32_t)buffer);
+
+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
+ hcchar.b.multicnt = 1;
+
+ /* Set host channel enable after all other setup is complete. */
+ hcchar.b.chen = 1;
+ hcchar.b.chdis = 0;
+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
+
+ while (1) {
+ hcint_new.d32 = dwc_read_reg32(&hc_regs->hcint);
+ if (hcint_new.b.chhltd) {
+ if (hcint_new.b.xfercomp) {
+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
+ if (usb_pipein(pipe))
+ done = len - hctsiz.b.xfersize;
+ else
+ done = len;
+ }
+
+ if (hcint_new.b.ack) {
+ if (hctsiz.b.pid == DWC_OTG_HC_PID_DATA0)
+ control_data_toggle[devnum][ep] = DWC_OTG_HC_PID_DATA0;
+ else
+ control_data_toggle[devnum][ep] = DWC_OTG_HC_PID_DATA1;
+ }
+
+ if (hcint_new.d32 != STATUS_ACK_HLT_COMPL) {
+ goto out;
+ handle_error(__LINE__, hcint_new.d32);
+ }
+
+ break;
+ }
+ }
+ } /* End of DATA stage */
+
+ /* STATUS stage */
+ if ((len == 0) || usb_pipeout(pipe))
+ status_direction = 1;
+ else
+ status_direction = 0;
+
+ dwc_otg_hc_init(&g_core_if, CHANNEL, devnum, ep, status_direction, DWC_OTG_EP_TYPE_CONTROL, max);
+
+ hctsiz.d32 = 0;
+ hctsiz.b.xfersize = 0;
+ hctsiz.b.pktcnt = 1;
+ hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32);
+
+ dwc_write_reg32(&hc_regs->hcdma, (uint32_t)status_buffer);
+
+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
+ hcchar.b.multicnt = 1;
+
+ /* Set host channel enable after all other setup is complete. */
+ hcchar.b.chen = 1;
+ hcchar.b.chdis = 0;
+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
+
+ while (1) {
+ hcint_new.d32 = dwc_read_reg32(&hc_regs->hcint);
+ if (hcint_new.b.chhltd)
+ break;
+ }
+
+ if (hcint_new.d32 != STATUS_ACK_HLT_COMPL)
+ handle_error(__LINE__, hcint_new.d32);
+
+out:
+ dev->act_len = done;
+ dev->status = 0;
+
+ return done;
+}
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int len, int interval)
+{
+ printf("dev = %p pipe = %#lx buf = %p size = %d int = %d\n", dev, pipe,
+ buffer, len, interval);
+ return -1;
+}
diff --git a/drivers/usb/host/dwc2_otg.c b/drivers/usb/host/dwc2_otg.c
new file mode 100644
index 0000000..f80a505
--- /dev/null
+++ b/drivers/usb/host/dwc2_otg.c
@@ -0,0 +1,2179 @@
+#include <common.h>
+#include <usb.h>
+#include <malloc.h>
+#include "dwc2_otg.h"
+#include "dwc2_otg_regs.h"
+#include "dwc2_otg_core_if.h"
+
+#undef DWC_OTG_DEBUG
+
+#ifdef DWC_OTG_DEBUG
+ #define PDEBUG(fmt, args...) \
+ printf("[%s:%d] " fmt, \
+ __PRETTY_FUNCTION__, __LINE__ , ## args)
+#else
+ #define PDEBUG(fmt, args...) do {} while (0)
+#endif
+
+void dwc_write_reg32(volatile uint32_t *addr, uint32_t value)
+{
+ *addr = value;
+}
+
+uint32_t dwc_read_reg32(volatile uint32_t *addr)
+{
+ return *addr;
+}
+
+void dwc_modify_reg32(volatile uint32_t *addr, uint32_t clear_mask, uint32_t set_mask)
+{
+ uint32_t v = *addr;
+ *addr = (v & ~clear_mask) | set_mask;
+}
+
+/**
+ * This function returns the mode of the operation, host or device.
+ *
+ * @return 0 - Device Mode, 1 - Host Mode
+ */
+static inline uint32_t dwc_otg_mode(dwc_otg_core_if_t *_core_if)
+{
+ return dwc_read_reg32(&_core_if->core_global_regs->gintsts) & 0x1;
+}
+
+uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t *_core_if)
+{
+ return dwc_otg_mode(_core_if) == DWC_HOST_MODE;
+}
+
+static void dwc_otg_set_uninitialized(int32_t *p, int size)
+{
+ int i;
+ for (i = 0; i < size; i++) {
+ p[i] = -1;
+ }
+}
+
+static int dwc_otg_param_initialized(int32_t val)
+{
+ return val != -1;
+}
+
+/**
+ * This function returns the Host All Channel Interrupt register
+ */
+static inline uint32_t dwc_otg_read_host_all_channels_intr(
+ dwc_otg_core_if_t *_core_if)
+{
+ return dwc_read_reg32(&_core_if->host_if->host_global_regs->haint);
+}
+
+static inline uint32_t dwc_otg_read_host_channel_intr(
+ dwc_otg_core_if_t *_core_if, int hc_num)
+{
+ return dwc_read_reg32(&_core_if->host_if->hc_regs[hc_num]->hcint);
+}
+
+/**
+ * This function Reads HPRT0 in preparation to modify. It keeps the
+ * WC bits 0 so that if they are read as 1, they won't clear when you
+ * write it back
+ */
+uint32_t dwc_otg_read_hprt0(dwc_otg_core_if_t *_core_if)
+{
+ hprt0_data_t hprt0;
+ hprt0.d32 = dwc_read_reg32(_core_if->host_if->hprt0);
+ hprt0.b.prtena = 0;
+ hprt0.b.prtconndet = 0;
+ hprt0.b.prtenchng = 0;
+ hprt0.b.prtovrcurrchng = 0;
+ return hprt0.d32;
+}
+
+/* Checks if the parameter is outside of its valid range of values */
+#define DWC_OTG_PARAM_TEST(_param_, _low_, _high_) \
+ (((_param_) < (_low_)) || \
+ ((_param_) > (_high_)))
+
+/* Parameter access functions */
+int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int valid;
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 0, 2)) {
+ printf("warning: Wrong value for otg_cap parameter\n");
+ printf("warning: otg_cap parameter must be 0, 1 or 2\n");
+ retval = -1;
+ goto out;
+ }
+
+ valid = 1;
+ switch (val) {
+ case DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE:
+ if (core_if->hwcfg2.b.op_mode !=
+ DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
+ valid = 0;
+ break;
+ case DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE:
+ if ((core_if->hwcfg2.b.op_mode !=
+ DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
+ && (core_if->hwcfg2.b.op_mode !=
+ DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
+ && (core_if->hwcfg2.b.op_mode !=
+ DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE)
+ && (core_if->hwcfg2.b.op_mode !=
+ DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) {
+ valid = 0;
+ }
+ break;
+ case DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE:
+ /* always valid */
+ break;
+ }
+ if (!valid) {
+ if (dwc_otg_param_initialized(core_if->core_params->otg_cap)) {
+ printf
+ ("error: %d invalid for otg_cap paremter. Check HW configuration.\n",
+ val);
+ }
+ val =
+ (((core_if->hwcfg2.b.op_mode ==
+ DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
+ || (core_if->hwcfg2.b.op_mode ==
+ DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
+ || (core_if->hwcfg2.b.op_mode ==
+ DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE)
+ || (core_if->hwcfg2.b.op_mode ==
+ DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) ?
+ DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE :
+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
+ retval = -1;
+ }
+
+ core_if->core_params->otg_cap = val;
+ out:
+ return retval;
+}
+
+int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->otg_cap;
+}
+
+int dwc_otg_set_param_opt(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong value for opt parameter\n");
+ return -1;
+ }
+ core_if->core_params->opt = val;
+ return 0;
+}
+
+int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->opt;
+}
+
+int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong value for dma enable\n");
+ return -1;
+ }
+
+ if ((val == 1) && (core_if->hwcfg2.b.architecture == 0)) {
+ if (dwc_otg_param_initialized(core_if->core_params->dma_enable)) {
+ printf
+ ("error: %d invalid for dma_enable paremter. Check HW configuration.\n",
+ val);
+ }
+ val = 0;
+ retval = -1;
+ }
+
+ core_if->core_params->dma_enable = val;
+ if (val == 0) {
+ dwc_otg_set_param_dma_desc_enable(core_if, 0);
+ }
+ return retval;
+}
+
+int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->dma_enable;
+}
+
+int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong value for dma_enable\n");
+ printf("warning: dma_desc_enable must be 0 or 1\n");
+ return -1;
+ }
+
+ if ((val == 1)
+ && ((dwc_otg_get_param_dma_enable(core_if) == 0)
+ || (core_if->hwcfg4.b.desc_dma == 0))) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->dma_desc_enable)) {
+ printf
+ ("error: %d invalid for dma_desc_enable paremter. Check HW configuration.\n",
+ val);
+ }
+ val = 0;
+ retval = -1;
+ }
+ core_if->core_params->dma_desc_enable = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->dma_desc_enable;
+}
+
+int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong value for host_support_fs_low_power\n");
+ printf("warning: host_support_fs_low_power must be 0 or 1\n");
+ return -1;
+ }
+ core_if->core_params->host_support_fs_ls_low_power = val;
+ return 0;
+}
+
+int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *
+ core_if)
+{
+ return core_if->core_params->host_support_fs_ls_low_power;
+}
+
+int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong value for enable_dynamic_fifo\n");
+ printf("warning: enable_dynamic_fifo must be 0 or 1\n");
+ return -1;
+ }
+
+ if ((val == 1) && (core_if->hwcfg2.b.dynamic_fifo == 0)) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->enable_dynamic_fifo)) {
+ printf
+ ("error: %d invalid for enable_dynamic_fifo paremter. Check HW configuration.\n",
+ val);
+ }
+ val = 0;
+ retval = -1;
+ }
+ core_if->core_params->enable_dynamic_fifo = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->enable_dynamic_fifo;
+}
+
+int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 32, 32768)) {
+ printf("warning: Wrong value for data_fifo_size\n");
+ printf("warning: data_fifo_size must be 32-32768\n");
+ return -1;
+ }
+
+ if (val > core_if->hwcfg3.b.dfifo_depth) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->data_fifo_size)) {
+ printf
+ ("error: %d invalid for data_fifo_size parameter. Check HW configuration.\n",
+ val);
+ }
+ val = core_if->hwcfg3.b.dfifo_depth;
+ retval = -1;
+ }
+
+ core_if->core_params->data_fifo_size = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->data_fifo_size;
+}
+
+int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
+ printf("warning: Wrong value for dev_rx_fifo_size\n");
+ printf("warning: dev_rx_fifo_size must be 16-32768\n");
+ return -1;
+ }
+
+ if (val > dwc_read_reg32(&core_if->core_global_regs->grxfsiz)) {
+ if (dwc_otg_param_initialized(core_if->core_params->dev_rx_fifo_size)) {
+ printf("warning: %d invalid for dev_rx_fifo_size parameter\n", val);
+ }
+ val = dwc_read_reg32(&core_if->core_global_regs->grxfsiz);
+ retval = -1;
+ }
+
+ core_if->core_params->dev_rx_fifo_size = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->dev_rx_fifo_size;
+}
+
+int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
+ printf("warning: Wrong value for dev_nperio_tx_fifo\n");
+ printf("warning: dev_nperio_tx_fifo must be 16-32768\n");
+ return -1;
+ }
+
+ if (val > (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> 16)) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->dev_nperio_tx_fifo_size)) {
+ printf
+ ("error: %d invalid for dev_nperio_tx_fifo_size. Check HW configuration.\n",
+ val);
+ }
+ val =
+ (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >>
+ 16);
+ retval = -1;
+ }
+
+ core_if->core_params->dev_nperio_tx_fifo_size = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->dev_nperio_tx_fifo_size;
+}
+
+int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
+ printf("warning: Wrong value for host_rx_fifo_size\n");
+ printf("warning: host_rx_fifo_size must be 16-32768\n");
+ return -1;
+ }
+
+ if (val > dwc_read_reg32(&core_if->core_global_regs->grxfsiz)) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->host_rx_fifo_size)) {
+ printf
+ ("error: %d invalid for host_rx_fifo_size. Check HW configuration.\n",
+ val);
+ }
+ val = dwc_read_reg32(&core_if->core_global_regs->grxfsiz);
+ retval = -1;
+ }
+
+ core_if->core_params->host_rx_fifo_size = val;
+ return retval;
+
+}
+
+int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->host_rx_fifo_size;
+}
+
+int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
+ printf("warning: Wrong value for host_nperio_tx_fifo_size\n");
+ printf("warning: host_nperio_tx_fifo_size must be 16-32768\n");
+ return -1;
+ }
+
+ if (val > (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> 16)) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->host_nperio_tx_fifo_size)) {
+ printf
+ ("error: %d invalid for host_nperio_tx_fifo_size. Check HW configuration.\n",
+ val);
+ }
+ val =
+ (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >>
+ 16);
+ retval = -1;
+ }
+
+ core_if->core_params->host_nperio_tx_fifo_size = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->host_nperio_tx_fifo_size;
+}
+
+int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
+ printf("warning: Wrong value for host_perio_tx_fifo_size\n");
+ printf("warning: host_perio_tx_fifo_size must be 16-32768\n");
+ return -1;
+ }
+
+ if (val >
+ ((dwc_read_reg32(&core_if->core_global_regs->hptxfsiz) >> 16))) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->host_perio_tx_fifo_size)) {
+ printf
+ ("error: %d invalid for host_perio_tx_fifo_size. Check HW configuration.\n",
+ val);
+ }
+ val =
+ (dwc_read_reg32(&core_if->core_global_regs->hptxfsiz) >>
+ 16);
+ retval = -1;
+ }
+
+ core_if->core_params->host_perio_tx_fifo_size = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->host_perio_tx_fifo_size;
+}
+
+int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 2047, 524288)) {
+ printf("warning: Wrong value for max_transfer_size\n");
+ printf("warning: max_transfer_size must be 2047-524288\n");
+ return -1;
+ }
+
+ if (val >= (1 << (core_if->hwcfg3.b.xfer_size_cntr_width + 11))) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->max_transfer_size)) {
+ printf
+ ("error: %d invalid for max_transfer_size. Check HW configuration.\n",
+ val);
+ }
+ val =
+ ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 11)) -
+ 1);
+ retval = -1;
+ }
+
+ core_if->core_params->max_transfer_size = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->max_transfer_size;
+}
+
+int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 15, 511)) {
+ printf("warning: Wrong value for max_packet_count\n");
+ printf("warning: max_packet_count must be 15-511\n");
+ return -1;
+ }
+
+ if (val > (1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4))) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->max_packet_count)) {
+ printf
+ ("error: %d invalid for max_packet_count. Check HW configuration.\n",
+ val);
+ }
+ val =
+ ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4)) - 1);
+ retval = -1;
+ }
+
+ core_if->core_params->max_packet_count = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->max_packet_count;
+}
+
+int dwc_otg_set_param_host_channels(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 1, 16)) {
+ printf("warning: Wrong value for host_channels\n");
+ printf("warning: host_channels must be 1-16\n");
+ return -1;
+ }
+
+ if (val > (core_if->hwcfg2.b.num_host_chan + 1)) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->host_channels)) {
+ printf
+ ("error: %d invalid for host_channels. Check HW configurations.\n",
+ val);
+ }
+ val = (core_if->hwcfg2.b.num_host_chan + 1);
+ retval = -1;
+ }
+
+ core_if->core_params->host_channels = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->host_channels;
+}
+
+int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 1, 15)) {
+ printf("warning: Wrong value for dev_endpoints\n");
+ printf("warning: dev_endpoints must be 1-15\n");
+ return -1;
+ }
+
+ if (val > (core_if->hwcfg2.b.num_dev_ep)) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->dev_endpoints)) {
+ printf
+ ("error: %d invalid for dev_endpoints. Check HW configurations.\n",
+ val);
+ }
+ val = core_if->hwcfg2.b.num_dev_ep;
+ retval = -1;
+ }
+
+ core_if->core_params->dev_endpoints = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->dev_endpoints;
+}
+
+int dwc_otg_set_param_phy_type(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+ int valid = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 0, 2)) {
+ printf("warning: Wrong value for phy_type\n");
+ printf("warning: phy_type must be 0, 1 or 2\n");
+ return -1;
+ }
+#ifndef NO_FS_PHY_HW_CHECKS
+ if ((val == DWC_PHY_TYPE_PARAM_UTMI) &&
+ ((core_if->hwcfg2.b.hs_phy_type == 1) ||
+ (core_if->hwcfg2.b.hs_phy_type == 3))) {
+ valid = 1;
+ } else if ((val == DWC_PHY_TYPE_PARAM_ULPI) &&
+ ((core_if->hwcfg2.b.hs_phy_type == 2) ||
+ (core_if->hwcfg2.b.hs_phy_type == 3))) {
+ valid = 1;
+ } else if ((val == DWC_PHY_TYPE_PARAM_FS) &&
+ (core_if->hwcfg2.b.fs_phy_type == 1)) {
+ valid = 1;
+ }
+ if (!valid) {
+ if (dwc_otg_param_initialized(core_if->core_params->phy_type)) {
+ printf
+ ("error: %d invalid for phy_type. Check HW configurations.\n",
+ val);
+ }
+ if (core_if->hwcfg2.b.hs_phy_type) {
+ if ((core_if->hwcfg2.b.hs_phy_type == 3) ||
+ (core_if->hwcfg2.b.hs_phy_type == 1)) {
+ val = DWC_PHY_TYPE_PARAM_UTMI;
+ } else {
+ val = DWC_PHY_TYPE_PARAM_ULPI;
+ }
+ }
+ retval = -1;
+ }
+#endif
+ core_if->core_params->phy_type = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->phy_type;
+}
+
+int dwc_otg_set_param_speed(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong value for speed parameter\n");
+ printf("warning: max_speed parameter must be 0 or 1\n");
+ return -1;
+ }
+ if ((val == 0)
+ && dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS) {
+ if (dwc_otg_param_initialized(core_if->core_params->speed)) {
+ printf
+ ("error: %d invalid for speed paremter. Check HW configuration.\n",
+ val);
+ }
+ val =
+ (dwc_otg_get_param_phy_type(core_if) ==
+ DWC_PHY_TYPE_PARAM_FS ? 1 : 0);
+ retval = -1;
+ }
+ core_if->core_params->speed = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->speed;
+}
+
+int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf
+ ("warning: Wrong value for host_ls_low_power_phy_clk parameter\n");
+ printf("warning: host_ls_low_power_phy_clk must be 0 or 1\n");
+ return -1;
+ }
+
+ if ((val == DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ)
+ && (dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS)) {
+ if (dwc_otg_param_initialized(core_if->core_params->host_ls_low_power_phy_clk)) {
+ printf("error: %d invalid for host_ls_low_power_phy_clk. Check HW configuration.\n",
+ val);
+ }
+ val =
+ (dwc_otg_get_param_phy_type(core_if) ==
+ DWC_PHY_TYPE_PARAM_FS) ?
+ DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ :
+ DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ;
+ retval = -1;
+ }
+
+ core_if->core_params->host_ls_low_power_phy_clk = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->host_ls_low_power_phy_clk;
+}
+
+int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong value for phy_ulpi_ddr\n");
+ printf("warning: phy_upli_ddr must be 0 or 1\n");
+ return -1;
+ }
+
+ core_if->core_params->phy_ulpi_ddr = val;
+ return 0;
+}
+
+int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->phy_ulpi_ddr;
+}
+
+int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong valaue for phy_ulpi_ext_vbus\n");
+ printf("warning: phy_ulpi_ext_vbus must be 0 or 1\n");
+ return -1;
+ }
+
+ core_if->core_params->phy_ulpi_ext_vbus = val;
+ return 0;
+}
+
+int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->phy_ulpi_ext_vbus;
+}
+
+int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ if (DWC_OTG_PARAM_TEST(val, 8, 8) && DWC_OTG_PARAM_TEST(val, 16, 16)) {
+ printf("warning: Wrong valaue for phy_utmi_width\n");
+ printf("warning: phy_utmi_width must be 8 or 16\n");
+ return -1;
+ }
+
+ core_if->core_params->phy_utmi_width = val;
+ return 0;
+}
+
+int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->phy_utmi_width;
+}
+
+int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong valaue for ulpi_fs_ls\n");
+ printf("warning: ulpi_fs_ls must be 0 or 1\n");
+ return -1;
+ }
+
+ core_if->core_params->ulpi_fs_ls = val;
+ return 0;
+}
+
+int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->ulpi_fs_ls;
+}
+
+int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong valaue for ts_dline\n");
+ printf("warning: ts_dline must be 0 or 1\n");
+ return -1;
+ }
+
+ core_if->core_params->ts_dline = val;
+ return 0;
+}
+
+int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->ts_dline;
+}
+
+int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong valaue for i2c_enable\n");
+ printf("warning: i2c_enable must be 0 or 1\n");
+ return -1;
+ }
+#ifndef NO_FS_PHY_HW_CHECK
+ if (val == 1 && core_if->hwcfg3.b.i2c == 0) {
+ if (dwc_otg_param_initialized(core_if->core_params->i2c_enable)) {
+ printf("error: %d invalid for i2c_enable. Check HW configuration.\n",
+ val);
+ }
+ val = 0;
+ retval = -1;
+ }
+#endif
+
+ core_if->core_params->i2c_enable = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->i2c_enable;
+}
+
+int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t *core_if,
+ int32_t val, int fifo_num)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 4, 768)) {
+ printf("warning: Wrong value for dev_perio_tx_fifo_size\n");
+ printf("warning: dev_perio_tx_fifo_size must be 4-768\n");
+ return -1;
+ }
+
+ if (val > (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz_dieptxf[fifo_num]))) {
+ if (dwc_otg_param_initialized(core_if->core_params->dev_perio_tx_fifo_size[fifo_num])) {
+ printf("error: `%d' invalid for parameter `dev_perio_fifo_size_%d'. Check HW configuration.\n",
+ val, fifo_num);
+ }
+ val = (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz_dieptxf[fifo_num]));
+ retval = -1;
+ }
+
+ core_if->core_params->dev_perio_tx_fifo_size[fifo_num] = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t *core_if,
+ int fifo_num)
+{
+ return core_if->core_params->dev_perio_tx_fifo_size[fifo_num];
+}
+
+int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong valaue for en_multiple_tx_fifo,\n");
+ printf("warning: en_multiple_tx_fifo must be 0 or 1\n");
+ return -1;
+ }
+
+ if (val == 1 && core_if->hwcfg4.b.ded_fifo_en == 0) {
+ if (dwc_otg_param_initialized(core_if->core_params->en_multiple_tx_fifo)) {
+ printf("error: %d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n",
+ val);
+ }
+ val = 0;
+ retval = -1;
+ }
+
+ core_if->core_params->en_multiple_tx_fifo = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->en_multiple_tx_fifo;
+}
+
+int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t *core_if, int32_t val,
+ int fifo_num)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 4, 768)) {
+ printf("warning: Wrong value for dev_tx_fifo_size\n");
+ printf("warning: dev_tx_fifo_size must be 4-768\n");
+ return -1;
+ }
+
+ if (val > (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz_dieptxf[fifo_num]))) {
+ if (dwc_otg_param_initialized(core_if->core_params->dev_tx_fifo_size[fifo_num])) {
+ printf("error: `%d' invalid for parameter `dev_tx_fifo_size_%d'. Check HW configuration.\n",
+ val, fifo_num);
+ }
+ val = (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz_dieptxf[fifo_num]));
+ retval = -1;
+ }
+
+ core_if->core_params->dev_tx_fifo_size[fifo_num] = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t *core_if,
+ int fifo_num)
+{
+ return core_if->core_params->dev_tx_fifo_size[fifo_num];
+}
+
+int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 0, 7)) {
+ printf("warning: Wrong value for thr_ctl\n");
+ printf("warning: thr_ctl must be 0-7\n");
+ return -1;
+ }
+
+ if ((val != 0) &&
+ (!dwc_otg_get_param_dma_enable(core_if) ||
+ !core_if->hwcfg4.b.ded_fifo_en)) {
+ if (dwc_otg_param_initialized(core_if->core_params->thr_ctl)) {
+ printf("error: %d invalid for parameter thr_ctl. Check HW configuration.\n",
+ val);
+ }
+ val = 0;
+ retval = -1;
+ }
+
+ core_if->core_params->thr_ctl = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_thr_ctl(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->thr_ctl;
+}
+
+int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong value for lpm_enable\n");
+ printf("warning: lpm_enable must be 0 or 1\n");
+ return -1;
+ }
+
+ if (val && !core_if->hwcfg3.b.otg_lpm_en) {
+ if (dwc_otg_param_initialized(core_if->core_params->lpm_enable)) {
+ printf("error: %d invalid for parameter lpm_enable. Check HW configuration.\n",
+ val);
+ }
+ val = 0;
+ retval = -1;
+ }
+
+ core_if->core_params->lpm_enable = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->lpm_enable;
+}
+
+int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ if (DWC_OTG_PARAM_TEST(val, 8, 128)) {
+ printf("warning: Wrong valaue for tx_thr_length\n");
+ printf("warning: tx_thr_length must be 8 - 128\n");
+ return -1;
+ }
+
+ core_if->core_params->tx_thr_length = val;
+ return 0;
+}
+
+int32_t dwc_otg_get_param_tx_thr_length(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->tx_thr_length;
+}
+
+int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ if (DWC_OTG_PARAM_TEST(val, 8, 128)) {
+ printf("warning: Wrong valaue for rx_thr_length\n");
+ printf("warning: rx_thr_length must be 8 - 128\n");
+ return -1;
+ }
+
+ core_if->core_params->rx_thr_length = val;
+ return 0;
+}
+
+int32_t dwc_otg_get_param_rx_thr_length(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->rx_thr_length;
+}
+
+int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ if (DWC_OTG_PARAM_TEST(val, 1, 1) &&
+ DWC_OTG_PARAM_TEST(val, 4, 4) &&
+ DWC_OTG_PARAM_TEST(val, 8, 8) &&
+ DWC_OTG_PARAM_TEST(val, 16, 16) &&
+ DWC_OTG_PARAM_TEST(val, 32, 32) &&
+ DWC_OTG_PARAM_TEST(val, 64, 64) &&
+ DWC_OTG_PARAM_TEST(val, 128, 128) &&
+ DWC_OTG_PARAM_TEST(val, 256, 256)) {
+ printf("warning: `%d' invalid for parameter `dma_burst_size'\n", val);
+ return -1;
+ }
+ core_if->core_params->dma_burst_size = val;
+ return 0;
+}
+
+int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->dma_burst_size;
+}
+
+int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: `%d' invalid for parameter `pti_enable'\n", val);
+ return -1;
+ }
+ if (val && (core_if->snpsid < OTG_CORE_REV_2_72a)) {
+ if (dwc_otg_param_initialized(core_if->core_params->pti_enable)) {
+ printf("error: %d invalid for parameter pti_enable. Check HW configuration.\n",
+ val);
+ }
+ retval = -1;
+ val = 0;
+ }
+ core_if->core_params->pti_enable = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->pti_enable;
+}
+
+int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: `%d' invalid for parameter `mpi_enable'\n", val);
+ return -1;
+ }
+ if (val && (core_if->hwcfg2.b.multi_proc_int == 0)) {
+ if (dwc_otg_param_initialized(core_if->core_params->mpi_enable)) {
+ printf("error: %d invalid for parameter mpi_enable. Check HW configuration.\n",
+ val);
+ }
+ retval = -1;
+ val = 0;
+ }
+ core_if->core_params->mpi_enable = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->mpi_enable;
+}
+
+int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: `%d' invalid for parameter `ic_usb_cap'\n", val);
+ printf("warning: ic_usb_cap must be 0 or 1\n");
+ return -1;
+ }
+
+ if (val && (core_if->hwcfg3.b.otg_enable_ic_usb == 0)) {
+ if (dwc_otg_param_initialized(core_if->core_params->ic_usb_cap)) {
+ printf("error: %d invalid for parameter ic_usb_cap. Check HW configuration.\n",
+ val);
+ }
+ retval = -1;
+ val = 0;
+ }
+ core_if->core_params->ic_usb_cap = val;
+ return retval;
+}
+int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->ic_usb_cap;
+}
+
+int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+ int valid = 1;
+
+ if (DWC_OTG_PARAM_TEST(val, 0, 3)) {
+ printf("warning: `%d' invalid for parameter `ahb_thr_ratio'\n", val);
+ printf("warning: ahb_thr_ratio must be 0 - 3\n");
+ return -1;
+ }
+
+ if (val && (core_if->snpsid < OTG_CORE_REV_2_81a || !dwc_otg_get_param_thr_ctl(core_if))) {
+ valid = 0;
+ } else if (val && ((dwc_otg_get_param_tx_thr_length(core_if) / (1 << val)) < 4)) {
+ valid = 0;
+ }
+ if (valid == 0) {
+ if (dwc_otg_param_initialized(core_if->core_params->ahb_thr_ratio)) {
+ printf("error: %d invalid for parameter ahb_thr_ratio. Chack HW configuration.\n", val);
+ }
+ retval = -1;
+ val = 0;
+ }
+
+ core_if->core_params->ahb_thr_ratio = val;
+ return retval;
+}
+int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->ahb_thr_ratio;
+}
+
+
+uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t *core_if)
+{
+ gotgctl_data_t otgctl;
+ otgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl);
+ return otgctl.b.hstnegscs;
+}
+
+uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t *core_if)
+{
+ gotgctl_data_t otgctl;
+ otgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl);
+ return otgctl.b.sesreqscs;
+}
+
+void dwc_otg_set_hnpreq(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ gotgctl_data_t otgctl;
+ otgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl);
+ otgctl.b.hnpreq = val;
+ dwc_write_reg32(&core_if->core_global_regs->gotgctl, otgctl.d32);
+}
+
+uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t *core_if)
+{
+ return core_if->snpsid;
+}
+
+uint32_t dwc_otg_get_mode(dwc_otg_core_if_t *core_if)
+{
+ gotgctl_data_t otgctl;
+ otgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl);
+ return otgctl.b.currmod;
+}
+
+uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t *core_if)
+{
+ gusbcfg_data_t usbcfg;
+ usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg);
+ return usbcfg.b.hnpcap;
+}
+
+void dwc_otg_set_hnpcapable(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ gusbcfg_data_t usbcfg;
+ usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg);
+ usbcfg.b.hnpcap = val;
+ dwc_write_reg32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);
+}
+
+uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t *core_if)
+{
+ gusbcfg_data_t usbcfg;
+ usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg);
+ return usbcfg.b.srpcap;
+}
+
+void dwc_otg_set_srpcapable(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ gusbcfg_data_t usbcfg;
+ usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg);
+ usbcfg.b.srpcap = val;
+ dwc_write_reg32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);
+}
+
+uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t *core_if)
+{
+ hprt0_data_t hprt0;
+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
+ return hprt0.b.prtconnsts;
+}
+
+uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t *core_if)
+{
+ hprt0_data_t hprt0;
+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
+ return hprt0.b.prtpwr;
+
+}
+
+void dwc_otg_set_prtpower(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ hprt0_data_t hprt0;
+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
+ hprt0.b.prtpwr = val;
+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+}
+
+uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t *core_if)
+{
+ hprt0_data_t hprt0;
+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
+ return hprt0.b.prtsusp;
+
+}
+
+void dwc_otg_set_prtsuspend(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ hprt0_data_t hprt0;
+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
+ hprt0.b.prtsusp = val;
+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+}
+
+void dwc_otg_set_prtresume(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ hprt0_data_t hprt0;
+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
+ hprt0.b.prtres = val;
+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+}
+
+uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t *core_if)
+{
+ glpmcfg_data_t lpmcfg;
+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
+
+ return lpmcfg.b.prt_sleep_sts;
+}
+
+uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t *core_if)
+{
+ glpmcfg_data_t lpmcfg;
+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
+ return lpmcfg.b.rem_wkup_en;
+}
+
+uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t *core_if)
+{
+ glpmcfg_data_t lpmcfg;
+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
+ return lpmcfg.b.appl_resp;
+}
+
+void dwc_otg_set_lpmresponse(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ glpmcfg_data_t lpmcfg;
+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
+ lpmcfg.b.appl_resp = val;
+ dwc_write_reg32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
+}
+
+uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t *core_if)
+{
+ glpmcfg_data_t lpmcfg;
+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
+ return lpmcfg.b.hsic_connect;
+}
+
+void dwc_otg_set_hsic_connect(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ glpmcfg_data_t lpmcfg;
+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
+ lpmcfg.b.hsic_connect = val;
+ dwc_write_reg32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
+}
+
+uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t *core_if)
+{
+ glpmcfg_data_t lpmcfg;
+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
+ return lpmcfg.b.inv_sel_hsic;
+
+}
+
+void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ glpmcfg_data_t lpmcfg;
+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
+ lpmcfg.b.inv_sel_hsic = val;
+ dwc_write_reg32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
+}
+
+uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t *core_if)
+{
+ return dwc_read_reg32(&core_if->core_global_regs->gotgctl);
+}
+
+void dwc_otg_set_gotgctl(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ dwc_write_reg32(&core_if->core_global_regs->gotgctl, val);
+}
+
+uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t *core_if)
+{
+ return dwc_read_reg32(&core_if->core_global_regs->gusbcfg);
+}
+
+void dwc_otg_set_gusbcfg(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ dwc_write_reg32(&core_if->core_global_regs->gusbcfg, val);
+}
+
+uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t *core_if)
+{
+ return dwc_read_reg32(&core_if->core_global_regs->grxfsiz);
+}
+
+void dwc_otg_set_grxfsiz(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ dwc_write_reg32(&core_if->core_global_regs->grxfsiz, val);
+}
+
+uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t *core_if)
+{
+ return dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz);
+}
+
+void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ dwc_write_reg32(&core_if->core_global_regs->gnptxfsiz, val);
+}
+
+uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t *core_if)
+{
+ return dwc_read_reg32(&core_if->core_global_regs->gpvndctl);
+}
+
+void dwc_otg_set_gpvndctl(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ dwc_write_reg32(&core_if->core_global_regs->gpvndctl, val);
+}
+
+uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t *core_if)
+{
+ return dwc_read_reg32(&core_if->core_global_regs->ggpio);
+}
+
+void dwc_otg_set_ggpio(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ dwc_write_reg32(&core_if->core_global_regs->ggpio, val);
+}
+
+uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t *core_if)
+{
+ return dwc_read_reg32(core_if->host_if->hprt0);
+
+}
+
+void dwc_otg_set_hprt0(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ dwc_write_reg32(core_if->host_if->hprt0, val);
+}
+
+uint32_t dwc_otg_get_guid(dwc_otg_core_if_t *core_if)
+{
+ return dwc_read_reg32(&core_if->core_global_regs->guid);
+}
+
+void dwc_otg_set_guid(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ dwc_write_reg32(&core_if->core_global_regs->guid, val);
+}
+
+uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t *core_if)
+{
+ return dwc_read_reg32(&core_if->core_global_regs->hptxfsiz);
+}
+
+
+static int dwc_otg_setup_params(dwc_otg_core_if_t *core_if)
+{
+ int i;
+ core_if->core_params = malloc(sizeof(*core_if->core_params));
+ if (!core_if->core_params) {
+ return -1;
+ }
+ dwc_otg_set_uninitialized((int32_t *) core_if->core_params,
+ sizeof(*core_if->core_params) /
+ sizeof(int32_t));
+ PDEBUG("Setting default values for core params\n");
+ dwc_otg_set_param_otg_cap(core_if, dwc_param_otg_cap_default);
+ dwc_otg_set_param_dma_enable(core_if, dwc_param_dma_enable_default);
+ dwc_otg_set_param_dma_desc_enable(core_if,
+ dwc_param_dma_desc_enable_default);
+ dwc_otg_set_param_opt(core_if, dwc_param_opt_default);
+ dwc_otg_set_param_dma_burst_size(core_if,
+ dwc_param_dma_burst_size_default);
+ dwc_otg_set_param_host_support_fs_ls_low_power(core_if,
+ dwc_param_host_support_fs_ls_low_power_default);
+ dwc_otg_set_param_enable_dynamic_fifo(core_if,
+ dwc_param_enable_dynamic_fifo_default);
+ dwc_otg_set_param_data_fifo_size(core_if,
+ dwc_param_data_fifo_size_default);
+ dwc_otg_set_param_dev_rx_fifo_size(core_if,
+ dwc_param_dev_rx_fifo_size_default);
+ dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if,
+ dwc_param_dev_nperio_tx_fifo_size_default);
+ dwc_otg_set_param_host_rx_fifo_size(core_if,
+ dwc_param_host_rx_fifo_size_default);
+ dwc_otg_set_param_host_nperio_tx_fifo_size(core_if,
+ dwc_param_host_nperio_tx_fifo_size_default);
+ dwc_otg_set_param_host_perio_tx_fifo_size(core_if,
+ dwc_param_host_perio_tx_fifo_size_default);
+ dwc_otg_set_param_max_transfer_size(core_if,
+ dwc_param_max_transfer_size_default);
+ dwc_otg_set_param_max_packet_count(core_if,
+ dwc_param_max_packet_count_default);
+ dwc_otg_set_param_host_channels(core_if,
+ dwc_param_host_channels_default);
+ dwc_otg_set_param_dev_endpoints(core_if,
+ dwc_param_dev_endpoints_default);
+ dwc_otg_set_param_phy_type(core_if, dwc_param_phy_type_default);
+ dwc_otg_set_param_speed(core_if, dwc_param_speed_default);
+ dwc_otg_set_param_host_ls_low_power_phy_clk(core_if,
+ dwc_param_host_ls_low_power_phy_clk_default);
+ dwc_otg_set_param_phy_ulpi_ddr(core_if, dwc_param_phy_ulpi_ddr_default);
+ dwc_otg_set_param_phy_ulpi_ext_vbus(core_if,
+ dwc_param_phy_ulpi_ext_vbus_default);
+ dwc_otg_set_param_phy_utmi_width(core_if,
+ dwc_param_phy_utmi_width_default);
+ dwc_otg_set_param_ts_dline(core_if, dwc_param_ts_dline_default);
+ dwc_otg_set_param_i2c_enable(core_if, dwc_param_i2c_enable_default);
+ dwc_otg_set_param_ulpi_fs_ls(core_if, dwc_param_ulpi_fs_ls_default);
+ dwc_otg_set_param_en_multiple_tx_fifo(core_if,
+ dwc_param_en_multiple_tx_fifo_default);
+ for (i = 0; i < 15; i++) {
+ dwc_otg_set_param_dev_perio_tx_fifo_size(core_if,
+ dwc_param_dev_perio_tx_fifo_size_default,
+ i);
+ }
+
+ for (i = 0; i < 15; i++) {
+ dwc_otg_set_param_dev_tx_fifo_size(core_if,
+ dwc_param_dev_tx_fifo_size_default,
+ i);
+ }
+ dwc_otg_set_param_thr_ctl(core_if, dwc_param_thr_ctl_default);
+ dwc_otg_set_param_mpi_enable(core_if, dwc_param_mpi_enable_default);
+ dwc_otg_set_param_pti_enable(core_if, dwc_param_pti_enable_default);
+ dwc_otg_set_param_lpm_enable(core_if, dwc_param_lpm_enable_default);
+ dwc_otg_set_param_ic_usb_cap(core_if, dwc_param_ic_usb_cap_default);
+ dwc_otg_set_param_tx_thr_length(core_if,
+ dwc_param_tx_thr_length_default);
+ dwc_otg_set_param_rx_thr_length(core_if,
+ dwc_param_rx_thr_length_default);
+ dwc_otg_set_param_ahb_thr_ratio(core_if, dwc_param_ahb_thr_ratio_default);
+ PDEBUG("Finished setting default values for core params\n");
+ return 0;
+}
+
+void dwc_otg_cil_init(dwc_otg_core_if_t *core_if, const uint32_t *reg_base_addr)
+{
+ dwc_otg_host_if_t *host_if = 0;
+ uint8_t *reg_base = (uint8_t *) reg_base_addr;
+ int i = 0;
+
+ PDEBUG("%s(%p)\n", __func__, reg_base_addr);
+
+ if (core_if == 0) {
+ PDEBUG("dwc_otg_core_if_t is NULL\n");
+ return;
+ }
+ core_if->core_global_regs = (dwc_otg_core_global_regs_t *) reg_base;
+
+ /*
+ * Allocate the Host Mode structures.
+ */
+ host_if = malloc(sizeof(dwc_otg_host_if_t));
+
+ if (host_if == 0) {
+ PDEBUG("Allocation of dwc_otg_host_if_t failed\n");
+ return;
+ }
+
+ host_if->host_global_regs = (dwc_otg_host_global_regs_t *)
+ (reg_base + DWC_OTG_HOST_GLOBAL_REG_OFFSET);
+
+ host_if->hprt0 =
+ (uint32_t *) (reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET);
+
+ for (i = 0; i < MAX_EPS_CHANNELS; i++) {
+ host_if->hc_regs[i] = (dwc_otg_hc_regs_t *)
+ (reg_base + DWC_OTG_HOST_CHAN_REGS_OFFSET +
+ (i * DWC_OTG_CHAN_REGS_OFFSET));
+ PDEBUG("hc_reg[%d]->hcchar=%p\n",
+ i, &host_if->hc_regs[i]->hcchar);
+ }
+
+ host_if->num_host_channels = MAX_EPS_CHANNELS;
+ core_if->host_if = host_if;
+
+ for (i = 0; i < MAX_EPS_CHANNELS; i++) {
+ core_if->data_fifo[i] =
+ (uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET +
+ (i * DWC_OTG_DATA_FIFO_SIZE));
+ PDEBUG("data_fifo[%d]=0x%08x\n",
+ i, (unsigned)core_if->data_fifo[i]);
+ }
+
+ core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET);
+
+ /*
+ * Store the contents of the hardware configuration registers here for
+ * easy access later.
+ */
+ core_if->hwcfg1.d32 =
+ dwc_read_reg32(&core_if->core_global_regs->ghwcfg1);
+ core_if->hwcfg2.d32 =
+ dwc_read_reg32(&core_if->core_global_regs->ghwcfg2);
+ core_if->hwcfg3.d32 =
+ dwc_read_reg32(&core_if->core_global_regs->ghwcfg3);
+ core_if->hwcfg4.d32 =
+ dwc_read_reg32(&core_if->core_global_regs->ghwcfg4);
+
+ PDEBUG("hwcfg1=%08x\n", core_if->hwcfg1.d32);
+ PDEBUG("hwcfg2=%08x\n", core_if->hwcfg2.d32);
+ PDEBUG("hwcfg3=%08x\n", core_if->hwcfg3.d32);
+ PDEBUG("hwcfg4=%08x\n", core_if->hwcfg4.d32);
+
+ core_if->hcfg.d32 =
+ dwc_read_reg32(&core_if->host_if->host_global_regs->hcfg);
+
+ PDEBUG("hcfg=%08x\n", core_if->hcfg.d32);
+ PDEBUG("dcfg=%08x\n", core_if->dcfg.d32);
+
+ PDEBUG("op_mode=%0x\n", core_if->hwcfg2.b.op_mode);
+ PDEBUG("arch=%0x\n", core_if->hwcfg2.b.architecture);
+ PDEBUG("num_dev_ep=%d\n", core_if->hwcfg2.b.num_dev_ep);
+ PDEBUG("num_host_chan=%d\n",
+ core_if->hwcfg2.b.num_host_chan);
+ PDEBUG("nonperio_tx_q_depth=0x%0x\n",
+ core_if->hwcfg2.b.nonperio_tx_q_depth);
+ PDEBUG("host_perio_tx_q_depth=0x%0x\n",
+ core_if->hwcfg2.b.host_perio_tx_q_depth);
+ PDEBUG("dev_token_q_depth=0x%0x\n",
+ core_if->hwcfg2.b.dev_token_q_depth);
+
+ PDEBUG("Total FIFO SZ=%d\n",
+ core_if->hwcfg3.b.dfifo_depth);
+ PDEBUG("xfer_size_cntr_width=%0x\n",
+ core_if->hwcfg3.b.xfer_size_cntr_width);
+
+ core_if->snpsid = dwc_read_reg32(&core_if->core_global_regs->gsnpsid);
+
+ printf("Core Release: %x.%x%x%x\n",
+ (core_if->snpsid >> 12 & 0xF),
+ (core_if->snpsid >> 8 & 0xF),
+ (core_if->snpsid >> 4 & 0xF), (core_if->snpsid & 0xF));
+
+ dwc_otg_setup_params(core_if);
+}
+
+/**
+ * Initializes the FSLSPClkSel field of the HCFG register depending on the PHY
+ * type.
+ */
+static void init_fslspclksel(dwc_otg_core_if_t *core_if)
+{
+ uint32_t val;
+ hcfg_data_t hcfg;
+
+ if (((core_if->hwcfg2.b.hs_phy_type == 2) &&
+ (core_if->hwcfg2.b.fs_phy_type == 1) &&
+ (core_if->core_params->ulpi_fs_ls)) ||
+ (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
+ /* Full speed PHY */
+ val = DWC_HCFG_48_MHZ;
+ } else {
+ /* High speed PHY running at full speed or high speed */
+ val = DWC_HCFG_30_60_MHZ;
+ }
+
+ PDEBUG("Initializing HCFG.FSLSPClkSel to 0x%1x\n", val);
+ hcfg.d32 = dwc_read_reg32(&core_if->host_if->host_global_regs->hcfg);
+ hcfg.b.fslspclksel = val;
+ dwc_write_reg32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32);
+}
+
+/**
+ * Flush a Tx FIFO.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param num Tx FIFO to flush.
+ */
+void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t *core_if, const int num)
+{
+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+ volatile grstctl_t greset = {.d32 = 0 };
+ int count = 0;
+
+ PDEBUG("Flush Tx FIFO %d\n", num);
+
+ greset.b.txfflsh = 1;
+ greset.b.txfnum = num;
+ dwc_write_reg32(&global_regs->grstctl, greset.d32);
+
+ do {
+ greset.d32 = dwc_read_reg32(&global_regs->grstctl);
+ if (++count > 10000) {
+ printf("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n",
+ __func__, greset.d32,
+ dwc_read_reg32(&global_regs->gnptxsts));
+ break;
+ }
+ udelay(1);
+ } while (greset.b.txfflsh == 1);
+
+ /* Wait for 3 PHY Clocks */
+ udelay(1);
+}
+
+/**
+ * Flush Rx FIFO.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ */
+void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t *core_if)
+{
+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+ volatile grstctl_t greset = {.d32 = 0 };
+ int count = 0;
+
+ PDEBUG("%s\n", __func__);
+ /*
+ *
+ */
+ greset.b.rxfflsh = 1;
+ dwc_write_reg32(&global_regs->grstctl, greset.d32);
+
+ do {
+ greset.d32 = dwc_read_reg32(&global_regs->grstctl);
+ if (++count > 10000) {
+ printf("%s() HANG! GRSTCTL=%0x\n", __func__,
+ greset.d32);
+ break;
+ }
+ udelay(1);
+ } while (greset.b.rxfflsh == 1);
+
+ /* Wait for 3 PHY Clocks */
+ udelay(1);
+}
+
+/**
+ * This function initializes the DWC_otg controller registers for
+ * host mode.
+ *
+ * This function flushes the Tx and Rx FIFOs and it flushes any entries in the
+ * request queues. Host channels are reset to ensure that they are ready for
+ * performing transfers.
+ *
+ * @param core_if Programming view of DWC_otg controller
+ *
+ */
+void dwc_otg_core_host_init(dwc_otg_core_if_t *core_if)
+{
+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+ dwc_otg_host_if_t *host_if = core_if->host_if;
+ dwc_otg_core_params_t *params = core_if->core_params;
+ hprt0_data_t hprt0 = {.d32 = 0 };
+ fifosize_data_t nptxfifosize;
+ fifosize_data_t ptxfifosize;
+ int i;
+ hcchar_data_t hcchar;
+ hcfg_data_t hcfg;
+ dwc_otg_hc_regs_t *hc_regs;
+ int num_channels;
+ gotgctl_data_t gotgctl = {.d32 = 0 };
+
+ PDEBUG("%s(%p)\n", __func__, core_if);
+
+ /* Restart the Phy Clock */
+ dwc_write_reg32(core_if->pcgcctl, 0);
+
+ /* Initialize Host Configuration Register */
+ init_fslspclksel(core_if);
+ if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {
+ hcfg.d32 = dwc_read_reg32(&host_if->host_global_regs->hcfg);
+ hcfg.b.fslssupp = 1;
+ dwc_write_reg32(&host_if->host_global_regs->hcfg, hcfg.d32);
+
+ }
+
+ if (core_if->core_params->dma_desc_enable) {
+ uint8_t op_mode = core_if->hwcfg2.b.op_mode;
+ if (!(core_if->hwcfg4.b.desc_dma && (core_if->snpsid >= OTG_CORE_REV_2_90a) &&
+ ((op_mode == DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) ||
+ (op_mode == DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) ||
+ (op_mode == DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG) ||
+ (op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST) ||
+ (op_mode == DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST)))) {
+
+ printf("Host can't operate in Descriptor DMA mode.\n"
+ "Either core version is below 2.90a or "
+ "GHWCFG2, GHWCFG4 registers' values do not allow Descriptor DMA in host mode.\n"
+ "To run the driver in Buffer DMA host mode set dma_desc_enable "
+ "module parameter to 0.\n");
+ return;
+ }
+ hcfg.d32 = dwc_read_reg32(&host_if->host_global_regs->hcfg);
+ hcfg.b.descdma = 1;
+ dwc_write_reg32(&host_if->host_global_regs->hcfg, hcfg.d32);
+ }
+
+ /* Configure data FIFO sizes */
+ if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
+ PDEBUG("Total FIFO Size=%d\n",
+ core_if->total_fifo_size);
+ PDEBUG("Rx FIFO Size=%d\n",
+ params->host_rx_fifo_size);
+ PDEBUG("NP Tx FIFO Size=%d\n",
+ params->host_nperio_tx_fifo_size);
+ PDEBUG("P Tx FIFO Size=%d\n",
+ params->host_perio_tx_fifo_size);
+
+ /* Rx FIFO */
+ PDEBUG("initial grxfsiz=%08x\n",
+ dwc_read_reg32(&global_regs->grxfsiz));
+ dwc_write_reg32(&global_regs->grxfsiz,
+ params->host_rx_fifo_size);
+ PDEBUG("new grxfsiz=%08x\n",
+ dwc_read_reg32(&global_regs->grxfsiz));
+
+ /* Non-periodic Tx FIFO */
+ PDEBUG("initial gnptxfsiz=%08x\n",
+ dwc_read_reg32(&global_regs->gnptxfsiz));
+ nptxfifosize.b.depth = params->host_nperio_tx_fifo_size;
+ nptxfifosize.b.startaddr = params->host_rx_fifo_size;
+ dwc_write_reg32(&global_regs->gnptxfsiz, nptxfifosize.d32);
+ PDEBUG("new gnptxfsiz=%08x\n",
+ dwc_read_reg32(&global_regs->gnptxfsiz));
+
+ /* Periodic Tx FIFO */
+ PDEBUG("initial hptxfsiz=%08x\n",
+ dwc_read_reg32(&global_regs->hptxfsiz));
+ ptxfifosize.b.depth = params->host_perio_tx_fifo_size;
+ ptxfifosize.b.startaddr =
+ nptxfifosize.b.startaddr + nptxfifosize.b.depth;
+ dwc_write_reg32(&global_regs->hptxfsiz, ptxfifosize.d32);
+ PDEBUG("new hptxfsiz=%08x\n",
+ dwc_read_reg32(&global_regs->hptxfsiz));
+ }
+
+ /* Clear Host Set HNP Enable in the OTG Control Register */
+ gotgctl.b.hstsethnpen = 1;
+ dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0);
+
+ /* Make sure the FIFOs are flushed. */
+ dwc_otg_flush_tx_fifo(core_if, 0x10 /* all Tx FIFOs */);
+ dwc_otg_flush_rx_fifo(core_if);
+
+ if (!core_if->core_params->dma_desc_enable) {
+ /* Flush out any leftover queued requests. */
+ num_channels = core_if->core_params->host_channels;
+
+ for (i = 0; i < num_channels; i++) {
+ hc_regs = core_if->host_if->hc_regs[i];
+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
+ hcchar.b.chen = 0;
+ hcchar.b.chdis = 1;
+ hcchar.b.epdir = 0;
+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
+ }
+
+ /* Halt all channels to put them into a known state. */
+ for (i = 0; i < num_channels; i++) {
+ int count = 0;
+ hc_regs = core_if->host_if->hc_regs[i];
+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
+ hcchar.b.chen = 1;
+ hcchar.b.chdis = 1;
+ hcchar.b.epdir = 0;
+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
+ PDEBUG("%s: Halt channel %d regs %p\n", __func__, i, hc_regs);
+ do {
+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
+ if (++count > 1000) {
+ printf
+ ("%s: Unable to clear halt on channel %d (timeout HCCHAR 0x%X @%p)\n",
+ __func__, i, hcchar.d32, &hc_regs->hcchar);
+ break;
+ }
+ udelay(1);
+ } while (hcchar.b.chen);
+ }
+ }
+
+ /* Turn on the vbus power. */
+ PDEBUG("Init: Port Power? op_state=%d\n", core_if->op_state);
+ if (core_if->op_state == A_HOST) {
+ hprt0.d32 = dwc_otg_read_hprt0(core_if);
+ PDEBUG("Init: Power Port (%d, %08x)\n", hprt0.b.prtpwr, hprt0.d32);
+ if (hprt0.b.prtpwr == 0) {
+ hprt0.b.prtpwr = 1;
+ dwc_write_reg32(host_if->hprt0, hprt0.d32);
+ }
+ }
+}
+
+/**
+ * Do core a soft reset of the core. Be careful with this because it
+ * resets all the internal state machines of the core.
+ */
+void dwc_otg_core_reset(dwc_otg_core_if_t *core_if)
+{
+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+ volatile grstctl_t greset = {.d32 = 0 };
+ int count = 0;
+
+ PDEBUG("%s\n", __func__);
+ /* Wait for AHB master IDLE state. */
+ do {
+ udelay(10);
+ greset.d32 = dwc_read_reg32(&global_regs->grstctl);
+ if (++count > 100000) {
+ printf("%s() HANG! AHB Idle GRSTCTL=%0x\n", __func__,
+ greset.d32);
+ return;
+ }
+ } while (greset.b.ahbidle == 0);
+
+ /* Core Soft Reset */
+ count = 0;
+ greset.b.csftrst = 1;
+ dwc_write_reg32(&global_regs->grstctl, greset.d32);
+ do {
+ greset.d32 = dwc_read_reg32(&global_regs->grstctl);
+ if (++count > 1000000) {
+ printf("%s() HANG! Soft Reset GRSTCTL=%0x\n",
+ __func__, greset.d32);
+ break;
+ }
+ udelay(1);
+ } while (greset.b.csftrst == 1);
+
+ /* Wait for 3 PHY Clocks */
+ udelay(100 * 1000);
+}
+
+
+
+/**
+ * This function initializes the DWC_otg controller registers and
+ * prepares the core for device mode or host mode operation.
+ *
+ * @param core_if Programming view of the DWC_otg controller
+ *
+ */
+void dwc_otg_core_init(dwc_otg_core_if_t *core_if)
+{
+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+ gahbcfg_data_t ahbcfg = {.d32 = 0 };
+ gusbcfg_data_t usbcfg = {.d32 = 0 };
+ gi2cctl_data_t i2cctl = {.d32 = 0 };
+
+ PDEBUG("dwc_otg_core_init(%p) regs at %p\n",
+ core_if, global_regs);
+
+ /* Common Initialization */
+
+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
+
+ /* Program the ULPI External VBUS bit if needed */
+ usbcfg.b.ulpi_ext_vbus_drv =
+ (core_if->core_params->phy_ulpi_ext_vbus ==
+ DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0;
+
+ /* Set external TS Dline pulsing */
+ usbcfg.b.term_sel_dl_pulse =
+ (core_if->core_params->ts_dline == 1) ? 1 : 0;
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+
+ /* Reset the Controller */
+ dwc_otg_core_reset(core_if);
+
+ /* Initialize parameters from Hardware configuration registers. */
+ core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth;
+ core_if->rx_fifo_size = dwc_read_reg32(&global_regs->grxfsiz);
+ core_if->nperio_tx_fifo_size =
+ dwc_read_reg32(&global_regs->gnptxfsiz) >> 16;
+
+ PDEBUG("Total FIFO SZ=%d\n", core_if->total_fifo_size);
+ PDEBUG("Rx FIFO SZ=%d\n", core_if->rx_fifo_size);
+ PDEBUG("NP Tx FIFO SZ=%d\n",
+ core_if->nperio_tx_fifo_size);
+
+ /* This programming sequence needs to happen in FS mode before any other
+ * programming occurs */
+ if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) &&
+ (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
+ /* If FS mode with FS PHY */
+
+ /* core_init() is now called on every switch so only call the
+ * following for the first time through. */
+ if (!core_if->phy_init_done) {
+ core_if->phy_init_done = 1;
+ PDEBUG("FS_PHY detected\n");
+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
+ usbcfg.b.physel = 1;
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+
+ /* Reset after a PHY select */
+ dwc_otg_core_reset(core_if);
+ }
+
+ /* Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. Also
+ * do this on HNP Dev/Host mode switches (done in dev_init and
+ * host_init). */
+ if (dwc_otg_is_host_mode(core_if)) {
+ init_fslspclksel(core_if);
+ }
+
+ if (core_if->core_params->i2c_enable) {
+ PDEBUG("FS_PHY Enabling I2c\n");
+ /* Program GUSBCFG.OtgUtmifsSel to I2C */
+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
+ usbcfg.b.otgutmifssel = 1;
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+
+ /* Program GI2CCTL.I2CEn */
+ i2cctl.d32 = dwc_read_reg32(&global_regs->gi2cctl);
+ i2cctl.b.i2cdevaddr = 1;
+ i2cctl.b.i2cen = 0;
+ dwc_write_reg32(&global_regs->gi2cctl, i2cctl.d32);
+ i2cctl.b.i2cen = 1;
+ dwc_write_reg32(&global_regs->gi2cctl, i2cctl.d32);
+ }
+
+ } /* endif speed == DWC_SPEED_PARAM_FULL */
+ else {
+ /* High speed PHY. */
+ if (!core_if->phy_init_done) {
+ core_if->phy_init_done = 1;
+ /* HS PHY parameters. These parameters are preserved
+ * during soft reset so only program the first time. Do
+ * a soft reset immediately after setting phyif. */
+ usbcfg.b.ulpi_utmi_sel = core_if->core_params->phy_type;
+ if (usbcfg.b.ulpi_utmi_sel == 1) {
+ PDEBUG(" ULPI interface \n");
+ /* ULPI interface */
+ usbcfg.b.phyif = 0;
+ usbcfg.b.ddrsel =
+ core_if->core_params->phy_ulpi_ddr;
+ } else {
+ PDEBUG(" UTMI+ interface \n");
+ /* UTMI+ interface */
+ if (core_if->core_params->phy_utmi_width == 16) {
+ usbcfg.b.phyif = 1;
+
+ } else {
+ usbcfg.b.phyif = 0;
+ }
+
+ }
+
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+ /* Reset after setting the PHY parameters */
+ dwc_otg_core_reset(core_if);
+ }
+ }
+
+ if ((core_if->hwcfg2.b.hs_phy_type == 2) &&
+ (core_if->hwcfg2.b.fs_phy_type == 1) &&
+ (core_if->core_params->ulpi_fs_ls)) {
+ PDEBUG("Setting ULPI FSLS\n");
+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
+ usbcfg.b.ulpi_fsls = 1;
+ usbcfg.b.ulpi_clk_sus_m = 1;
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+ } else {
+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
+ usbcfg.b.ulpi_fsls = 0;
+ usbcfg.b.ulpi_clk_sus_m = 0;
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+ }
+
+ /* Program the GAHBCFG Register. */
+ switch (core_if->hwcfg2.b.architecture) {
+
+ case DWC_SLAVE_ONLY_ARCH:
+ PDEBUG("Slave Only Mode\n");
+ ahbcfg.b.nptxfemplvl_txfemplvl =
+ DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
+ ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
+ core_if->dma_enable = 0;
+ core_if->dma_desc_enable = 0;
+ break;
+
+ case DWC_EXT_DMA_ARCH:
+ PDEBUG("External DMA Mode\n");
+ {
+ uint8_t brst_sz = core_if->core_params->dma_burst_size;
+ ahbcfg.b.hburstlen = 0;
+ while (brst_sz > 1) {
+ ahbcfg.b.hburstlen++;
+ brst_sz >>= 1;
+ }
+ }
+ core_if->dma_enable = (core_if->core_params->dma_enable != 0);
+ core_if->dma_desc_enable =
+ (core_if->core_params->dma_desc_enable != 0);
+ break;
+
+ case DWC_INT_DMA_ARCH:
+ PDEBUG("Internal DMA Mode\n");
+ /*ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR; */
+ ahbcfg.b.hburstlen = (1<<3)|(0<<0); /* WRESP=1, max 4 beats */
+ core_if->dma_enable = (core_if->core_params->dma_enable != 0);
+ core_if->dma_desc_enable =
+ (core_if->core_params->dma_desc_enable != 0);
+ break;
+
+ }
+ if (core_if->dma_enable) {
+ if (core_if->dma_desc_enable) {
+ PDEBUG("Using Descriptor DMA mode\n");
+ } else {
+ PDEBUG("Using Buffer DMA mode\n");
+
+ }
+ } else {
+ PDEBUG("Using Slave mode\n");
+ core_if->dma_desc_enable = 0;
+ }
+
+ ahbcfg.b.dmaenable = core_if->dma_enable;
+ PDEBUG("DMA enable: %d(%08x)\n", ahbcfg.b.dmaenable, ahbcfg.d32);
+ dwc_write_reg32(&global_regs->gahbcfg, ahbcfg.d32);
+
+ core_if->en_multiple_tx_fifo = core_if->hwcfg4.b.ded_fifo_en;
+
+ core_if->pti_enh_enable = core_if->core_params->pti_enable != 0;
+ core_if->multiproc_int_enable = core_if->core_params->mpi_enable;
+ PDEBUG("Periodic Transfer Interrupt Enhancement - %s\n",
+ ((core_if->pti_enh_enable) ? "enabled" : "disabled"));
+ PDEBUG("Multiprocessor Interrupt Enhancement - %s\n",
+ ((core_if->multiproc_int_enable) ? "enabled" : "disabled"));
+
+
+ ahbcfg.d32 = dwc_read_reg32(&global_regs->gahbcfg);
+
+ /*
+ * Program the GUSBCFG register.
+ */
+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
+
+ switch (core_if->hwcfg2.b.op_mode) {
+ case DWC_MODE_HNP_SRP_CAPABLE:
+ usbcfg.b.hnpcap = (core_if->core_params->otg_cap ==
+ DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);
+ usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
+ break;
+
+ case DWC_MODE_SRP_ONLY_CAPABLE:
+ usbcfg.b.hnpcap = 0;
+ usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
+ break;
+
+ case DWC_MODE_NO_HNP_SRP_CAPABLE:
+ usbcfg.b.hnpcap = 0;
+ usbcfg.b.srpcap = 0;
+ break;
+
+ case DWC_MODE_SRP_CAPABLE_DEVICE:
+ usbcfg.b.hnpcap = 0;
+ usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
+ break;
+
+ case DWC_MODE_NO_SRP_CAPABLE_DEVICE:
+ usbcfg.b.hnpcap = 0;
+ usbcfg.b.srpcap = 0;
+ break;
+
+ case DWC_MODE_SRP_CAPABLE_HOST:
+ usbcfg.b.hnpcap = 0;
+ usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
+ break;
+
+ case DWC_MODE_NO_SRP_CAPABLE_HOST:
+ usbcfg.b.hnpcap = 0;
+ usbcfg.b.srpcap = 0;
+ break;
+ }
+
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+
+ if (core_if->core_params->ic_usb_cap) {
+ gusbcfg_data_t gusbcfg = {.d32 = 0 };
+ gusbcfg.b.ic_usb_cap = 1;
+ dwc_modify_reg32(&core_if->core_global_regs->gusbcfg,
+ 0, gusbcfg.d32);
+ }
+
+ /* Do device or host intialization based on mode during PCD
+ * and HCD initialization */
+ if (dwc_otg_is_host_mode(core_if)) {
+ PDEBUG("Host Mode\n");
+ core_if->op_state = A_HOST;
+ }
+}
+
+/**
+ * Prepares a host channel for transferring packets to/from a specific
+ * endpoint. The HCCHARn register is set up with the characteristics specified
+ * in _hc. Host channel interrupts that may need to be serviced while this
+ * transfer is in progress are enabled.
+ *
+ * @param core_if Programming view of DWC_otg controller
+ * @param hc Information needed to initialize the host channel
+ */
+void dwc_otg_hc_init(dwc_otg_core_if_t *core_if, uint8_t hc_num,
+ uint8_t dev_addr, uint8_t ep_num, uint8_t ep_is_in,
+ uint8_t ep_type, uint16_t max_packet)
+{
+ hcintmsk_data_t hc_intr_mask;
+ hcchar_data_t hcchar;
+ hcsplt_data_t hcsplt;
+
+ dwc_otg_host_if_t *host_if = core_if->host_if;
+ dwc_otg_hc_regs_t *hc_regs = host_if->hc_regs[hc_num];
+
+ /* Clear old interrupt conditions for this host channel. */
+ hc_intr_mask.d32 = 0xFFFFFFFF;
+ hc_intr_mask.b.reserved14_31 = 0;
+ dwc_write_reg32(&hc_regs->hcint, hc_intr_mask.d32);
+
+ /*
+ * Program the HCCHARn register with the endpoint characteristics for
+ * the current transfer.
+ */
+ hcchar.d32 = 0;
+ hcchar.b.devaddr = dev_addr;
+ hcchar.b.epnum = ep_num;
+ hcchar.b.epdir = ep_is_in;
+ hcchar.b.lspddev = 0; /* XXX: low speed handler needed */
+ hcchar.b.eptype = ep_type;
+ hcchar.b.mps = max_packet;
+
+ dwc_write_reg32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32);
+
+ PDEBUG("%s: Channel %d\n", __func__, hc_num);
+ PDEBUG(" Dev Addr: %d\n", hcchar.b.devaddr);
+ PDEBUG(" Ep Num: %d\n", hcchar.b.epnum);
+ PDEBUG(" Is In: %d\n", hcchar.b.epdir);
+ PDEBUG(" Is Low Speed: %d\n", hcchar.b.lspddev);
+ PDEBUG(" Ep Type: %d\n", hcchar.b.eptype);
+ PDEBUG(" Max Pkt: %d\n", hcchar.b.mps);
+ PDEBUG(" Multi Cnt: %d\n", hcchar.b.multicnt);
+
+ /*
+ * Program the HCSPLIT register for SPLITs
+ */
+ hcsplt.d32 = 0;
+ dwc_write_reg32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32);
+}
diff --git a/drivers/usb/host/dwc2_otg.h b/drivers/usb/host/dwc2_otg.h
new file mode 100644
index 0000000..3974e1d
--- /dev/null
+++ b/drivers/usb/host/dwc2_otg.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2012 Oleksandr Tymoshenko <gonzo(a)freebsd.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef __DWC_OTG_H__
+#define __DWC_OTG_H__
+
+/* USB HUB CONSTANTS (not OHCI-specific; see hub.h, based on usb_ohci.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 */
+
+#define DWC_OTG_HC_PID_DATA0 0
+#define DWC_OTG_HC_PID_DATA2 1
+#define DWC_OTG_HC_PID_DATA1 2
+#define DWC_OTG_HC_PID_MDATA 3
+#define DWC_OTG_HC_PID_SETUP 3
+
+/** Macros defined for DWC OTG HW Release verison */
+#define OTG_CORE_REV_2_60a 0x4F54260A
+#define OTG_CORE_REV_2_71a 0x4F54271A
+#define OTG_CORE_REV_2_72a 0x4F54272A
+#define OTG_CORE_REV_2_80a 0x4F54280A
+#define OTG_CORE_REV_2_81a 0x4F54281A
+#define OTG_CORE_REV_2_90a 0x4F54290A
+
+#define DWC_OTG_EP_TYPE_CONTROL 0
+#define DWC_OTG_EP_TYPE_ISOC 1
+#define DWC_OTG_EP_TYPE_BULK 2
+#define DWC_OTG_EP_TYPE_INTR 3
+
+#define DWC_OTG_EP_SPEED_LOW 0
+#define DWC_OTG_EP_SPEED_FULL 1
+#define DWC_OTG_EP_SPEED_HIGH 2
+
+/** Maximum number of Periodic FIFOs */
+#define MAX_PERIO_FIFOS 15
+/** Maximum number of Periodic FIFOs */
+#define MAX_TX_FIFOS 15
+
+/** Maximum number of Endpoints/HostChannels */
+#define MAX_EPS_CHANNELS 16
+
+#endif /* __DWC_OTG_H__ */
diff --git a/drivers/usb/host/dwc2_otg_core_if.h b/drivers/usb/host/dwc2_otg_core_if.h
new file mode 100644
index 0000000..ee85fe5
--- /dev/null
+++ b/drivers/usb/host/dwc2_otg_core_if.h
@@ -0,0 +1,1001 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $
+ * $Revision: #4 $
+ * $Date: 2008/12/18 $
+ * $Change: 1155299 $
+ *
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * ========================================================================== */
+
+#ifndef __DWC_CORE_IF_H__
+#define __DWC_CORE_IF_H__
+
+/** @file
+ * This file defines DWC_OTG Core API
+ */
+
+/**
+ * The following parameters may be specified when starting the module. These
+ * parameters define how the DWC_otg controller should be configured.
+ */
+typedef struct dwc_otg_core_params {
+ int32_t opt;
+
+ /**
+ * Specifies the OTG capabilities. The driver will automatically
+ * detect the value for this parameter if none is specified.
+ * 0 - HNP and SRP capable (default)
+ * 1 - SRP Only capable
+ * 2 - No HNP/SRP capable
+ */
+ int32_t otg_cap;
+
+ /**
+ * Specifies whether to use slave or DMA mode for accessing the data
+ * FIFOs. The driver will automatically detect the value for this
+ * parameter if none is specified.
+ * 0 - Slave
+ * 1 - DMA (default, if available)
+ */
+ int32_t dma_enable;
+
+ /**
+ * When DMA mode is enabled specifies whether to use address DMA or DMA Descritor mode for accessing the data
+ * FIFOs in device mode. The driver will automatically detect the value for this
+ * parameter if none is specified.
+ * 0 - address DMA
+ * 1 - DMA Descriptor(default, if available)
+ */
+ int32_t dma_desc_enable;
+ /** The DMA Burst size (applicable only for External DMA
+ * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)
+ */
+ int32_t dma_burst_size; /* Translate this to GAHBCFG values */
+
+ /**
+ * Specifies the maximum speed of operation in host and device mode.
+ * The actual speed depends on the speed of the attached device and
+ * the value of phy_type. The actual speed depends on the speed of the
+ * attached device.
+ * 0 - High Speed (default)
+ * 1 - Full Speed
+ */
+ int32_t speed;
+ /** Specifies whether low power mode is supported when attached
+ * to a Full Speed or Low Speed device in host mode.
+ * 0 - Don't support low power mode (default)
+ * 1 - Support low power mode
+ */
+ int32_t host_support_fs_ls_low_power;
+
+ /** Specifies the PHY clock rate in low power mode when connected to a
+ * Low Speed device in host mode. This parameter is applicable only if
+ * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS
+ * then defaults to 6 MHZ otherwise 48 MHZ.
+ *
+ * 0 - 48 MHz
+ * 1 - 6 MHz
+ */
+ int32_t host_ls_low_power_phy_clk;
+
+ /**
+ * 0 - Use cC FIFO size parameters
+ * 1 - Allow dynamic FIFO sizing (default)
+ */
+ int32_t enable_dynamic_fifo;
+
+ /** Total number of 4-byte words in the data FIFO memory. This
+ * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic
+ * Tx FIFOs.
+ * 32 to 32768 (default 8192)
+ * Note: The total FIFO memory depth in the FPGA configuration is 8192.
+ */
+ int32_t data_fifo_size;
+
+ /** Number of 4-byte words in the Rx FIFO in device mode when dynamic
+ * FIFO sizing is enabled.
+ * 16 to 32768 (default 1064)
+ */
+ int32_t dev_rx_fifo_size;
+
+ /** Number of 4-byte words in the non-periodic Tx FIFO in device mode
+ * when dynamic FIFO sizing is enabled.
+ * 16 to 32768 (default 1024)
+ */
+ int32_t dev_nperio_tx_fifo_size;
+
+ /** Number of 4-byte words in each of the periodic Tx FIFOs in device
+ * mode when dynamic FIFO sizing is enabled.
+ * 4 to 768 (default 256)
+ */
+ uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];
+
+ /** Number of 4-byte words in the Rx FIFO in host mode when dynamic
+ * FIFO sizing is enabled.
+ * 16 to 32768 (default 1024)
+ */
+ int32_t host_rx_fifo_size;
+
+ /** Number of 4-byte words in the non-periodic Tx FIFO in host mode
+ * when Dynamic FIFO sizing is enabled in the core.
+ * 16 to 32768 (default 1024)
+ */
+ int32_t host_nperio_tx_fifo_size;
+
+ /** Number of 4-byte words in the host periodic Tx FIFO when dynamic
+ * FIFO sizing is enabled.
+ * 16 to 32768 (default 1024)
+ */
+ int32_t host_perio_tx_fifo_size;
+
+ /** The maximum transfer size supported in bytes.
+ * 2047 to 65535 (default 65535)
+ */
+ int32_t max_transfer_size;
+
+ /** The maximum number of packets in a transfer.
+ * 15 to 511 (default 511)
+ */
+ int32_t max_packet_count;
+
+ /** The number of host channel registers to use.
+ * 1 to 16 (default 12)
+ * Note: The FPGA configuration supports a maximum of 12 host channels.
+ */
+ int32_t host_channels;
+
+ /** The number of endpoints in addition to EP0 available for device
+ * mode operations.
+ * 1 to 15 (default 6 IN and OUT)
+ * Note: The FPGA configuration supports a maximum of 6 IN and OUT
+ * endpoints in addition to EP0.
+ */
+ int32_t dev_endpoints;
+
+ /**
+ * Specifies the type of PHY interface to use. By default, the driver
+ * will automatically detect the phy_type.
+ *
+ * 0 - Full Speed PHY
+ * 1 - UTMI+ (default)
+ * 2 - ULPI
+ */
+ int32_t phy_type;
+
+ /**
+ * Specifies the UTMI+ Data Width. This parameter is
+ * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
+ * PHY_TYPE, this parameter indicates the data width between
+ * the MAC and the ULPI Wrapper.) Also, this parameter is
+ * applicable only if the OTG_HSPHY_WIDTH cC parameter was set
+ * to "8 and 16 bits", meaning that the core has been
+ * configured to work at either data path width.
+ *
+ * 8 or 16 bits (default 16)
+ */
+ int32_t phy_utmi_width;
+
+ /**
+ * Specifies whether the ULPI operates at double or single
+ * data rate. This parameter is only applicable if PHY_TYPE is
+ * ULPI.
+ *
+ * 0 - single data rate ULPI interface with 8 bit wide data
+ * bus (default)
+ * 1 - double data rate ULPI interface with 4 bit wide data
+ * bus
+ */
+ int32_t phy_ulpi_ddr;
+
+ /**
+ * Specifies whether to use the internal or external supply to
+ * drive the vbus with a ULPI phy.
+ */
+ int32_t phy_ulpi_ext_vbus;
+
+ /**
+ * Specifies whether to use the I2Cinterface for full speed PHY. This
+ * parameter is only applicable if PHY_TYPE is FS.
+ * 0 - No (default)
+ * 1 - Yes
+ */
+ int32_t i2c_enable;
+
+ int32_t ulpi_fs_ls;
+
+ int32_t ts_dline;
+
+ /**
+ * Specifies whether dedicated transmit FIFOs are
+ * enabled for non periodic IN endpoints in device mode
+ * 0 - No
+ * 1 - Yes
+ */
+ int32_t en_multiple_tx_fifo;
+
+ /** Number of 4-byte words in each of the Tx FIFOs in device
+ * mode when dynamic FIFO sizing is enabled.
+ * 4 to 768 (default 256)
+ */
+ uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];
+
+ /** Thresholding enable flag-
+ * bit 0 - enable non-ISO Tx thresholding
+ * bit 1 - enable ISO Tx thresholding
+ * bit 2 - enable Rx thresholding
+ */
+ uint32_t thr_ctl;
+
+ /** Thresholding length for Tx
+ * FIFOs in 32 bit DWORDs
+ */
+ uint32_t tx_thr_length;
+
+ /** Thresholding length for Rx
+ * FIFOs in 32 bit DWORDs
+ */
+ uint32_t rx_thr_length;
+
+ /**
+ * Specifies whether LPM (Link Power Management) support is enabled
+ */
+ int32_t lpm_enable;
+
+ /** Per Transfer Interrupt
+ * mode enable flag
+ * 1 - Enabled
+ * 0 - Disabled
+ */
+ int32_t pti_enable;
+
+ /** Multi Processor Interrupt
+ * mode enable flag
+ * 1 - Enabled
+ * 0 - Disabled
+ */
+ int32_t mpi_enable;
+
+ /** IS_USB Capability
+ * 1 - Enabled
+ * 0 - Disabled
+ */
+ int32_t ic_usb_cap;
+
+ /** AHB Threshold Ratio
+ * 2'b00 AHB Threshold = MAC Threshold
+ * 2'b01 AHB Threshold = 1/2 MAC Threshold
+ * 2'b10 AHB Threshold = 1/4 MAC Threshold
+ * 2'b11 AHB Threshold = 1/8 MAC Threshold
+ */
+ int32_t ahb_thr_ratio;
+
+} dwc_otg_core_params_t;
+
+/**
+ * The <code>dwc_otg_core_if</code> structure contains information needed to manage
+ * the DWC_otg controller acting in either host or device mode. It
+ * represents the programming view of the controller as a whole.
+ */
+struct dwc_otg_core_if {
+ /** Parameters that define how the core should be configured.*/
+ dwc_otg_core_params_t *core_params;
+
+ /** Core Global registers starting at offset 000h. */
+ dwc_otg_core_global_regs_t *core_global_regs;
+
+ /** Host-specific information */
+ dwc_otg_host_if_t *host_if;
+
+ /** Value from SNPSID register */
+ uint32_t snpsid;
+
+ /*
+ * Set to 1 if the core PHY interface bits in USBCFG have been
+ * initialized.
+ */
+ uint8_t phy_init_done;
+
+ /* Common configuration information */
+ /** Power and Clock Gating Control Register */
+ volatile uint32_t *pcgcctl;
+#define DWC_OTG_PCGCCTL_OFFSET 0xE00
+
+ /** Push/pop addresses for endpoints or host channels.*/
+ uint32_t *data_fifo[MAX_EPS_CHANNELS];
+#define DWC_OTG_DATA_FIFO_OFFSET 0x1000
+#define DWC_OTG_DATA_FIFO_SIZE 0x1000
+
+ /** Total RAM for FIFOs (Bytes) */
+ uint16_t total_fifo_size;
+ /** Size of Rx FIFO (Bytes) */
+ uint16_t rx_fifo_size;
+ /** Size of Non-periodic Tx FIFO (Bytes) */
+ uint16_t nperio_tx_fifo_size;
+
+ /** 1 if DMA is enabled, 0 otherwise. */
+ uint8_t dma_enable;
+
+ /** 1 if DMA descriptor is enabled, 0 otherwise. */
+ uint8_t dma_desc_enable;
+
+ /** 1 if PTI Enhancement mode is enabled, 0 otherwise. */
+ uint8_t pti_enh_enable;
+
+ /** 1 if MPI Enhancement mode is enabled, 0 otherwise. */
+ uint8_t multiproc_int_enable;
+
+ /** 1 if dedicated Tx FIFOs are enabled, 0 otherwise. */
+ uint8_t en_multiple_tx_fifo;
+
+ /** Set to 1 if multiple packets of a high-bandwidth transfer is in
+ * process of being queued */
+ uint8_t queuing_high_bandwidth;
+
+ /** Hardware Configuration -- stored here for convenience.*/
+ hwcfg1_data_t hwcfg1;
+ hwcfg2_data_t hwcfg2;
+ hwcfg3_data_t hwcfg3;
+ hwcfg4_data_t hwcfg4;
+
+ /** Host and Device Configuration -- stored here for convenience.*/
+ hcfg_data_t hcfg;
+
+ /** The operational State, during transations
+ * (a_host>>a_peripherial and b_device=>b_host) this may not
+ * match the core but allows the software to determine
+ * transitions.
+ */
+ uint8_t op_state;
+
+ /**
+ * Set to 1 if the HCD needs to be restarted on a session request
+ * interrupt. This is required if no connector ID status change has
+ * occurred since the HCD was last disconnected.
+ */
+ uint8_t restart_hcd_on_session_req;
+
+ /** HCD callbacks */
+ /** A-Device is a_host */
+#define A_HOST (1)
+ /** A-Device is a_suspend */
+#define A_SUSPEND (2)
+ /** A-Device is a_peripherial */
+#define A_PERIPHERAL (3)
+ /** B-Device is operating as a Peripheral. */
+#define B_PERIPHERAL (4)
+ /** B-Device is operating as a Host. */
+#define B_HOST (5)
+
+ /** Device mode Periodic Tx FIFO Mask */
+ uint32_t p_tx_msk;
+ /** Device mode Periodic Tx FIFO Mask */
+ uint32_t tx_msk;
+};
+
+typedef struct dwc_otg_core_if dwc_otg_core_if_t;
+
+extern void dwc_otg_cil_init(dwc_otg_core_if_t *_core_if, const uint32_t *_reg_base_addr);
+extern void dwc_otg_core_init(dwc_otg_core_if_t *_core_if);
+extern void dwc_otg_cil_remove(dwc_otg_core_if_t *_core_if);
+
+extern void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t *_core_if);
+extern void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t *_core_if);
+
+extern uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t *_core_if);
+extern uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t *_core_if);
+
+extern uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t *core_if);
+
+/** This function should be called on every hardware interrupt. */
+extern int32_t dwc_otg_handle_common_intr(dwc_otg_core_if_t *_core_if);
+
+/* Register access functions */
+void dwc_write_reg32(volatile uint32_t *addr, uint32_t value);
+uint32_t dwc_read_reg32(volatile uint32_t *addr);
+
+/** @name OTG Core Parameters */
+/** @{ */
+
+/**
+ * Specifies the OTG capabilities. The driver will automatically
+ * detect the value for this parameter if none is specified.
+ * 0 - HNP and SRP capable (default)
+ * 1 - SRP Only capable
+ * 2 - No HNP/SRP capable
+ */
+extern int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t *core_if, int32_t val);
+extern int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t *core_if);
+#define DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE 0
+#define DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE 1
+#define DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE 2
+#define dwc_param_otg_cap_default DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE
+
+extern int dwc_otg_set_param_opt(dwc_otg_core_if_t *core_if, int32_t val);
+extern int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t *core_if);
+#define dwc_param_opt_default 1
+
+/**
+ * Specifies whether to use slave or DMA mode for accessing the data
+ * FIFOs. The driver will automatically detect the value for this
+ * parameter if none is specified.
+ * 0 - Slave
+ * 1 - DMA (default, if available)
+ */
+extern int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t *core_if);
+#define dwc_param_dma_enable_default 1
+
+/**
+ * When DMA mode is enabled specifies whether to use
+ * address DMA or DMA Descritor mode for accessing the data
+ * FIFOs in device mode. The driver will automatically detect
+ * the value for this parameter if none is specified.
+ * 0 - address DMA
+ * 1 - DMA Descriptor(default, if available)
+ */
+extern int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t *core_if);
+#define dwc_param_dma_desc_enable_default 0 /* Broadcom BCM2708 */
+
+/** The DMA Burst size (applicable only for External DMA
+ * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)
+ */
+extern int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t *core_if);
+#define dwc_param_dma_burst_size_default 32
+
+/**
+ * Specifies the maximum speed of operation in host and device mode.
+ * The actual speed depends on the speed of the attached device and
+ * the value of phy_type. The actual speed depends on the speed of the
+ * attached device.
+ * 0 - High Speed (default)
+ * 1 - Full Speed
+ */
+extern int dwc_otg_set_param_speed(dwc_otg_core_if_t *core_if, int32_t val);
+extern int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t *core_if);
+#define dwc_param_speed_default 0
+#define DWC_SPEED_PARAM_HIGH 0
+#define DWC_SPEED_PARAM_FULL 1
+
+/** Specifies whether low power mode is supported when attached
+ * to a Full Speed or Low Speed device in host mode.
+ * 0 - Don't support low power mode (default)
+ * 1 - Support low power mode
+ */
+extern int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *
+ core_if, int32_t val);
+extern int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t
+ *core_if);
+#define dwc_param_host_support_fs_ls_low_power_default 0
+
+/** Specifies the PHY clock rate in low power mode when connected to a
+ * Low Speed device in host mode. This parameter is applicable only if
+ * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS
+ * then defaults to 6 MHZ otherwise 48 MHZ.
+ *
+ * 0 - 48 MHz
+ * 1 - 6 MHz
+ */
+extern int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *
+ core_if, int32_t val);
+extern int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *
+ core_if);
+#define dwc_param_host_ls_low_power_phy_clk_default 0
+#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0
+#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1
+
+/**
+ * 0 - Use cC FIFO size parameters
+ * 1 - Allow dynamic FIFO sizing (default)
+ */
+extern int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t *
+ core_if);
+#define dwc_param_enable_dynamic_fifo_default 1
+
+/** Total number of 4-byte words in the data FIFO memory. This
+ * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic
+ * Tx FIFOs.
+ * 32 to 32768 (default 8192)
+ * Note: The total FIFO memory depth in the FPGA configuration is 8192.
+ */
+extern int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t *core_if);
+#define dwc_param_data_fifo_size_default 0xFF0 /* Broadcom BCM2708 */
+
+/** Number of 4-byte words in the Rx FIFO in device mode when dynamic
+ * FIFO sizing is enabled.
+ * 16 to 32768 (default 1064)
+ */
+extern int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t *core_if);
+#define dwc_param_dev_rx_fifo_size_default 1064
+
+/** Number of 4-byte words in the non-periodic Tx FIFO in device mode
+ * when dynamic FIFO sizing is enabled.
+ * 16 to 32768 (default 1024)
+ */
+extern int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *
+ core_if, int32_t val);
+extern int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *
+ core_if);
+#define dwc_param_dev_nperio_tx_fifo_size_default 1024
+
+/** Number of 4-byte words in each of the periodic Tx FIFOs in device
+ * mode when dynamic FIFO sizing is enabled.
+ * 4 to 768 (default 256)
+ */
+extern int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t *core_if,
+ int32_t val, int fifo_num);
+extern int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t *
+ core_if, int fifo_num);
+#define dwc_param_dev_perio_tx_fifo_size_default 256
+
+/** Number of 4-byte words in the Rx FIFO in host mode when dynamic
+ * FIFO sizing is enabled.
+ * 16 to 32768 (default 1024)
+ */
+extern int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t *core_if);
+#define dwc_param_host_rx_fifo_size_default 774 /* Broadcom BCM2708 */
+
+/** Number of 4-byte words in the non-periodic Tx FIFO in host mode
+ * when Dynamic FIFO sizing is enabled in the core.
+ * 16 to 32768 (default 1024)
+ */
+extern int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *
+ core_if, int32_t val);
+extern int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *
+ core_if);
+#define dwc_param_host_nperio_tx_fifo_size_default 0x100 /* Broadcom BCM2708 */
+
+/** Number of 4-byte words in the host periodic Tx FIFO when dynamic
+ * FIFO sizing is enabled.
+ * 16 to 32768 (default 1024)
+ */
+extern int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *
+ core_if, int32_t val);
+extern int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *
+ core_if);
+#define dwc_param_host_perio_tx_fifo_size_default 0x200 /* Broadcom BCM2708 */
+
+/** The maximum transfer size supported in bytes.
+ * 2047 to 65535 (default 65535)
+ */
+extern int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t *core_if);
+#define dwc_param_max_transfer_size_default 65535
+
+/** The maximum number of packets in a transfer.
+ * 15 to 511 (default 511)
+ */
+extern int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t *core_if);
+#define dwc_param_max_packet_count_default 511
+
+/** The number of host channel registers to use.
+ * 1 to 16 (default 12)
+ * Note: The FPGA configuration supports a maximum of 12 host channels.
+ */
+extern int dwc_otg_set_param_host_channels(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t *core_if);
+#define dwc_param_host_channels_default 12
+
+/** The number of endpoints in addition to EP0 available for device
+ * mode operations.
+ * 1 to 15 (default 6 IN and OUT)
+ * Note: The FPGA configuration supports a maximum of 6 IN and OUT
+ * endpoints in addition to EP0.
+ */
+extern int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t *core_if);
+#define dwc_param_dev_endpoints_default 6
+
+/**
+ * Specifies the type of PHY interface to use. By default, the driver
+ * will automatically detect the phy_type.
+ *
+ * 0 - Full Speed PHY
+ * 1 - UTMI+ (default)
+ * 2 - ULPI
+ */
+extern int dwc_otg_set_param_phy_type(dwc_otg_core_if_t *core_if, int32_t val);
+extern int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t *core_if);
+#define DWC_PHY_TYPE_PARAM_FS 0
+#define DWC_PHY_TYPE_PARAM_UTMI 1
+#define DWC_PHY_TYPE_PARAM_ULPI 2
+#define dwc_param_phy_type_default DWC_PHY_TYPE_PARAM_UTMI
+
+/**
+ * Specifies the UTMI+ Data Width. This parameter is
+ * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
+ * PHY_TYPE, this parameter indicates the data width between
+ * the MAC and the ULPI Wrapper.) Also, this parameter is
+ * applicable only if the OTG_HSPHY_WIDTH cC parameter was set
+ * to "8 and 16 bits", meaning that the core has been
+ * configured to work at either data path width.
+ *
+ * 8 or 16 bits (default 16)
+ */
+extern int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t *core_if);
+#define dwc_param_phy_utmi_width_default 8 /* Broadcom BCM2708 */
+
+/**
+ * Specifies whether the ULPI operates at double or single
+ * data rate. This parameter is only applicable if PHY_TYPE is
+ * ULPI.
+ *
+ * 0 - single data rate ULPI interface with 8 bit wide data
+ * bus (default)
+ * 1 - double data rate ULPI interface with 4 bit wide data
+ * bus
+ */
+extern int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t *core_if);
+#define dwc_param_phy_ulpi_ddr_default 0
+
+/**
+ * Specifies whether to use the internal or external supply to
+ * drive the vbus with a ULPI phy.
+ */
+extern int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t *core_if);
+#define DWC_PHY_ULPI_INTERNAL_VBUS 0
+#define DWC_PHY_ULPI_EXTERNAL_VBUS 1
+#define dwc_param_phy_ulpi_ext_vbus_default DWC_PHY_ULPI_INTERNAL_VBUS
+
+/**
+ * Specifies whether to use the I2Cinterface for full speed PHY. This
+ * parameter is only applicable if PHY_TYPE is FS.
+ * 0 - No (default)
+ * 1 - Yes
+ */
+extern int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t *core_if);
+#define dwc_param_i2c_enable_default 0
+
+extern int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t *core_if);
+#define dwc_param_ulpi_fs_ls_default 0
+
+extern int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t *core_if, int32_t val);
+extern int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t *core_if);
+#define dwc_param_ts_dline_default 0
+
+/**
+ * Specifies whether dedicated transmit FIFOs are
+ * enabled for non periodic IN endpoints in device mode
+ * 0 - No
+ * 1 - Yes
+ */
+extern int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t *
+ core_if);
+#define dwc_param_en_multiple_tx_fifo_default 1
+
+/** Number of 4-byte words in each of the Tx FIFOs in device
+ * mode when dynamic FIFO sizing is enabled.
+ * 4 to 768 (default 256)
+ */
+extern int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t *core_if,
+ int fifo_num, int32_t val);
+extern int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t *core_if,
+ int fifo_num);
+#define dwc_param_dev_tx_fifo_size_default 256
+
+/** Thresholding enable flag-
+ * bit 0 - enable non-ISO Tx thresholding
+ * bit 1 - enable ISO Tx thresholding
+ * bit 2 - enable Rx thresholding
+ */
+extern int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t *core_if, int32_t val);
+extern int32_t dwc_otg_get_thr_ctl(dwc_otg_core_if_t *core_if, int fifo_num);
+#define dwc_param_thr_ctl_default 0
+
+/** Thresholding length for Tx
+ * FIFOs in 32 bit DWORDs
+ */
+extern int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_tx_thr_length(dwc_otg_core_if_t *core_if);
+#define dwc_param_tx_thr_length_default 64
+
+/** Thresholding length for Rx
+ * FIFOs in 32 bit DWORDs
+ */
+extern int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_rx_thr_length(dwc_otg_core_if_t *core_if);
+#define dwc_param_rx_thr_length_default 64
+
+/**
+ * Specifies whether LPM (Link Power Management) support is enabled
+ */
+extern int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t *core_if);
+#define dwc_param_lpm_enable_default 0
+
+/**
+ * Specifies whether PTI enhancement is enabled
+ */
+extern int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t *core_if);
+#define dwc_param_pti_enable_default 0
+
+/**
+ * Specifies whether MPI enhancement is enabled
+ */
+extern int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t *core_if);
+#define dwc_param_mpi_enable_default 0
+
+/**
+ * Specifies whether IC_USB capability is enabled
+ */
+extern int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t *core_if);
+#define dwc_param_ic_usb_cap_default 0
+
+extern int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t *core_if, int32_t val);
+extern int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t *core_if);
+#define dwc_param_ahb_thr_ratio_default 0
+
+/** @} */
+
+/** @name Access to registers and bit-fields */
+
+/**
+ * Dump core registers and SPRAM
+ */
+extern void dwc_otg_dump_dev_registers(dwc_otg_core_if_t *_core_if);
+extern void dwc_otg_dump_spram(dwc_otg_core_if_t *_core_if);
+extern void dwc_otg_dump_host_registers(dwc_otg_core_if_t *_core_if);
+extern void dwc_otg_dump_global_registers(dwc_otg_core_if_t *_core_if);
+
+/**
+ * Get host negotiation status.
+ */
+extern uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t *core_if);
+
+/**
+ * Get srp status
+ */
+extern uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t *core_if);
+
+/**
+ * Set hnpreq bit in the GOTGCTL register.
+ */
+extern void dwc_otg_set_hnpreq(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * Get Content of SNPSID register.
+ */
+extern uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t *core_if);
+
+/**
+ * Get current mode.
+ * Returns 0 if in device mode, and 1 if in host mode.
+ */
+extern uint32_t dwc_otg_get_mode(dwc_otg_core_if_t *core_if);
+
+/**
+ * Get value of hnpcapable field in the GUSBCFG register
+ */
+extern uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t *core_if);
+/**
+ * Set value of hnpcapable field in the GUSBCFG register
+ */
+extern void dwc_otg_set_hnpcapable(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * Get value of srpcapable field in the GUSBCFG register
+ */
+extern uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t *core_if);
+/**
+ * Set value of srpcapable field in the GUSBCFG register
+ */
+extern void dwc_otg_set_srpcapable(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * Get value of devspeed field in the DCFG register
+ */
+extern uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t *core_if);
+/**
+ * Set value of devspeed field in the DCFG register
+ */
+extern void dwc_otg_set_devspeed(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * Get the value of busconnected field from the HPRT0 register
+ */
+extern uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t *core_if);
+
+/**
+ * Gets the device enumeration Speed.
+ */
+extern uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t *core_if);
+
+/**
+ * Get value of prtpwr field from the HPRT0 register
+ */
+extern uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t *core_if);
+/**
+ * Set value of prtpwr field from the HPRT0 register
+ */
+extern void dwc_otg_set_prtpower(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * Get value of prtsusp field from the HPRT0 regsiter
+ */
+extern uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t *core_if);
+/**
+ * Set value of prtpwr field from the HPRT0 register
+ */
+extern void dwc_otg_set_prtsuspend(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * Set value of prtres field from the HPRT0 register
+ *FIXME Remove?
+ */
+extern void dwc_otg_set_prtresume(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * Get value of rmtwkupsig bit in DCTL register
+ */
+extern uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t *core_if);
+
+/**
+ * Get value of prt_sleep_sts field from the GLPMCFG register
+ */
+extern uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t *core_if);
+
+/**
+ * Get value of rem_wkup_en field from the GLPMCFG register
+ */
+extern uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t *core_if);
+
+/**
+ * Get value of appl_resp field from the GLPMCFG register
+ */
+extern uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t *core_if);
+/**
+ * Set value of appl_resp field from the GLPMCFG register
+ */
+extern void dwc_otg_set_lpmresponse(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * Get value of hsic_connect field from the GLPMCFG register
+ */
+extern uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t *core_if);
+/**
+ * Set value of hsic_connect field from the GLPMCFG register
+ */
+extern void dwc_otg_set_hsic_connect(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * Get value of inv_sel_hsic field from the GLPMCFG register.
+ */
+extern uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t *core_if);
+/**
+ * Set value of inv_sel_hsic field from the GLPMFG register.
+ */
+extern void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/*
+ * Some functions for accessing registers
+ */
+
+/**
+ * GOTGCTL register
+ */
+extern uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t *core_if);
+extern void dwc_otg_set_gotgctl(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * GUSBCFG register
+ */
+extern uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t *core_if);
+extern void dwc_otg_set_gusbcfg(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * GRXFSIZ register
+ */
+extern uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t *core_if);
+extern void dwc_otg_set_grxfsiz(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * GNPTXFSIZ register
+ */
+extern uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t *core_if);
+extern void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t *core_if, uint32_t val);
+
+extern uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t *core_if);
+extern void dwc_otg_set_gpvndctl(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * GGPIO register
+ */
+extern uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t *core_if);
+extern void dwc_otg_set_ggpio(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * GUID register
+ */
+extern uint32_t dwc_otg_get_guid(dwc_otg_core_if_t *core_if);
+extern void dwc_otg_set_guid(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * HPRT0 register
+ */
+extern uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t *core_if);
+extern void dwc_otg_set_hprt0(dwc_otg_core_if_t *core_if, uint32_t val);
+extern uint32_t dwc_otg_read_hprt0(dwc_otg_core_if_t *_core_if);
+
+/**
+ * GHPTXFSIZE
+ */
+extern uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t *core_if);
+
+/**
+ * Init channel @hc_num with provided parameters
+ */
+extern void dwc_otg_hc_init(dwc_otg_core_if_t *core_if, uint8_t hc_num,
+ uint8_t dev_addr, uint8_t ep_num, uint8_t ep_is_in,
+ uint8_t ep_type, uint16_t max_packet);
+
+
+/**
+ * Host controller initialization part
+ */
+extern void dwc_otg_core_host_init(dwc_otg_core_if_t *core_if);
+
+/** @} */
+
+#endif /* __DWC_CORE_IF_H__ */
diff --git a/drivers/usb/host/dwc2_otg_regs.h b/drivers/usb/host/dwc2_otg_regs.h
new file mode 100644
index 0000000..765e46e
--- /dev/null
+++ b/drivers/usb/host/dwc2_otg_regs.h
@@ -0,0 +1,1625 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $
+ * $Revision: #76 $
+ * $Date: 2009/04/02 $
+ * $Change: 1224216 $
+ *
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * ========================================================================== */
+
+#ifndef __DWC_OTG_REGS_H__
+#define __DWC_OTG_REGS_H__
+
+#include "dwc2_otg.h"
+
+/**
+ * @file
+ *
+ * This file contains the data structures for accessing the DWC_otg core registers.
+ *
+ * The application interfaces with the HS OTG core by reading from and
+ * writing to the Control and Status Register (CSR) space through the
+ * AHB Slave interface. These registers are 32 bits wide, and the
+ * addresses are 32-bit-block aligned.
+ * CSRs are classified as follows:
+ * - Core Global Registers
+ * - Device Mode Registers
+ * - Device Global Registers
+ * - Device Endpoint Specific Registers
+ * - Host Mode Registers
+ * - Host Global Registers
+ * - Host Port CSRs
+ * - Host Channel Specific Registers
+ *
+ * Only the Core Global registers can be accessed in both Device and
+ * Host modes. When the HS OTG core is operating in one mode, either
+ * Device or Host, the application must not access registers from the
+ * other mode. When the core switches from one mode to another, the
+ * registers in the new mode of operation must be reprogrammed as they
+ * would be after a power-on reset.
+ */
+
+/****************************************************************************/
+/** DWC_otg Core registers .
+ * The dwc_otg_core_global_regs structure defines the size
+ * and relative field offsets for the Core Global registers.
+ */
+typedef struct dwc_otg_core_global_regs {
+ /** OTG Control and Status Register. <i>Offset: 000h</i> */
+ volatile uint32_t gotgctl;
+ /** OTG Interrupt Register. <i>Offset: 004h</i> */
+ volatile uint32_t gotgint;
+ /**Core AHB Configuration Register. <i>Offset: 008h</i> */
+ volatile uint32_t gahbcfg;
+
+#define DWC_GLBINTRMASK 0x0001
+#define DWC_DMAENABLE 0x0020
+#define DWC_NPTXEMPTYLVL_EMPTY 0x0080
+#define DWC_NPTXEMPTYLVL_HALFEMPTY 0x0000
+#define DWC_PTXEMPTYLVL_EMPTY 0x0100
+#define DWC_PTXEMPTYLVL_HALFEMPTY 0x0000
+
+ /**Core USB Configuration Register. <i>Offset: 00Ch</i> */
+ volatile uint32_t gusbcfg;
+ /**Core Reset Register. <i>Offset: 010h</i> */
+ volatile uint32_t grstctl;
+ /**Core Interrupt Register. <i>Offset: 014h</i> */
+ volatile uint32_t gintsts;
+ /**Core Interrupt Mask Register. <i>Offset: 018h</i> */
+ volatile uint32_t gintmsk;
+ /**Receive Status Queue Read Register (Read Only). <i>Offset: 01Ch</i> */
+ volatile uint32_t grxstsr;
+ /**Receive Status Queue Read & POP Register (Read Only). <i>Offset: 020h</i>*/
+ volatile uint32_t grxstsp;
+ /**Receive FIFO Size Register. <i>Offset: 024h</i> */
+ volatile uint32_t grxfsiz;
+ /**Non Periodic Transmit FIFO Size Register. <i>Offset: 028h</i> */
+ volatile uint32_t gnptxfsiz;
+ /**Non Periodic Transmit FIFO/Queue Status Register (Read
+ * Only). <i>Offset: 02Ch</i> */
+ volatile uint32_t gnptxsts;
+ /**I2C Access Register. <i>Offset: 030h</i> */
+ volatile uint32_t gi2cctl;
+ /**PHY Vendor Control Register. <i>Offset: 034h</i> */
+ volatile uint32_t gpvndctl;
+ /**General Purpose Input/Output Register. <i>Offset: 038h</i> */
+ volatile uint32_t ggpio;
+ /**User ID Register. <i>Offset: 03Ch</i> */
+ volatile uint32_t guid;
+ /**Synopsys ID Register (Read Only). <i>Offset: 040h</i> */
+ volatile uint32_t gsnpsid;
+ /**User HW Config1 Register (Read Only). <i>Offset: 044h</i> */
+ volatile uint32_t ghwcfg1;
+ /**User HW Config2 Register (Read Only). <i>Offset: 048h</i> */
+ volatile uint32_t ghwcfg2;
+#define DWC_SLAVE_ONLY_ARCH 0
+#define DWC_EXT_DMA_ARCH 1
+#define DWC_INT_DMA_ARCH 2
+
+#define DWC_MODE_HNP_SRP_CAPABLE 0
+#define DWC_MODE_SRP_ONLY_CAPABLE 1
+#define DWC_MODE_NO_HNP_SRP_CAPABLE 2
+#define DWC_MODE_SRP_CAPABLE_DEVICE 3
+#define DWC_MODE_NO_SRP_CAPABLE_DEVICE 4
+#define DWC_MODE_SRP_CAPABLE_HOST 5
+#define DWC_MODE_NO_SRP_CAPABLE_HOST 6
+
+ /**User HW Config3 Register (Read Only). <i>Offset: 04Ch</i> */
+ volatile uint32_t ghwcfg3;
+ /**User HW Config4 Register (Read Only). <i>Offset: 050h</i>*/
+ volatile uint32_t ghwcfg4;
+ /** Core LPM Configuration register */
+ volatile uint32_t glpmcfg;
+ /** Reserved <i>Offset: 058h-0FFh</i> */
+ volatile uint32_t reserved[42];
+ /** Host Periodic Transmit FIFO Size Register. <i>Offset: 100h</i> */
+ volatile uint32_t hptxfsiz;
+ /** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled,
+ otherwise Device Transmit FIFO#n Register.
+ * <i>Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15).</i> */
+ volatile uint32_t dptxfsiz_dieptxf[15];
+} dwc_otg_core_global_regs_t;
+
+/**
+ * This union represents the bit fields of the Core OTG Control
+ * and Status Register (GOTGCTL). Set the bits using the bit
+ * fields then write the <i>d32</i> value to the register.
+ */
+typedef union gotgctl_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned sesreqscs:1;
+ unsigned sesreq:1;
+ unsigned reserved2_7:6;
+ unsigned hstnegscs:1;
+ unsigned hnpreq:1;
+ unsigned hstsethnpen:1;
+ unsigned devhnpen:1;
+ unsigned reserved12_15:4;
+ unsigned conidsts:1;
+ unsigned reserved17:1;
+ unsigned asesvld:1;
+ unsigned bsesvld:1;
+ unsigned currmod:1;
+ unsigned reserved21_31:11;
+ } b;
+} gotgctl_data_t;
+
+/**
+ * This union represents the bit fields of the Core OTG Interrupt Register
+ * (GOTGINT). Set/clear the bits using the bit fields then write the <i>d32</i>
+ * value to the register.
+ */
+typedef union gotgint_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ /** Current Mode */
+ unsigned reserved0_1:2;
+
+ /** Session End Detected */
+ unsigned sesenddet:1;
+
+ unsigned reserved3_7:5;
+
+ /** Session Request Success Status Change */
+ unsigned sesreqsucstschng:1;
+ /** Host Negotiation Success Status Change */
+ unsigned hstnegsucstschng:1;
+
+ unsigned reserver10_16:7;
+
+ /** Host Negotiation Detected */
+ unsigned hstnegdet:1;
+ /** A-Device Timeout Change */
+ unsigned adevtoutchng:1;
+ /** Debounce Done */
+ unsigned debdone:1;
+
+ unsigned reserved31_20:12;
+
+ } b;
+} gotgint_data_t;
+
+/**
+ * This union represents the bit fields of the Core AHB Configuration
+ * Register (GAHBCFG). Set/clear the bits using the bit fields then
+ * write the <i>d32</i> value to the register.
+ */
+typedef union gahbcfg_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned glblintrmsk:1;
+#define DWC_GAHBCFG_GLBINT_ENABLE 1
+
+ unsigned hburstlen:4;
+#define DWC_GAHBCFG_INT_DMA_BURST_SINGLE 0
+#define DWC_GAHBCFG_INT_DMA_BURST_INCR 1
+#define DWC_GAHBCFG_INT_DMA_BURST_INCR4 3
+#define DWC_GAHBCFG_INT_DMA_BURST_INCR8 5
+#define DWC_GAHBCFG_INT_DMA_BURST_INCR16 7
+
+ unsigned dmaenable:1;
+#define DWC_GAHBCFG_DMAENABLE 1
+ unsigned reserved:1;
+ unsigned nptxfemplvl_txfemplvl:1;
+ unsigned ptxfemplvl:1;
+#define DWC_GAHBCFG_TXFEMPTYLVL_EMPTY 1
+#define DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY 0
+ unsigned reserved9_31:23;
+ } b;
+} gahbcfg_data_t;
+
+/**
+ * This union represents the bit fields of the Core USB Configuration
+ * Register (GUSBCFG). Set the bits using the bit fields then write
+ * the <i>d32</i> value to the register.
+ */
+typedef union gusbcfg_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned toutcal:3;
+ unsigned phyif:1;
+ unsigned ulpi_utmi_sel:1;
+ unsigned fsintf:1;
+ unsigned physel:1;
+ unsigned ddrsel:1;
+ unsigned srpcap:1;
+ unsigned hnpcap:1;
+ unsigned usbtrdtim:4;
+ unsigned nptxfrwnden:1;
+ unsigned phylpwrclksel:1;
+ unsigned otgutmifssel:1;
+ unsigned ulpi_fsls:1;
+ unsigned ulpi_auto_res:1;
+ unsigned ulpi_clk_sus_m:1;
+ unsigned ulpi_ext_vbus_drv:1;
+ unsigned ulpi_int_vbus_indicator:1;
+ unsigned term_sel_dl_pulse:1;
+ unsigned reserved23_25:3;
+ unsigned ic_usb_cap:1;
+ unsigned ic_traffic_pull_remove:1;
+ unsigned tx_end_delay:1;
+ unsigned reserved29_31:3;
+ } b;
+} gusbcfg_data_t;
+
+/**
+ * This union represents the bit fields of the Core LPM Configuration
+ * Register (GLPMCFG). Set the bits using bit fields then write
+ * the <i>d32</i> value to the register.
+ */
+typedef union glpmctl_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ /** LPM-Capable (LPMCap) (Device and Host)
+ * The application uses this bit to control
+ * the DWC_otg core LPM capabilities.
+ */
+ unsigned lpm_cap_en:1;
+ /** LPM response programmed by application (AppL1Res) (Device)
+ * Handshake response to LPM token pre-programmed
+ * by device application software.
+ */
+ unsigned appl_resp:1;
+ /** Host Initiated Resume Duration (HIRD) (Device and Host)
+ * In Host mode this field indicates the value of HIRD
+ * to be sent in an LPM transaction.
+ * In Device mode this field is updated with the
+ * Received LPM Token HIRD bmAttribute
+ * when an ACK/NYET/STALL response is sent
+ * to an LPM transaction.
+ */
+ unsigned hird:4;
+ /** RemoteWakeEnable (bRemoteWake) (Device and Host)
+ * In Host mode this bit indicates the value of remote
+ * wake up to be sent in wIndex field of LPM transaction.
+ * In Device mode this field is updated with the
+ * Received LPM Token bRemoteWake bmAttribute
+ * when an ACK/NYET/STALL response is sent
+ * to an LPM transaction.
+ */
+ unsigned rem_wkup_en:1;
+ /** Enable utmi_sleep_n (EnblSlpM) (Device and Host)
+ * The application uses this bit to control
+ * the utmi_sleep_n assertion to the PHY when in L1 state.
+ */
+ unsigned en_utmi_sleep:1;
+ /** HIRD Threshold (HIRD_Thres) (Device and Host)
+ */
+ unsigned hird_thres:5;
+ /** LPM Response (CoreL1Res) (Device and Host)
+ * In Host mode this bit contains handsake response to
+ * LPM transaction.
+ * In Device mode the response of the core to
+ * LPM transaction received is reflected in these two bits.
+ * - 0x0: ERROR (No handshake response)
+ * - 0x1: STALL
+ * - 0x2: NYET
+ * - 0x3: ACK
+ */
+ unsigned lpm_resp:2;
+ /** Port Sleep Status (SlpSts) (Device and Host)
+ * This bit is set as long as a Sleep condition
+ * is present on the USB bus.
+ */
+ unsigned prt_sleep_sts:1;
+ /** Sleep State Resume OK (L1ResumeOK) (Device and Host)
+ * Indicates that the application or host
+ * can start resume from Sleep state.
+ */
+ unsigned sleep_state_resumeok:1;
+ /** LPM channel Index (LPM_Chnl_Indx) (Host)
+ * The channel number on which the LPM transaction
+ * has to be applied while sending
+ * an LPM transaction to the local device.
+ */
+ unsigned lpm_chan_index:4;
+ /** LPM Retry Count (LPM_Retry_Cnt) (Host)
+ * Number host retries that would be performed
+ * if the device response was not valid response.
+ */
+ unsigned retry_count:3;
+ /** Send LPM Transaction (SndLPM) (Host)
+ * When set by application software,
+ * an LPM transaction containing two tokens
+ * is sent.
+ */
+ unsigned send_lpm:1;
+ /** LPM Retry status (LPM_RetryCnt_Sts) (Host)
+ * Number of LPM Host Retries still remaining
+ * to be transmitted for the current LPM sequence
+ */
+ unsigned retry_count_sts:3;
+ unsigned reserved28_29:2;
+ /** In host mode once this bit is set, the host
+ * configures to drive the HSIC Idle state on the bus.
+ * It then waits for the device to initiate the Connect sequence.
+ * In device mode once this bit is set, the device waits for
+ * the HSIC Idle line state on the bus. Upon receving the Idle
+ * line state, it initiates the HSIC Connect sequence.
+ */
+ unsigned hsic_connect:1;
+ /** This bit overrides and functionally inverts
+ * the if_select_hsic input port signal.
+ */
+ unsigned inv_sel_hsic:1;
+ } b;
+} glpmcfg_data_t;
+
+/**
+ * This union represents the bit fields of the Core Reset Register
+ * (GRSTCTL). Set/clear the bits using the bit fields then write the
+ * <i>d32</i> value to the register.
+ */
+typedef union grstctl_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ /** Core Soft Reset (CSftRst) (Device and Host)
+ *
+ * The application can flush the control logic in the
+ * entire core using this bit. This bit resets the
+ * pipelines in the AHB Clock domain as well as the
+ * PHY Clock domain.
+ *
+ * The state machines are reset to an IDLE state, the
+ * control bits in the CSRs are cleared, all the
+ * transmit FIFOs and the receive FIFO are flushed.
+ *
+ * The status mask bits that control the generation of
+ * the interrupt, are cleared, to clear the
+ * interrupt. The interrupt status bits are not
+ * cleared, so the application can get the status of
+ * any events that occurred in the core after it has
+ * set this bit.
+ *
+ * Any transactions on the AHB are terminated as soon
+ * as possible following the protocol. Any
+ * transactions on the USB are terminated immediately.
+ *
+ * The configuration settings in the CSRs are
+ * unchanged, so the software doesn't have to
+ * reprogram these registers (Device
+ * Configuration/Host Configuration/Core System
+ * Configuration/Core PHY Configuration).
+ *
+ * The application can write to this bit, any time it
+ * wants to reset the core. This is a self clearing
+ * bit and the core clears this bit after all the
+ * necessary logic is reset in the core, which may
+ * take several clocks, depending on the current state
+ * of the core.
+ */
+ unsigned csftrst:1;
+ /** Hclk Soft Reset
+ *
+ * The application uses this bit to reset the control logic in
+ * the AHB clock domain. Only AHB clock domain pipelines are
+ * reset.
+ */
+ unsigned hsftrst:1;
+ /** Host Frame Counter Reset (Host Only)<br>
+ *
+ * The application can reset the (micro)frame number
+ * counter inside the core, using this bit. When the
+ * (micro)frame counter is reset, the subsequent SOF
+ * sent out by the core, will have a (micro)frame
+ * number of 0.
+ */
+ unsigned hstfrm:1;
+ /** In Token Sequence Learning Queue Flush
+ * (INTknQFlsh) (Device Only)
+ */
+ unsigned intknqflsh:1;
+ /** RxFIFO Flush (RxFFlsh) (Device and Host)
+ *
+ * The application can flush the entire Receive FIFO
+ * using this bit. <p>The application must first
+ * ensure that the core is not in the middle of a
+ * transaction. <p>The application should write into
+ * this bit, only after making sure that neither the
+ * DMA engine is reading from the RxFIFO nor the MAC
+ * is writing the data in to the FIFO. <p>The
+ * application should wait until the bit is cleared
+ * before performing any other operations. This bit
+ * will takes 8 clocks (slowest of PHY or AHB clock)
+ * to clear.
+ */
+ unsigned rxfflsh:1;
+ /** TxFIFO Flush (TxFFlsh) (Device and Host).
+ *
+ * This bit is used to selectively flush a single or
+ * all transmit FIFOs. The application must first
+ * ensure that the core is not in the middle of a
+ * transaction. <p>The application should write into
+ * this bit, only after making sure that neither the
+ * DMA engine is writing into the TxFIFO nor the MAC
+ * is reading the data out of the FIFO. <p>The
+ * application should wait until the core clears this
+ * bit, before performing any operations. This bit
+ * will takes 8 clocks (slowest of PHY or AHB clock)
+ * to clear.
+ */
+ unsigned txfflsh:1;
+
+ /** TxFIFO Number (TxFNum) (Device and Host).
+ *
+ * This is the FIFO number which needs to be flushed,
+ * using the TxFIFO Flush bit. This field should not
+ * be changed until the TxFIFO Flush bit is cleared by
+ * the core.
+ * - 0x0: Non Periodic TxFIFO Flush
+ * - 0x1: Periodic TxFIFO #1 Flush in device mode
+ * or Periodic TxFIFO in host mode
+ * - 0x2: Periodic TxFIFO #2 Flush in device mode.
+ * - ...
+ * - 0xF: Periodic TxFIFO #15 Flush in device mode
+ * - 0x10: Flush all the Transmit NonPeriodic and
+ * Transmit Periodic FIFOs in the core
+ */
+ unsigned txfnum:5;
+ /** Reserved */
+ unsigned reserved11_29:19;
+ /** DMA Request Signal. Indicated DMA request is in
+ * probress. Used for debug purpose. */
+ unsigned dmareq:1;
+ /** AHB Master Idle. Indicates the AHB Master State
+ * Machine is in IDLE condition. */
+ unsigned ahbidle:1;
+ } b;
+} grstctl_t;
+
+/**
+ * This union represents the bit fields of the Core Interrupt Mask
+ * Register (GINTMSK). Set/clear the bits using the bit fields then
+ * write the <i>d32</i> value to the register.
+ */
+typedef union gintmsk_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned reserved0:1;
+ unsigned modemismatch:1;
+ unsigned otgintr:1;
+ unsigned sofintr:1;
+ unsigned rxstsqlvl:1;
+ unsigned nptxfempty:1;
+ unsigned ginnakeff:1;
+ unsigned goutnakeff:1;
+ unsigned reserved8:1;
+ unsigned i2cintr:1;
+ unsigned erlysuspend:1;
+ unsigned usbsuspend:1;
+ unsigned usbreset:1;
+ unsigned enumdone:1;
+ unsigned isooutdrop:1;
+ unsigned eopframe:1;
+ unsigned reserved16:1;
+ unsigned epmismatch:1;
+ unsigned inepintr:1;
+ unsigned outepintr:1;
+ unsigned incomplisoin:1;
+ unsigned incomplisoout:1;
+ unsigned reserved22_23:2;
+ unsigned portintr:1;
+ unsigned hcintr:1;
+ unsigned ptxfempty:1;
+ unsigned lpmtranrcvd:1;
+ unsigned conidstschng:1;
+ unsigned disconnect:1;
+ unsigned sessreqintr:1;
+ unsigned wkupintr:1;
+ } b;
+} gintmsk_data_t;
+/**
+ * This union represents the bit fields of the Core Interrupt Register
+ * (GINTSTS). Set/clear the bits using the bit fields then write the
+ * <i>d32</i> value to the register.
+ */
+typedef union gintsts_data {
+ /** raw register data */
+ uint32_t d32;
+#define DWC_SOF_INTR_MASK 0x0008
+ /** register bits */
+ struct {
+#define DWC_HOST_MODE 1
+ unsigned curmode:1;
+ unsigned modemismatch:1;
+ unsigned otgintr:1;
+ unsigned sofintr:1;
+ unsigned rxstsqlvl:1;
+ unsigned nptxfempty:1;
+ unsigned ginnakeff:1;
+ unsigned goutnakeff:1;
+ unsigned reserved8:1;
+ unsigned i2cintr:1;
+ unsigned erlysuspend:1;
+ unsigned usbsuspend:1;
+ unsigned usbreset:1;
+ unsigned enumdone:1;
+ unsigned isooutdrop:1;
+ unsigned eopframe:1;
+ unsigned intokenrx:1;
+ unsigned epmismatch:1;
+ unsigned inepint:1;
+ unsigned outepintr:1;
+ unsigned incomplisoin:1;
+ unsigned incomplisoout:1;
+ unsigned reserved22_23:2;
+ unsigned portintr:1;
+ unsigned hcintr:1;
+ unsigned ptxfempty:1;
+ unsigned lpmtranrcvd:1;
+ unsigned conidstschng:1;
+ unsigned disconnect:1;
+ unsigned sessreqintr:1;
+ unsigned wkupintr:1;
+ } b;
+} gintsts_data_t;
+
+/**
+ * This union represents the bit fields in the Device Receive Status Read and
+ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>
+ * element then read out the bits using the <i>b</i>it elements.
+ */
+typedef union device_grxsts_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned epnum:4;
+ unsigned bcnt:11;
+ unsigned dpid:2;
+
+#define DWC_STS_DATA_UPDT 0x2 /* OUT Data Packet */
+#define DWC_STS_XFER_COMP 0x3 /* OUT Data Transfer Complete */
+
+#define DWC_DSTS_GOUT_NAK 0x1 /* Global OUT NAK */
+#define DWC_DSTS_SETUP_COMP 0x4 /* Setup Phase Complete */
+#define DWC_DSTS_SETUP_UPDT 0x6 /* SETUP Packet */
+ unsigned pktsts:4;
+ unsigned fn:4;
+ unsigned reserved:7;
+ } b;
+} device_grxsts_data_t;
+
+/**
+ * This union represents the bit fields in the Host Receive Status Read and
+ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>
+ * element then read out the bits using the <i>b</i>it elements.
+ */
+typedef union host_grxsts_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned chnum:4;
+ unsigned bcnt:11;
+ unsigned dpid:2;
+
+ unsigned pktsts:4;
+#define DWC_GRXSTS_PKTSTS_IN 0x2
+#define DWC_GRXSTS_PKTSTS_IN_XFER_COMP 0x3
+#define DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR 0x5
+#define DWC_GRXSTS_PKTSTS_CH_HALTED 0x7
+
+ unsigned reserved:11;
+ } b;
+} host_grxsts_data_t;
+
+/**
+ * This union represents the bit fields in the FIFO Size Registers (HPTXFSIZ,
+ * GNPTXFSIZ, DPTXFSIZn, DIEPTXFn). Read the register into the <i>d32</i> element then
+ * read out the bits using the <i>b</i>it elements.
+ */
+typedef union fifosize_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned startaddr:16;
+ unsigned depth:16;
+ } b;
+} fifosize_data_t;
+
+/**
+ * This union represents the bit fields in the Non-Periodic Transmit
+ * FIFO/Queue Status Register (GNPTXSTS). Read the register into the
+ * <i>d32</i> element then read out the bits using the <i>b</i>it
+ * elements.
+ */
+typedef union gnptxsts_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned nptxfspcavail:16;
+ unsigned nptxqspcavail:8;
+ /** Top of the Non-Periodic Transmit Request Queue
+ * - bit 24 - Terminate (Last entry for the selected
+ * channel/EP)
+ * - bits 26:25 - Token Type
+ * - 2'b00 - IN/OUT
+ * - 2'b01 - Zero Length OUT
+ * - 2'b10 - PING/Complete Split
+ * - 2'b11 - Channel Halt
+ * - bits 30:27 - Channel/EP Number
+ */
+ unsigned nptxqtop_terminate:1;
+ unsigned nptxqtop_token:2;
+ unsigned nptxqtop_chnep:4;
+ unsigned reserved:1;
+ } b;
+} gnptxsts_data_t;
+
+/**
+ * This union represents the bit fields in the Transmit
+ * FIFO Status Register (DTXFSTS). Read the register into the
+ * <i>d32</i> element then read out the bits using the <i>b</i>it
+ * elements.
+ */
+typedef union dtxfsts_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned txfspcavail:16;
+ unsigned reserved:16;
+ } b;
+} dtxfsts_data_t;
+
+/**
+ * This union represents the bit fields in the I2C Control Register
+ * (I2CCTL). Read the register into the <i>d32</i> element then read out the
+ * bits using the <i>b</i>it elements.
+ */
+typedef union gi2cctl_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned rwdata:8;
+ unsigned regaddr:8;
+ unsigned addr:7;
+ unsigned i2cen:1;
+ unsigned ack:1;
+ unsigned i2csuspctl:1;
+ unsigned i2cdevaddr:2;
+ unsigned reserved:2;
+ unsigned rw:1;
+ unsigned bsydne:1;
+ } b;
+} gi2cctl_data_t;
+
+/**
+ * This union represents the bit fields in the User HW Config1
+ * Register. Read the register into the <i>d32</i> element then read
+ * out the bits using the <i>b</i>it elements.
+ */
+typedef union hwcfg1_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned ep_dir0:2;
+ unsigned ep_dir1:2;
+ unsigned ep_dir2:2;
+ unsigned ep_dir3:2;
+ unsigned ep_dir4:2;
+ unsigned ep_dir5:2;
+ unsigned ep_dir6:2;
+ unsigned ep_dir7:2;
+ unsigned ep_dir8:2;
+ unsigned ep_dir9:2;
+ unsigned ep_dir10:2;
+ unsigned ep_dir11:2;
+ unsigned ep_dir12:2;
+ unsigned ep_dir13:2;
+ unsigned ep_dir14:2;
+ unsigned ep_dir15:2;
+ } b;
+} hwcfg1_data_t;
+
+/**
+ * This union represents the bit fields in the User HW Config2
+ * Register. Read the register into the <i>d32</i> element then read
+ * out the bits using the <i>b</i>it elements.
+ */
+typedef union hwcfg2_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ /* GHWCFG2 */
+ unsigned op_mode:3;
+#define DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG 0
+#define DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG 1
+#define DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG 2
+#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3
+#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4
+#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST 5
+#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6
+
+ unsigned architecture:2;
+ unsigned point2point:1;
+ unsigned hs_phy_type:2;
+#define DWC_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0
+#define DWC_HWCFG2_HS_PHY_TYPE_UTMI 1
+#define DWC_HWCFG2_HS_PHY_TYPE_ULPI 2
+#define DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI 3
+
+ unsigned fs_phy_type:2;
+ unsigned num_dev_ep:4;
+ unsigned num_host_chan:4;
+ unsigned perio_ep_supported:1;
+ unsigned dynamic_fifo:1;
+ unsigned multi_proc_int:1;
+ unsigned reserved21:1;
+ unsigned nonperio_tx_q_depth:2;
+ unsigned host_perio_tx_q_depth:2;
+ unsigned dev_token_q_depth:5;
+ unsigned reserved31:1;
+ } b;
+} hwcfg2_data_t;
+
+/**
+ * This union represents the bit fields in the User HW Config3
+ * Register. Read the register into the <i>d32</i> element then read
+ * out the bits using the <i>b</i>it elements.
+ */
+typedef union hwcfg3_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ /* GHWCFG3 */
+ unsigned xfer_size_cntr_width:4;
+ unsigned packet_size_cntr_width:3;
+ unsigned otg_func:1;
+ unsigned i2c:1;
+ unsigned vendor_ctrl_if:1;
+ unsigned optional_features:1;
+ unsigned synch_reset_type:1;
+ unsigned otg_enable_ic_usb:1;
+ unsigned otg_enable_hsic:1;
+ unsigned reserved14:1;
+ unsigned otg_lpm_en:1;
+ unsigned dfifo_depth:16;
+ } b;
+} hwcfg3_data_t;
+
+/**
+ * This union represents the bit fields in the User HW Config4
+ * Register. Read the register into the <i>d32</i> element then read
+ * out the bits using the <i>b</i>it elements.
+ */
+typedef union hwcfg4_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned num_dev_perio_in_ep:4;
+ unsigned power_optimiz:1;
+ unsigned min_ahb_freq:9;
+ unsigned utmi_phy_data_width:2;
+ unsigned num_dev_mode_ctrl_ep:4;
+ unsigned iddig_filt_en:1;
+ unsigned vbus_valid_filt_en:1;
+ unsigned a_valid_filt_en:1;
+ unsigned b_valid_filt_en:1;
+ unsigned session_end_filt_en:1;
+ unsigned ded_fifo_en:1;
+ unsigned num_in_eps:4;
+ unsigned desc_dma:1;
+ unsigned desc_dma_dyn:1;
+ } b;
+} hwcfg4_data_t;
+
+/* Device Registers */
+
+/**
+ * Device Global Registers. <i>Offsets 800h-BFFh</i>
+ *
+ * The following structures define the size and relative field offsets
+ * for the Device Mode Registers.
+ *
+ * <i>These registers are visible only in Device mode and must not be
+ * accessed in Host mode, as the results are unknown.</i>
+ */
+typedef struct dwc_otg_dev_global_regs {
+ /** Device Configuration Register. <i>Offset 800h</i> */
+ volatile uint32_t dcfg;
+ /** Device Control Register. <i>Offset: 804h</i> */
+ volatile uint32_t dctl;
+ /** Device Status Register (Read Only). <i>Offset: 808h</i> */
+ volatile uint32_t dsts;
+ /** Reserved. <i>Offset: 80Ch</i> */
+ uint32_t unused;
+ /** Device IN Endpoint Common Interrupt Mask
+ * Register. <i>Offset: 810h</i> */
+ volatile uint32_t diepmsk;
+ /** Device OUT Endpoint Common Interrupt Mask
+ * Register. <i>Offset: 814h</i> */
+ volatile uint32_t doepmsk;
+ /** Device All Endpoints Interrupt Register. <i>Offset: 818h</i> */
+ volatile uint32_t daint;
+ /** Device All Endpoints Interrupt Mask Register. <i>Offset:
+ * 81Ch</i> */
+ volatile uint32_t daintmsk;
+ /** Device IN Token Queue Read Register-1 (Read Only).
+ * <i>Offset: 820h</i> */
+ volatile uint32_t dtknqr1;
+ /** Device IN Token Queue Read Register-2 (Read Only).
+ * <i>Offset: 824h</i> */
+ volatile uint32_t dtknqr2;
+ /** Device VBUS discharge Register. <i>Offset: 828h</i> */
+ volatile uint32_t dvbusdis;
+ /** Device VBUS Pulse Register. <i>Offset: 82Ch</i> */
+ volatile uint32_t dvbuspulse;
+ /** Device IN Token Queue Read Register-3 (Read Only). /
+ * Device Thresholding control register (Read/Write)
+ * <i>Offset: 830h</i> */
+ volatile uint32_t dtknqr3_dthrctl;
+ /** Device IN Token Queue Read Register-4 (Read Only). /
+ * Device IN EPs empty Inr. Mask Register (Read/Write)
+ * <i>Offset: 834h</i> */
+ volatile uint32_t dtknqr4_fifoemptymsk;
+ /** Device Each Endpoint Interrupt Register (Read Only). /
+ * <i>Offset: 838h</i> */
+ volatile uint32_t deachint;
+ /** Device Each Endpoint Interrupt mask Register (Read/Write). /
+ * <i>Offset: 83Ch</i> */
+ volatile uint32_t deachintmsk;
+ /** Device Each In Endpoint Interrupt mask Register (Read/Write). /
+ * <i>Offset: 840h</i> */
+ volatile uint32_t diepeachintmsk[MAX_EPS_CHANNELS];
+ /** Device Each Out Endpoint Interrupt mask Register (Read/Write). /
+ * <i>Offset: 880h</i> */
+ volatile uint32_t doepeachintmsk[MAX_EPS_CHANNELS];
+} dwc_otg_device_global_regs_t;
+
+/* DMA Descriptor Specific Structures */
+
+/** Buffer status definitions */
+
+#define BS_HOST_READY 0x0
+#define BS_DMA_BUSY 0x1
+#define BS_DMA_DONE 0x2
+#define BS_HOST_BUSY 0x3
+
+/** Receive/Transmit status definitions */
+
+#define RTS_SUCCESS 0x0
+#define RTS_BUFFLUSH 0x1
+#define RTS_RESERVED 0x2
+#define RTS_BUFERR 0x3
+
+/**
+ * This union represents the bit fields in the DMA Descriptor
+ * status quadlet. Read the quadlet into the <i>d32</i> member then
+ * set/clear the bits using the <i>b</i>it, <i>b_iso_out</i> and
+ * <i>b_iso_in</i> elements.
+ */
+typedef union dev_dma_desc_sts {
+ /** raw register data */
+ uint32_t d32;
+ /** quadlet bits */
+ struct {
+ /** Received number of bytes */
+ unsigned bytes:16;
+
+ unsigned reserved16_22:7;
+ /** Multiple Transfer - only for OUT EPs */
+ unsigned mtrf:1;
+ /** Setup Packet received - only for OUT EPs */
+ unsigned sr:1;
+ /** Interrupt On Complete */
+ unsigned ioc:1;
+ /** Short Packet */
+ unsigned sp:1;
+ /** Last */
+ unsigned l:1;
+ /** Receive Status */
+ unsigned sts:2;
+ /** Buffer Status */
+ unsigned bs:2;
+ } b;
+
+#ifdef DWC_EN_ISOC
+ /** iso out quadlet bits */
+ struct {
+ /** Received number of bytes */
+ unsigned rxbytes:11;
+
+ unsigned reserved11:1;
+ /** Frame Number */
+ unsigned framenum:11;
+ /** Received ISO Data PID */
+ unsigned pid:2;
+ /** Interrupt On Complete */
+ unsigned ioc:1;
+ /** Short Packet */
+ unsigned sp:1;
+ /** Last */
+ unsigned l:1;
+ /** Receive Status */
+ unsigned rxsts:2;
+ /** Buffer Status */
+ unsigned bs:2;
+ } b_iso_out;
+
+ /** iso in quadlet bits */
+ struct {
+ /** Transmited number of bytes */
+ unsigned txbytes:12;
+ /** Frame Number */
+ unsigned framenum:11;
+ /** Transmited ISO Data PID */
+ unsigned pid:2;
+ /** Interrupt On Complete */
+ unsigned ioc:1;
+ /** Short Packet */
+ unsigned sp:1;
+ /** Last */
+ unsigned l:1;
+ /** Transmit Status */
+ unsigned txsts:2;
+ /** Buffer Status */
+ unsigned bs:2;
+ } b_iso_in;
+#endif /* DWC_EN_ISOC */
+} dev_dma_desc_sts_t;
+
+/**
+ * DMA Descriptor structure
+ *
+ * DMA Descriptor structure contains two quadlets:
+ * Status quadlet and Data buffer pointer.
+ */
+typedef struct dwc_otg_dev_dma_desc {
+ /** DMA Descriptor status quadlet */
+ dev_dma_desc_sts_t status;
+ /** DMA Descriptor data buffer pointer */
+ uint32_t buf;
+} dwc_otg_dev_dma_desc_t;
+
+/* Host Mode Register Structures */
+
+/**
+ * The Host Global Registers structure defines the size and relative
+ * field offsets for the Host Mode Global Registers. Host Global
+ * Registers offsets 400h-7FFh.
+*/
+typedef struct dwc_otg_host_global_regs {
+ /** Host Configuration Register. <i>Offset: 400h</i> */
+ volatile uint32_t hcfg;
+ /** Host Frame Interval Register. <i>Offset: 404h</i> */
+ volatile uint32_t hfir;
+ /** Host Frame Number / Frame Remaining Register. <i>Offset: 408h</i> */
+ volatile uint32_t hfnum;
+ /** Reserved. <i>Offset: 40Ch</i> */
+ uint32_t reserved40C;
+ /** Host Periodic Transmit FIFO/ Queue Status Register. <i>Offset: 410h</i> */
+ volatile uint32_t hptxsts;
+ /** Host All Channels Interrupt Register. <i>Offset: 414h</i> */
+ volatile uint32_t haint;
+ /** Host All Channels Interrupt Mask Register. <i>Offset: 418h</i> */
+ volatile uint32_t haintmsk;
+ /** Host Frame List Base Address Register . <i>Offset: 41Ch</i> */
+ volatile uint32_t hflbaddr;
+} dwc_otg_host_global_regs_t;
+
+
+/**
+ * This union represents the bit fields in the Host Configuration Register.
+ * Read the register into the <i>d32</i> member then set/clear the bits using
+ * the <i>b</i>it elements. Write the <i>d32</i> member to the hcfg register.
+ */
+typedef union hcfg_data {
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct {
+ /** FS/LS Phy Clock Select */
+ unsigned fslspclksel:2;
+#define DWC_HCFG_30_60_MHZ 0
+#define DWC_HCFG_48_MHZ 1
+#define DWC_HCFG_6_MHZ 2
+
+ /** FS/LS Only Support */
+ unsigned fslssupp:1;
+ unsigned reserved3_22:20;
+ /** Enable Scatter/gather DMA in Host mode */
+ unsigned descdma:1;
+ /** Frame List Entries */
+ unsigned frlisten:2;
+ /** Enable Periodic Scheduling */
+ unsigned perschedena:1;
+ /** Periodic Scheduling Enabled Status */
+ unsigned perschedstat:1;
+ } b;
+} hcfg_data_t;
+
+/**
+ * This union represents the bit fields in the Host Frame Remaing/Number
+ * Register.
+ */
+typedef union hfir_data {
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct {
+ unsigned frint:16;
+ unsigned reserved:16;
+ } b;
+} hfir_data_t;
+
+/**
+ * This union represents the bit fields in the Host Frame Remaing/Number
+ * Register.
+ */
+typedef union hfnum_data {
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct {
+ unsigned frnum:16;
+#define DWC_HFNUM_MAX_FRNUM 0x3FFF
+ unsigned frrem:16;
+ } b;
+} hfnum_data_t;
+
+typedef union hptxsts_data {
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct {
+ unsigned ptxfspcavail:16;
+ unsigned ptxqspcavail:8;
+ /** Top of the Periodic Transmit Request Queue
+ * - bit 24 - Terminate (last entry for the selected channel)
+ * - bits 26:25 - Token Type
+ * - 2'b00 - Zero length
+ * - 2'b01 - Ping
+ * - 2'b10 - Disable
+ * - bits 30:27 - Channel Number
+ * - bit 31 - Odd/even microframe
+ */
+ unsigned ptxqtop_terminate:1;
+ unsigned ptxqtop_token:2;
+ unsigned ptxqtop_chnum:4;
+ unsigned ptxqtop_odd:1;
+ } b;
+} hptxsts_data_t;
+
+/**
+ * This union represents the bit fields in the Host Port Control and Status
+ * Register. Read the register into the <i>d32</i> member then set/clear the
+ * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
+ * hprt0 register.
+ */
+typedef union hprt0_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned prtconnsts:1;
+ unsigned prtconndet:1;
+ unsigned prtena:1;
+ unsigned prtenchng:1;
+ unsigned prtovrcurract:1;
+ unsigned prtovrcurrchng:1;
+ unsigned prtres:1;
+ unsigned prtsusp:1;
+ unsigned prtrst:1;
+ unsigned reserved9:1;
+ unsigned prtlnsts:2;
+ unsigned prtpwr:1;
+ unsigned prttstctl:4;
+ unsigned prtspd:2;
+#define DWC_HPRT0_PRTSPD_HIGH_SPEED 0
+#define DWC_HPRT0_PRTSPD_FULL_SPEED 1
+#define DWC_HPRT0_PRTSPD_LOW_SPEED 2
+ unsigned reserved19_31:13;
+ } b;
+} hprt0_data_t;
+
+/**
+ * This union represents the bit fields in the Host All Interrupt
+ * Register.
+ */
+typedef union haint_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned ch0:1;
+ unsigned ch1:1;
+ unsigned ch2:1;
+ unsigned ch3:1;
+ unsigned ch4:1;
+ unsigned ch5:1;
+ unsigned ch6:1;
+ unsigned ch7:1;
+ unsigned ch8:1;
+ unsigned ch9:1;
+ unsigned ch10:1;
+ unsigned ch11:1;
+ unsigned ch12:1;
+ unsigned ch13:1;
+ unsigned ch14:1;
+ unsigned ch15:1;
+ unsigned reserved:16;
+ } b;
+
+ struct {
+ unsigned chint:16;
+ unsigned reserved:16;
+ } b2;
+} haint_data_t;
+
+/**
+ * This union represents the bit fields in the Host All Interrupt
+ * Register.
+ */
+typedef union haintmsk_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned ch0:1;
+ unsigned ch1:1;
+ unsigned ch2:1;
+ unsigned ch3:1;
+ unsigned ch4:1;
+ unsigned ch5:1;
+ unsigned ch6:1;
+ unsigned ch7:1;
+ unsigned ch8:1;
+ unsigned ch9:1;
+ unsigned ch10:1;
+ unsigned ch11:1;
+ unsigned ch12:1;
+ unsigned ch13:1;
+ unsigned ch14:1;
+ unsigned ch15:1;
+ unsigned reserved:16;
+ } b;
+
+ struct {
+ unsigned chint:16;
+ unsigned reserved:16;
+ } b2;
+} haintmsk_data_t;
+
+/**
+ * Host Channel Specific Registers. <i>500h-5FCh</i>
+ */
+typedef struct dwc_otg_hc_regs {
+ /** Host Channel 0 Characteristic Register. <i>Offset: 500h + (chan_num * 20h) + 00h</i> */
+ volatile uint32_t hcchar;
+ /** Host Channel 0 Split Control Register. <i>Offset: 500h + (chan_num * 20h) + 04h</i> */
+ volatile uint32_t hcsplt;
+ /** Host Channel 0 Interrupt Register. <i>Offset: 500h + (chan_num * 20h) + 08h</i> */
+ volatile uint32_t hcint;
+ /** Host Channel 0 Interrupt Mask Register. <i>Offset: 500h + (chan_num * 20h) + 0Ch</i> */
+ volatile uint32_t hcintmsk;
+ /** Host Channel 0 Transfer Size Register. <i>Offset: 500h + (chan_num * 20h) + 10h</i> */
+ volatile uint32_t hctsiz;
+ /** Host Channel 0 DMA Address Register. <i>Offset: 500h + (chan_num * 20h) + 14h</i> */
+ volatile uint32_t hcdma;
+ volatile uint32_t reserved;
+ /** Host Channel 0 DMA Buffer Address Register. <i>Offset: 500h + (chan_num * 20h) + 1Ch</i> */
+ volatile uint32_t hcdmab;
+} dwc_otg_hc_regs_t;
+
+/**
+ * This union represents the bit fields in the Host Channel Characteristics
+ * Register. Read the register into the <i>d32</i> member then set/clear the
+ * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
+ * hcchar register.
+ */
+typedef union hcchar_data {
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct {
+ /** Maximum packet size in bytes */
+ unsigned mps:11;
+
+ /** Endpoint number */
+ unsigned epnum:4;
+
+ /** 0: OUT, 1: IN */
+ unsigned epdir:1;
+
+ unsigned reserved:1;
+
+ /** 0: Full/high speed device, 1: Low speed device */
+ unsigned lspddev:1;
+
+ /** 0: Control, 1: Isoc, 2: Bulk, 3: Intr */
+ unsigned eptype:2;
+
+ /** Packets per frame for periodic transfers. 0 is reserved. */
+ unsigned multicnt:2;
+
+ /** Device address */
+ unsigned devaddr:7;
+
+ /**
+ * Frame to transmit periodic transaction.
+ * 0: even, 1: odd
+ */
+ unsigned oddfrm:1;
+
+ /** Channel disable */
+ unsigned chdis:1;
+
+ /** Channel enable */
+ unsigned chen:1;
+ } b;
+} hcchar_data_t;
+
+typedef union hcsplt_data {
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct {
+ /** Port Address */
+ unsigned prtaddr:7;
+
+ /** Hub Address */
+ unsigned hubaddr:7;
+
+ /** Transaction Position */
+ unsigned xactpos:2;
+#define DWC_HCSPLIT_XACTPOS_MID 0
+#define DWC_HCSPLIT_XACTPOS_END 1
+#define DWC_HCSPLIT_XACTPOS_BEGIN 2
+#define DWC_HCSPLIT_XACTPOS_ALL 3
+
+ /** Do Complete Split */
+ unsigned compsplt:1;
+
+ /** Reserved */
+ unsigned reserved:14;
+
+ /** Split Enble */
+ unsigned spltena:1;
+ } b;
+} hcsplt_data_t;
+
+/**
+ * This union represents the bit fields in the Host All Interrupt
+ * Register.
+ */
+typedef union hcint_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ /** Transfer Complete */
+ unsigned xfercomp:1;
+ /** Channel Halted */
+ unsigned chhltd:1;
+ /** AHB Error */
+ unsigned ahberr:1;
+ /** STALL Response Received */
+ unsigned stall:1;
+ /** NAK Response Received */
+ unsigned nak:1;
+ /** ACK Response Received */
+ unsigned ack:1;
+ /** NYET Response Received */
+ unsigned nyet:1;
+ /** Transaction Err */
+ unsigned xacterr:1;
+ /** Babble Error */
+ unsigned bblerr:1;
+ /** Frame Overrun */
+ unsigned frmovrun:1;
+ /** Data Toggle Error */
+ unsigned datatglerr:1;
+ /** Buffer Not Available (only for DDMA mode) */
+ unsigned bna:1;
+ /** Exessive transaction error (only for DDMA mode) */
+ unsigned xcs_xact:1;
+ /** Frame List Rollover interrupt */
+ unsigned frm_list_roll:1;
+ /** Reserved */
+ unsigned reserved14_31:18;
+ } b;
+} hcint_data_t;
+
+/**
+ * This union represents the bit fields in the Host Channel Interrupt Mask
+ * Register. Read the register into the <i>d32</i> member then set/clear the
+ * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
+ * hcintmsk register.
+ */
+typedef union hcintmsk_data {
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct {
+ unsigned xfercompl:1;
+ unsigned chhltd:1;
+ unsigned ahberr:1;
+ unsigned stall:1;
+ unsigned nak:1;
+ unsigned ack:1;
+ unsigned nyet:1;
+ unsigned xacterr:1;
+ unsigned bblerr:1;
+ unsigned frmovrun:1;
+ unsigned datatglerr:1;
+ unsigned bna:1;
+ unsigned xcs_xact:1;
+ unsigned frm_list_roll:1;
+ unsigned reserved14_31:18;
+ } b;
+} hcintmsk_data_t;
+
+/**
+ * This union represents the bit fields in the Host Channel Transfer Size
+ * Register. Read the register into the <i>d32</i> member then set/clear the
+ * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
+ * hcchar register.
+ */
+
+typedef union hctsiz_data {
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct {
+ /** Total transfer size in bytes */
+ unsigned xfersize:19;
+
+ /** Data packets to transfer */
+ unsigned pktcnt:10;
+
+ /**
+ * Packet ID for next data packet
+ * 0: DATA0
+ * 1: DATA2
+ * 2: DATA1
+ * 3: MDATA (non-Control), SETUP (Control)
+ */
+ unsigned pid:2;
+#define DWC_HCTSIZ_DATA0 0
+#define DWC_HCTSIZ_DATA1 2
+#define DWC_HCTSIZ_DATA2 1
+#define DWC_HCTSIZ_MDATA 3
+#define DWC_HCTSIZ_SETUP 3
+
+ /** Do PING protocol when 1 */
+ unsigned dopng:1;
+ } b;
+
+ /** register bits */
+ struct {
+ /** Scheduling information */
+ unsigned schinfo:8;
+
+ /** Number of transfer descriptors.
+ * Max value:
+ * 64 in general,
+ * 256 only for HS isochronous endpoint.
+ */
+ unsigned ntd:8;
+
+ /** Data packets to transfer */
+ unsigned reserved16_28:13;
+
+ /**
+ * Packet ID for next data packet
+ * 0: DATA0
+ * 1: DATA2
+ * 2: DATA1
+ * 3: MDATA (non-Control)
+ */
+ unsigned pid:2;
+
+ /** Do PING protocol when 1 */
+ unsigned dopng:1;
+ } b_ddma;
+} hctsiz_data_t;
+
+
+/**
+ * This union represents the bit fields in the Host DMA Address
+ * Register used in Descriptor DMA mode.
+ */
+typedef union hcdma_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned reserved0_2:3;
+ /** Current Transfer Descriptor. Not used for ISOC */
+ unsigned ctd:8;
+ /** Start Address of Descriptor List */
+ unsigned dma_addr:21;
+ } b;
+} hcdma_data_t;
+
+/**
+ * This union represents the bit fields in the DMA Descriptor
+ * status quadlet for host mode. Read the quadlet into the <i>d32</i> member then
+ * set/clear the bits using the <i>b</i>it elements.
+ */
+typedef union host_dma_desc_sts {
+ /** raw register data */
+ uint32_t d32;
+ /** quadlet bits */
+
+ /* for non-isochronous */
+ struct {
+ /** Number of bytes */
+ unsigned n_bytes:17;
+ /** QTD offset to jump when Short Packet received - only for IN EPs */
+ unsigned qtd_offset:6;
+ /**
+ * Set to request the core to jump to alternate QTD if
+ * Short Packet received - only for IN EPs
+ */
+ unsigned a_qtd:1;
+ /**
+ * Setup Packet bit. When set indicates that buffer contains
+ * setup packet.
+ */
+ unsigned sup:1;
+ /** Interrupt On Complete */
+ unsigned ioc:1;
+ /** End of List */
+ unsigned eol:1;
+ unsigned reserved27:1;
+ /** Rx/Tx Status */
+ unsigned sts:2;
+ #define DMA_DESC_STS_PKTERR 1
+ unsigned reserved30:1;
+ /** Active Bit */
+ unsigned a:1;
+ } b;
+ /* for isochronous */
+ struct {
+ /** Number of bytes */
+ unsigned n_bytes:12;
+ unsigned reserved12_24:13;
+ /** Interrupt On Complete */
+ unsigned ioc:1;
+ unsigned reserved26_27:2;
+ /** Rx/Tx Status */
+ unsigned sts:2;
+ unsigned reserved30:1;
+ /** Active Bit */
+ unsigned a:1;
+ } b_isoc;
+} host_dma_desc_sts_t;
+
+#define MAX_DMA_DESC_SIZE 131071
+#define MAX_DMA_DESC_NUM_GENERIC 64
+#define MAX_DMA_DESC_NUM_HS_ISOC 256
+#define MAX_FRLIST_EN_NUM 64
+/**
+ * Host-mode DMA Descriptor structure
+ *
+ * DMA Descriptor structure contains two quadlets:
+ * Status quadlet and Data buffer pointer.
+ */
+typedef struct dwc_otg_host_dma_desc {
+ /** DMA Descriptor status quadlet */
+ host_dma_desc_sts_t status;
+ /** DMA Descriptor data buffer pointer */
+ uint32_t buf;
+} dwc_otg_host_dma_desc_t;
+
+/** OTG Host Interface Structure.
+ *
+ * The OTG Host Interface Structure structure contains information
+ * needed to manage the DWC_otg controller acting in host mode. It
+ * represents the programming view of the host-specific aspects of the
+ * controller.
+ */
+typedef struct dwc_otg_host_if {
+ /** Host Global Registers starting at offset 400h. */
+ dwc_otg_host_global_regs_t *host_global_regs;
+#define DWC_OTG_HOST_GLOBAL_REG_OFFSET 0x400
+
+ /** Host Port 0 Control and Status Register */
+ volatile uint32_t *hprt0;
+#define DWC_OTG_HOST_PORT_REGS_OFFSET 0x440
+
+ /** Host Channel Specific Registers at offsets 500h-5FCh. */
+ dwc_otg_hc_regs_t *hc_regs[MAX_EPS_CHANNELS];
+#define DWC_OTG_HOST_CHAN_REGS_OFFSET 0x500
+#define DWC_OTG_CHAN_REGS_OFFSET 0x20
+
+ /* Host configuration information */
+ /** Number of Host Channels (range: 1-16) */
+ uint8_t num_host_channels;
+ /** Periodic EPs supported (0: no, 1: yes) */
+ uint8_t perio_eps_supported;
+ /** Periodic Tx FIFO Size (Only 1 host periodic Tx FIFO) */
+ uint16_t perio_tx_fifo_size;
+
+} dwc_otg_host_if_t;
+
+/**
+ * This union represents the bit fields in the Power and Clock Gating Control
+ * Register. Read the register into the <i>d32</i> member then set/clear the
+ * bits using the <i>b</i>it elements.
+ */
+typedef union pcgcctl_data {
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct {
+ /** Stop Pclk */
+ unsigned stoppclk:1;
+ /** Gate Hclk */
+ unsigned gatehclk:1;
+ /** Power Clamp */
+ unsigned pwrclmp:1;
+ /** Reset Power Down Modules */
+ unsigned rstpdwnmodule:1;
+ /** PHY Suspended */
+ unsigned physuspended:1;
+ /** Enable Sleep Clock Gating (Enbl_L1Gating) */
+ unsigned enbl_sleep_gating:1;
+ /** PHY In Sleep (PhySleep) */
+ unsigned phy_in_sleep:1;
+ /** Deep Sleep */
+ unsigned deep_sleep:1;
+
+ unsigned reserved31_8:24;
+ } b;
+} pcgcctl_data_t;
+
+#endif
diff --git a/include/usb.h b/include/usb.h
index 736730e..184c006 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -150,7 +150,8 @@ enum usb_init_type {
defined(CONFIG_USB_OMAP3) || defined(CONFIG_USB_DA8XX) || \
defined(CONFIG_USB_BLACKFIN) || defined(CONFIG_USB_AM35X) || \
defined(CONFIG_USB_MUSB_DSPS) || defined(CONFIG_USB_MUSB_AM35X) || \
- defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined(CONFIG_USB_XHCI)
+ defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined(CONFIG_USB_XHCI) || \
+ defined(CONFIG_USB_DWC2_OTG)
int usb_lowlevel_init(int index, enum usb_init_type init, void **controller);
int usb_lowlevel_stop(int index);
--
1.8.3.2
2
1

06 Feb '14
* Enable USB HW driver
* Don't disable USB-related commands any more
* Add USB-related support to bootcmd
Signed-off-by: Stephen Warren <swarren(a)wwwdotorg.org>
---
These two patches are RFC, since they rely on the DWC2 USB driver, from:
[RFC PATCH] usb: add driver for Synopsis DWC2 USB IP block
include/configs/rpi_b.h | 60 ++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 50 insertions(+), 10 deletions(-)
diff --git a/include/configs/rpi_b.h b/include/configs/rpi_b.h
index 68bb2b0..0061de5 100644
--- a/include/configs/rpi_b.h
+++ b/include/configs/rpi_b.h
@@ -146,6 +146,41 @@
"bootcmd_mmc0=setenv devnum 0; run mmc_boot;\0"
#define BOOT_TARGETS_MMC "mmc0"
+#define BOOTCMD_INIT_USB "run usb_init; "
+#define BOOTCMDS_USB \
+ "usb_init=" \
+ "if ${usb_need_init}; then " \
+ "set usb_need_init false; " \
+ "usb start 0; " \
+ "fi\0" \
+ \
+ "usb_boot=" \
+ "setenv devtype usb; " \
+ BOOTCMD_INIT_USB \
+ "if usb dev ${devnum}; then " \
+ "run scan_boot; " \
+ "fi\0" \
+ \
+ "bootcmd_usb0=setenv devnum 0; run usb_boot;\0"
+#define BOOT_TARGETS_USB "usb0"
+
+#define BOOTCMDS_DHCP \
+ "bootcmd_dhcp=" \
+ BOOTCMD_INIT_USB \
+ "if dhcp ${scriptaddr} boot.scr.uimg; then "\
+ "source ${scriptaddr}; " \
+ "fi\0"
+#define BOOT_TARGETS_DHCP "dhcp"
+
+#define BOOTCMDS_PXE \
+ "bootcmd_pxe=" \
+ BOOTCMD_INIT_USB \
+ "dhcp; " \
+ "if pxe get; then " \
+ "pxe boot; " \
+ "fi\0"
+#define BOOT_TARGETS_PXE "pxe"
+
#define BOOTCMDS_COMMON \
"rootpart=1\0" \
\
@@ -187,18 +222,22 @@
\
"boot_targets=" \
BOOT_TARGETS_MMC " " \
+ BOOT_TARGETS_USB " " \
+ BOOT_TARGETS_PXE " " \
+ BOOT_TARGETS_DHCP " " \
"\0" \
\
"boot_prefixes=/\0" \
\
"boot_scripts=boot.scr.uimg\0" \
\
- BOOTCMDS_MMC
-
-#define CONFIG_BOOTCOMMAND \
- "for target in ${boot_targets}; do run bootcmd_${target}; done"
+ BOOTCMDS_MMC \
+ BOOTCMDS_USB \
+ BOOTCMDS_DHCP \
+ BOOTCMDS_PXE
#define CONFIG_BOOTCOMMAND \
+ "set usb_need_init; " \
"for target in ${boot_targets}; do run bootcmd_${target}; done"
#define CONFIG_EXTRA_ENV_SETTINGS \
@@ -227,16 +266,17 @@
#define CONFIG_CMDLINE_TAG
#define CONFIG_INITRD_TAG
+/* USB support */
+#define CONFIG_USB_DWC2_OTG
+#define CONFIG_USB_HOST_ETHER
+#define CONFIG_USB_STORAGE
+#define CONFIG_USB_ETHER_SMSC95XX
+#define CONFIG_CMD_USB
+
#include <config_distro_defaults.h>
/* Some things don't make sense on this HW or yet */
#undef CONFIG_CMD_FPGA
-#undef CONFIG_CMD_NET
-#undef CONFIG_CMD_NFS
#undef CONFIG_CMD_SAVEENV
-#undef CONFIG_CMD_DHCP
-#undef CONFIG_CMD_MII
-#undef CONFIG_CMD_NET
-#undef CONFIG_CMD_PING
#endif
--
1.8.3.2
1
1
The mv_udc is not marvell-specific anymore. The mv_udc is used to drive
generic ChipIdea CI13xxx series OTG cores, so rename the driver to ci_udc
instead.
Signed-off-by: Marek Vasut <marex(a)denx.de>
Cc: Eric Nelson <eric.nelson(a)boundarydevices.com>
Cc: Stefano Babic <sbabic(a)denx.de>
---
board/boundary/nitrogen6x/nitrogen6x.c | 2 +-
drivers/serial/usbtty.h | 4 +-
drivers/usb/gadget/Makefile | 2 +-
drivers/usb/gadget/{mv_udc.c => ci_udc.c} | 178 +++++++++++++++---------------
drivers/usb/gadget/{mv_udc.h => ci_udc.h} | 12 +-
drivers/usb/gadget/gadget_chips.h | 8 +-
include/configs/nitrogen6x.h | 2 +-
include/configs/sansa_fuze_plus.h | 2 +-
include/configs/xfi3.h | 2 +-
include/usb/{mv_udc.h => ci_udc.h} | 6 +-
10 files changed, 109 insertions(+), 109 deletions(-)
rename drivers/usb/gadget/{mv_udc.c => ci_udc.c} (79%)
rename drivers/usb/gadget/{mv_udc.h => ci_udc.h} (94%)
rename include/usb/{mv_udc.h => ci_udc.h} (73%)
diff --git a/board/boundary/nitrogen6x/nitrogen6x.c b/board/boundary/nitrogen6x/nitrogen6x.c
index 3f4cfa1..d9c05b0 100644
--- a/board/boundary/nitrogen6x/nitrogen6x.c
+++ b/board/boundary/nitrogen6x/nitrogen6x.c
@@ -389,7 +389,7 @@ int board_eth_init(bd_t *bis)
}
#endif
-#ifdef CONFIG_MV_UDC
+#ifdef CONFIG_CI_UDC
/* For otg ethernet*/
usb_eth_initialize(bis);
#endif
diff --git a/drivers/serial/usbtty.h b/drivers/serial/usbtty.h
index 819dec6..21a3ef4 100644
--- a/drivers/serial/usbtty.h
+++ b/drivers/serial/usbtty.h
@@ -20,8 +20,8 @@
#include <usb/pxa27x_udc.h>
#elif defined(CONFIG_DW_UDC)
#include <usb/designware_udc.h>
-#elif defined(CONFIG_MV_UDC)
-#include <usb/mv_udc.h>
+#elif defined(CONFIG_CI_UDC)
+#include <usb/ci_udc.h>
#endif
#include <usb/udc.h>
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index f13b172..804a2bd 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -21,7 +21,7 @@ endif
ifdef CONFIG_USB_ETHER
obj-y += ether.o
obj-$(CONFIG_USB_ETH_RNDIS) += rndis.o
-obj-$(CONFIG_MV_UDC) += mv_udc.o
+obj-$(CONFIG_CI_UDC) += ci_udc.o
obj-$(CONFIG_CPU_PXA25X) += pxa25x_udc.o
else
# Devices not related to the new gadget layer depend on CONFIG_USB_DEVICE
diff --git a/drivers/usb/gadget/mv_udc.c b/drivers/usb/gadget/ci_udc.c
similarity index 79%
rename from drivers/usb/gadget/mv_udc.c
rename to drivers/usb/gadget/ci_udc.c
index da41738..6c5ef4c 100644
--- a/drivers/usb/gadget/mv_udc.c
+++ b/drivers/usb/gadget/ci_udc.c
@@ -20,9 +20,9 @@
#include <linux/types.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
-#include <usb/mv_udc.h>
+#include <usb/ci_udc.h>
#include "../host/ehci.h"
-#include "mv_udc.h"
+#include "ci_udc.h"
/*
* Check if the system has too long cachelines. If the cachelines are
@@ -70,85 +70,85 @@ static struct usb_endpoint_descriptor ep0_in_desc = {
.bmAttributes = USB_ENDPOINT_XFER_CONTROL,
};
-static int mv_pullup(struct usb_gadget *gadget, int is_on);
-static int mv_ep_enable(struct usb_ep *ep,
+static int ci_pullup(struct usb_gadget *gadget, int is_on);
+static int ci_ep_enable(struct usb_ep *ep,
const struct usb_endpoint_descriptor *desc);
-static int mv_ep_disable(struct usb_ep *ep);
-static int mv_ep_queue(struct usb_ep *ep,
+static int ci_ep_disable(struct usb_ep *ep);
+static int ci_ep_queue(struct usb_ep *ep,
struct usb_request *req, gfp_t gfp_flags);
static struct usb_request *
-mv_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags);
-static void mv_ep_free_request(struct usb_ep *ep, struct usb_request *_req);
+ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags);
+static void ci_ep_free_request(struct usb_ep *ep, struct usb_request *_req);
-static struct usb_gadget_ops mv_udc_ops = {
- .pullup = mv_pullup,
+static struct usb_gadget_ops ci_udc_ops = {
+ .pullup = ci_pullup,
};
-static struct usb_ep_ops mv_ep_ops = {
- .enable = mv_ep_enable,
- .disable = mv_ep_disable,
- .queue = mv_ep_queue,
- .alloc_request = mv_ep_alloc_request,
- .free_request = mv_ep_free_request,
+static struct usb_ep_ops ci_ep_ops = {
+ .enable = ci_ep_enable,
+ .disable = ci_ep_disable,
+ .queue = ci_ep_queue,
+ .alloc_request = ci_ep_alloc_request,
+ .free_request = ci_ep_free_request,
};
/* Init values for USB endpoints. */
-static const struct usb_ep mv_ep_init[2] = {
+static const struct usb_ep ci_ep_init[2] = {
[0] = { /* EP 0 */
.maxpacket = 64,
.name = "ep0",
- .ops = &mv_ep_ops,
+ .ops = &ci_ep_ops,
},
[1] = { /* EP 1..n */
.maxpacket = 512,
.name = "ep-",
- .ops = &mv_ep_ops,
+ .ops = &ci_ep_ops,
},
};
-static struct mv_drv controller = {
+static struct ci_drv controller = {
.gadget = {
- .name = "mv_udc",
- .ops = &mv_udc_ops,
+ .name = "ci_udc",
+ .ops = &ci_udc_ops,
.is_dualspeed = 1,
},
};
/**
- * mv_get_qh() - return queue head for endpoint
+ * ci_get_qh() - return queue head for endpoint
* @ep_num: Endpoint number
* @dir_in: Direction of the endpoint (IN = 1, OUT = 0)
*
* This function returns the QH associated with particular endpoint
* and it's direction.
*/
-static struct ept_queue_head *mv_get_qh(int ep_num, int dir_in)
+static struct ept_queue_head *ci_get_qh(int ep_num, int dir_in)
{
return &controller.epts[(ep_num * 2) + dir_in];
}
/**
- * mv_get_qtd() - return queue item for endpoint
+ * ci_get_qtd() - return queue item for endpoint
* @ep_num: Endpoint number
* @dir_in: Direction of the endpoint (IN = 1, OUT = 0)
*
* This function returns the QH associated with particular endpoint
* and it's direction.
*/
-static struct ept_queue_item *mv_get_qtd(int ep_num, int dir_in)
+static struct ept_queue_item *ci_get_qtd(int ep_num, int dir_in)
{
return controller.items[(ep_num * 2) + dir_in];
}
/**
- * mv_flush_qh - flush cache over queue head
+ * ci_flush_qh - flush cache over queue head
* @ep_num: Endpoint number
*
* This function flushes cache over QH for particular endpoint.
*/
-static void mv_flush_qh(int ep_num)
+static void ci_flush_qh(int ep_num)
{
- struct ept_queue_head *head = mv_get_qh(ep_num, 0);
+ struct ept_queue_head *head = ci_get_qh(ep_num, 0);
const uint32_t start = (uint32_t)head;
const uint32_t end = start + 2 * sizeof(*head);
@@ -156,14 +156,14 @@ static void mv_flush_qh(int ep_num)
}
/**
- * mv_invalidate_qh - invalidate cache over queue head
+ * ci_invalidate_qh - invalidate cache over queue head
* @ep_num: Endpoint number
*
* This function invalidates cache over QH for particular endpoint.
*/
-static void mv_invalidate_qh(int ep_num)
+static void ci_invalidate_qh(int ep_num)
{
- struct ept_queue_head *head = mv_get_qh(ep_num, 0);
+ struct ept_queue_head *head = ci_get_qh(ep_num, 0);
uint32_t start = (uint32_t)head;
uint32_t end = start + 2 * sizeof(*head);
@@ -171,14 +171,14 @@ static void mv_invalidate_qh(int ep_num)
}
/**
- * mv_flush_qtd - flush cache over queue item
+ * ci_flush_qtd - flush cache over queue item
* @ep_num: Endpoint number
*
* This function flushes cache over qTD pair for particular endpoint.
*/
-static void mv_flush_qtd(int ep_num)
+static void ci_flush_qtd(int ep_num)
{
- struct ept_queue_item *item = mv_get_qtd(ep_num, 0);
+ struct ept_queue_item *item = ci_get_qtd(ep_num, 0);
const uint32_t start = (uint32_t)item;
const uint32_t end_raw = start + 2 * sizeof(*item);
const uint32_t end = roundup(end_raw, ARCH_DMA_MINALIGN);
@@ -187,14 +187,14 @@ static void mv_flush_qtd(int ep_num)
}
/**
- * mv_invalidate_qtd - invalidate cache over queue item
+ * ci_invalidate_qtd - invalidate cache over queue item
* @ep_num: Endpoint number
*
* This function invalidates cache over qTD pair for particular endpoint.
*/
-static void mv_invalidate_qtd(int ep_num)
+static void ci_invalidate_qtd(int ep_num)
{
- struct ept_queue_item *item = mv_get_qtd(ep_num, 0);
+ struct ept_queue_item *item = ci_get_qtd(ep_num, 0);
const uint32_t start = (uint32_t)item;
const uint32_t end_raw = start + 2 * sizeof(*item);
const uint32_t end = roundup(end_raw, ARCH_DMA_MINALIGN);
@@ -203,20 +203,20 @@ static void mv_invalidate_qtd(int ep_num)
}
static struct usb_request *
-mv_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags)
+ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags)
{
- struct mv_ep *mv_ep = container_of(ep, struct mv_ep, ep);
- return &mv_ep->req;
+ struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep);
+ return &ci_ep->req;
}
-static void mv_ep_free_request(struct usb_ep *ep, struct usb_request *_req)
+static void ci_ep_free_request(struct usb_ep *ep, struct usb_request *_req)
{
return;
}
static void ep_enable(int num, int in, int maxpacket)
{
- struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor;
+ struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
unsigned n;
n = readl(&udc->epctrl[num]);
@@ -226,22 +226,22 @@ static void ep_enable(int num, int in, int maxpacket)
n |= (CTRL_RXE | CTRL_RXR | CTRL_RXT_BULK);
if (num != 0) {
- struct ept_queue_head *head = mv_get_qh(num, in);
+ struct ept_queue_head *head = ci_get_qh(num, in);
head->config = CONFIG_MAX_PKT(maxpacket) | CONFIG_ZLT;
- mv_flush_qh(num);
+ ci_flush_qh(num);
}
writel(n, &udc->epctrl[num]);
}
-static int mv_ep_enable(struct usb_ep *ep,
+static int ci_ep_enable(struct usb_ep *ep,
const struct usb_endpoint_descriptor *desc)
{
- struct mv_ep *mv_ep = container_of(ep, struct mv_ep, ep);
+ struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep);
int num, in;
num = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
in = (desc->bEndpointAddress & USB_DIR_IN) != 0;
- mv_ep->desc = desc;
+ ci_ep->desc = desc;
if (num) {
int max = get_unaligned_le16(&desc->wMaxPacketSize);
@@ -259,15 +259,15 @@ static int mv_ep_enable(struct usb_ep *ep,
return 0;
}
-static int mv_ep_disable(struct usb_ep *ep)
+static int ci_ep_disable(struct usb_ep *ep)
{
- struct mv_ep *mv_ep = container_of(ep, struct mv_ep, ep);
+ struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep);
- mv_ep->desc = NULL;
+ ci_ep->desc = NULL;
return 0;
}
-static int mv_bounce(struct mv_ep *ep, int in)
+static int ci_bounce(struct ci_ep *ep, int in)
{
uint32_t addr = (uint32_t)ep->req.buf;
uint32_t ba;
@@ -306,7 +306,7 @@ flush:
return 0;
}
-static void mv_debounce(struct mv_ep *ep, int in)
+static void ci_debounce(struct ci_ep *ep, int in)
{
uint32_t addr = (uint32_t)ep->req.buf;
uint32_t ba = (uint32_t)ep->b_buf;
@@ -328,36 +328,36 @@ free:
free(ep->b_buf);
}
-static int mv_ep_queue(struct usb_ep *ep,
+static int ci_ep_queue(struct usb_ep *ep,
struct usb_request *req, gfp_t gfp_flags)
{
- struct mv_ep *mv_ep = container_of(ep, struct mv_ep, ep);
- struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor;
+ struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep);
+ struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
struct ept_queue_item *item;
struct ept_queue_head *head;
int bit, num, len, in, ret;
- num = mv_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
- in = (mv_ep->desc->bEndpointAddress & USB_DIR_IN) != 0;
- item = mv_get_qtd(num, in);
- head = mv_get_qh(num, in);
+ num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0;
+ item = ci_get_qtd(num, in);
+ head = ci_get_qh(num, in);
len = req->length;
- ret = mv_bounce(mv_ep, in);
+ ret = ci_bounce(ci_ep, in);
if (ret)
return ret;
item->next = TERMINATE;
item->info = INFO_BYTES(len) | INFO_IOC | INFO_ACTIVE;
- item->page0 = (uint32_t)mv_ep->b_buf;
- item->page1 = ((uint32_t)mv_ep->b_buf & 0xfffff000) + 0x1000;
- mv_flush_qtd(num);
+ item->page0 = (uint32_t)ci_ep->b_buf;
+ item->page1 = ((uint32_t)ci_ep->b_buf & 0xfffff000) + 0x1000;
+ ci_flush_qtd(num);
head->next = (unsigned) item;
head->info = 0;
DBG("ept%d %s queue len %x, buffer %p\n",
- num, in ? "in" : "out", len, mv_ep->b_buf);
- mv_flush_qh(num);
+ num, in ? "in" : "out", len, ci_ep->b_buf);
+ ci_flush_qh(num);
if (in)
bit = EPT_TX(num);
@@ -369,7 +369,7 @@ static int mv_ep_queue(struct usb_ep *ep,
return 0;
}
-static void handle_ep_complete(struct mv_ep *ep)
+static void handle_ep_complete(struct ci_ep *ep)
{
struct ept_queue_item *item;
int num, in, len;
@@ -377,8 +377,8 @@ static void handle_ep_complete(struct mv_ep *ep)
in = (ep->desc->bEndpointAddress & USB_DIR_IN) != 0;
if (num == 0)
ep->desc = &ep0_out_desc;
- item = mv_get_qtd(num, in);
- mv_invalidate_qtd(num);
+ item = ci_get_qtd(num, in);
+ ci_invalidate_qtd(num);
if (item->info & 0xff)
printf("EP%d/%s FAIL info=%x pg0=%x\n",
@@ -386,7 +386,7 @@ static void handle_ep_complete(struct mv_ep *ep)
len = (item->info >> 16) & 0x7fff;
ep->req.length -= len;
- mv_debounce(ep, in);
+ ci_debounce(ep, in);
DBG("ept%d %s complete %x\n",
num, in ? "in" : "out", len);
@@ -403,15 +403,15 @@ static void handle_ep_complete(struct mv_ep *ep)
static void handle_setup(void)
{
struct usb_request *req = &controller.ep[0].req;
- struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor;
+ struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
struct ept_queue_head *head;
struct usb_ctrlrequest r;
int status = 0;
int num, in, _num, _in, i;
char *buf;
- head = mv_get_qh(0, 0); /* EP0 OUT */
+ head = ci_get_qh(0, 0); /* EP0 OUT */
- mv_invalidate_qh(0);
+ ci_invalidate_qh(0);
memcpy(&r, head->setup_data, sizeof(struct usb_ctrlrequest));
writel(EPT_RX(0), &udc->epstat);
DBG("handle setup %s, %x, %x index %x value %x\n", reqname(r.bRequest),
@@ -425,7 +425,7 @@ static void handle_setup(void)
if ((r.wValue == 0) && (r.wLength == 0)) {
req->length = 0;
for (i = 0; i < NUM_ENDPOINTS; i++) {
- struct mv_ep *ep = &controller.ep[i];
+ struct ci_ep *ep = &controller.ep[i];
if (!ep->desc)
continue;
@@ -478,7 +478,7 @@ static void stop_activity(void)
{
int i, num, in;
struct ept_queue_head *head;
- struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor;
+ struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
writel(readl(&udc->epcomp), &udc->epcomp);
writel(readl(&udc->epstat), &udc->epstat);
writel(0xffffffff, &udc->epflush);
@@ -492,16 +492,16 @@ static void stop_activity(void)
& USB_ENDPOINT_NUMBER_MASK;
in = (controller.ep[i].desc->bEndpointAddress
& USB_DIR_IN) != 0;
- head = mv_get_qh(num, in);
+ head = ci_get_qh(num, in);
head->info = INFO_ACTIVE;
- mv_flush_qh(num);
+ ci_flush_qh(num);
}
}
}
void udc_irq(void)
{
- struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor;
+ struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
unsigned n = readl(&udc->usbsts);
writel(n, &udc->usbsts);
int bit, i, num, in;
@@ -563,7 +563,7 @@ void udc_irq(void)
int usb_gadget_handle_interrupts(void)
{
u32 value;
- struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor;
+ struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
value = readl(&udc->usbsts);
if (value)
@@ -572,9 +572,9 @@ int usb_gadget_handle_interrupts(void)
return value;
}
-static int mv_pullup(struct usb_gadget *gadget, int is_on)
+static int ci_pullup(struct usb_gadget *gadget, int is_on)
{
- struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor;
+ struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
if (is_on) {
/* RESET */
writel(USBCMD_ITC(MICRO_8FRAME) | USBCMD_RST, &udc->usbcmd);
@@ -602,7 +602,7 @@ static int mv_pullup(struct usb_gadget *gadget, int is_on)
void udc_disconnect(void)
{
- struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor;
+ struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
/* disable pullup */
stop_activity();
writel(USBCMD_FS2, &udc->usbcmd);
@@ -673,23 +673,23 @@ static int mvudc_probe(void)
controller.items[i] = (struct ept_queue_item *)imem;
if (i & 1) {
- mv_flush_qh(i - 1);
- mv_flush_qtd(i - 1);
+ ci_flush_qh(i - 1);
+ ci_flush_qtd(i - 1);
}
}
INIT_LIST_HEAD(&controller.gadget.ep_list);
/* Init EP 0 */
- memcpy(&controller.ep[0].ep, &mv_ep_init[0], sizeof(*mv_ep_init));
+ memcpy(&controller.ep[0].ep, &ci_ep_init[0], sizeof(*ci_ep_init));
controller.ep[0].desc = &ep0_in_desc;
controller.gadget.ep0 = &controller.ep[0].ep;
INIT_LIST_HEAD(&controller.gadget.ep0->ep_list);
/* Init EP 1..n */
for (i = 1; i < NUM_ENDPOINTS; i++) {
- memcpy(&controller.ep[i].ep, &mv_ep_init[1],
- sizeof(*mv_ep_init));
+ memcpy(&controller.ep[i].ep, &ci_ep_init[1],
+ sizeof(*ci_ep_init));
list_add_tail(&controller.ep[i].ep.ep_list,
&controller.gadget.ep_list);
}
@@ -699,7 +699,7 @@ static int mvudc_probe(void)
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
{
- struct mv_udc *udc;
+ struct ci_udc *udc;
int ret;
if (!driver)
@@ -715,7 +715,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
ret = mvudc_probe();
if (!ret) {
- udc = (struct mv_udc *)controller.ctrl->hcor;
+ udc = (struct ci_udc *)controller.ctrl->hcor;
/* select ULPI phy */
writel(PTS(PTS_ENABLE) | PFSC, &udc->portsc);
diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/ci_udc.h
similarity index 94%
rename from drivers/usb/gadget/mv_udc.h
rename to drivers/usb/gadget/ci_udc.h
index c7d8b33..42f6ef4 100644
--- a/drivers/usb/gadget/mv_udc.h
+++ b/drivers/usb/gadget/ci_udc.h
@@ -3,12 +3,12 @@
*
* Licensed under the GPL-2 or later.
*/
-#ifndef __GADGET__MV_UDC_H__
-#define __GADGET__MV_UDC_H__
+#ifndef __GADGET__CI_UDC_H__
+#define __GADGET__CI_UDC_H__
#define NUM_ENDPOINTS 6
-struct mv_udc {
+struct ci_udc {
#define MICRO_8FRAME 0x8
#define USBCMD_ITC(x) ((((x) > 0xff) ? 0xff : x) << 16)
#define USBCMD_FS2 (1 << 15)
@@ -48,7 +48,7 @@ struct mv_udc {
u32 epctrl[16]; /* 0x1c0 */
};
-struct mv_ep {
+struct ci_ep {
struct usb_ep ep;
struct list_head queue;
const struct usb_endpoint_descriptor *desc;
@@ -59,14 +59,14 @@ struct mv_ep {
uint8_t b_fast[64] __aligned(ARCH_DMA_MINALIGN);
};
-struct mv_drv {
+struct ci_drv {
struct usb_gadget gadget;
struct usb_gadget_driver *driver;
struct ehci_ctrl *ctrl;
struct ept_queue_head *epts;
struct ept_queue_item *items[2 * NUM_ENDPOINTS];
uint8_t *items_mem;
- struct mv_ep ep[NUM_ENDPOINTS];
+ struct ci_ep ep[NUM_ENDPOINTS];
};
struct ept_queue_head {
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index aa54b85..cc94771 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -144,10 +144,10 @@
#define gadget_is_m66592(g) 0
#endif
-#ifdef CONFIG_MV_UDC
-#define gadget_is_mv(g) (!strcmp("mv_udc", (g)->name))
+#ifdef CONFIG_CI_UDC
+#define gadget_is_ci(g) (!strcmp("ci_udc", (g)->name))
#else
-#define gadget_is_mv(g) 0
+#define gadget_is_ci(g) 0
#endif
#ifdef CONFIG_USB_GADGET_FOTG210
@@ -219,7 +219,7 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
return 0x19;
else if (gadget_is_m66592(gadget))
return 0x20;
- else if (gadget_is_mv(gadget))
+ else if (gadget_is_ci(gadget))
return 0x21;
else if (gadget_is_fotg210(gadget))
return 0x22;
diff --git a/include/configs/nitrogen6x.h b/include/configs/nitrogen6x.h
index f4ff5cd..e44ec88 100644
--- a/include/configs/nitrogen6x.h
+++ b/include/configs/nitrogen6x.h
@@ -31,7 +31,7 @@
#define CONFIG_BOARD_EARLY_INIT_F
#define CONFIG_MISC_INIT_R
#define CONFIG_MXC_GPIO
-#define CONFIG_MV_UDC
+#define CONFIG_CI_UDC
#define CONFIG_USBD_HS
#define CONFIG_USB_GADGET_DUALSPEED
#define CONFIG_USB_ETHER
diff --git a/include/configs/sansa_fuze_plus.h b/include/configs/sansa_fuze_plus.h
index a85eb1c..8cce34a 100644
--- a/include/configs/sansa_fuze_plus.h
+++ b/include/configs/sansa_fuze_plus.h
@@ -56,7 +56,7 @@
#define CONFIG_EHCI_MXS_PORT0
#define CONFIG_USB_MAX_CONTROLLER_COUNT 1
-#define CONFIG_MV_UDC /* ChipIdea CI13xxx UDC */
+#define CONFIG_CI_UDC /* ChipIdea CI13xxx UDC */
#define CONFIG_USB_GADGET_DUALSPEED
#define CONFIG_USB_ETHER
diff --git a/include/configs/xfi3.h b/include/configs/xfi3.h
index 022bc95..8e6b365 100644
--- a/include/configs/xfi3.h
+++ b/include/configs/xfi3.h
@@ -55,7 +55,7 @@
#define CONFIG_EHCI_MXS_PORT0
#define CONFIG_USB_MAX_CONTROLLER_COUNT 1
-#define CONFIG_MV_UDC /* ChipIdea CI13xxx UDC */
+#define CONFIG_CI_UDC /* ChipIdea CI13xxx UDC */
#define CONFIG_USB_GADGET_DUALSPEED
#define CONFIG_USB_ETHER
diff --git a/include/usb/mv_udc.h b/include/usb/ci_udc.h
similarity index 73%
rename from include/usb/mv_udc.h
rename to include/usb/ci_udc.h
index f6c7b5e..0dee504 100644
--- a/include/usb/mv_udc.h
+++ b/include/usb/ci_udc.h
@@ -6,9 +6,9 @@
*/
-#ifndef __MV_UDC_H__
-#define __MV_UDC_H__
+#ifndef __CI_UDC_H__
+#define __CI_UDC_H__
#define EP_MAX_PACKET_SIZE 0x200
#define EP0_MAX_PACKET_SIZE 64
-#endif /* __MV_UDC_H__ */
+#endif /* __CI_UDC_H__ */
--
1.8.5.3
3
4

06 Feb '14
This patch adds support for augmenting the BootStream with the
SMEM block. For further details on the SMEM block, please refer
to i.MX28 datasheet section 12.10 .
NOTE: It is absolutely optional to augment BootStream with SMEM
block. The SMEM block is only useful if you need to tweak
SPI NOR clockspeed or place the u-boot.sb elsewhere than
at block 1 of the SPI NOR (SMEM block resides in block 0).
The i.MX28 will boot BootStream image placed at block 0 in
SPI NOR directly.
Signed-off-by: Marek Vasut <marex(a)denx.de>
Cc: Stefano Babic <sbabic(a)denx.de>
---
tools/mxsboot.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 130 insertions(+), 3 deletions(-)
diff --git a/tools/mxsboot.c b/tools/mxsboot.c
index 90b2173..1575e8d 100644
--- a/tools/mxsboot.c
+++ b/tools/mxsboot.c
@@ -38,6 +38,14 @@ static uint32_t nand_erasesize = 128 * 1024;
static uint32_t sd_sector = 2048;
/*
+ * Layout for the SPI configuration block with the default settings
+ * in it. This is what the BootROM uses.
+ */
+static uint32_t spi_sector_size = 128;
+static uint32_t spi_image_offset = 64 * 1024; /* Block 1 */
+static uint32_t spi_clock_idx = 8; /* BootROM's default clock */
+
+/*
* Each of the U-Boot bootstreams is at maximum 1MB big.
*
* TWEAK this if, for some wild reason, you need to boot bigger image.
@@ -125,6 +133,49 @@ struct mx28_sd_config_block {
struct mx28_sd_drive_info drv_info[1];
};
+#define SSP_CLOCK_CONFIG_CLKSEL(n) ((n) << 0)
+#define SSP_CLOCK_CONFIG_IO_FRAC(n) ((n) << 1)
+#define SSP_CLOCK_CONFIG_SSP_FRAC(n) ((n) << 7)
+#define SSP_CLOCK_CONFIG_SSP_DIV(n) ((n) << 16)
+#define SSP_CLOCK_CONFIG_SSP_RATE(n) ((n) << 24)
+#define SSP_CLOCK_CONFIG(clksel, iofrac, sspfrac, sspdiv, ssprate) \
+ SSP_CLOCK_CONFIG_CLKSEL(clksel) | \
+ SSP_CLOCK_CONFIG_IO_FRAC(iofrac) | \
+ SSP_CLOCK_CONFIG_SSP_FRAC(sspfrac) | \
+ SSP_CLOCK_CONFIG_SSP_DIV(sspdiv) | \
+ SSP_CLOCK_CONFIG_SSP_RATE(ssprate)
+
+#define SSP_BOOT_FLAG_DISABLE_FASTREAD (1 << 0)
+
+struct mx28_spi_config_block {
+ uint32_t signature;
+ uint32_t boot_start_addr;
+ uint32_t sector_size;
+ uint32_t flags;
+ uint32_t clock_config_size;
+ uint32_t clock_config;
+};
+
+/* This is aligned with Table 12-27 in i.MX28 reference manual. */
+static const uint32_t mx28_spi_clock_config[] = {
+ 0x00000000, /* 0 ... invalid. */
+ SSP_CLOCK_CONFIG(1, 0, 0, 100, 0), /* 1 ... 0.24 MHz */
+ SSP_CLOCK_CONFIG(1, 0, 0, 24, 0), /* 2 ... 1 MHz */
+ SSP_CLOCK_CONFIG(1, 0, 0, 12, 0), /* 3 ... 2 MHz */
+ SSP_CLOCK_CONFIG(1, 0, 0, 6, 0), /* 4 ... 4 MHz */
+ SSP_CLOCK_CONFIG(1, 0, 0, 4, 0), /* 5 ... 6 MHz */
+ SSP_CLOCK_CONFIG(0, 18, 6, 10, 0), /* 6 ... 8 MHz */
+ SSP_CLOCK_CONFIG(0, 18, 6, 8, 0), /* 7 ... 10 MHz */
+ SSP_CLOCK_CONFIG(1, 0, 0, 2, 0), /* 8 ... 12 MHz */
+ SSP_CLOCK_CONFIG(0, 18, 5, 6, 0), /* 9 ... 16 MHz */
+ SSP_CLOCK_CONFIG(0, 18, 6, 4, 0), /* 10 .. 20 MHz */
+ SSP_CLOCK_CONFIG(0, 18, 8, 2, 0), /* 11 .. 30 MHz */
+ SSP_CLOCK_CONFIG(0, 18, 6, 2, 0), /* 12 .. 40 MHz */
+ SSP_CLOCK_CONFIG(0, 18, 5, 2, 0), /* 13 .. 48 MHz */
+ SSP_CLOCK_CONFIG(0, 21, 4, 2, 0), /* 14 .. 51.4 MHz */
+ 0x00000000 /* 15 .. invalid. */
+};
+
static inline uint32_t mx28_nand_ecc_size_in_bits(uint32_t ecc_strength)
{
return ecc_strength * 13;
@@ -445,6 +496,7 @@ static void usage(void)
" <type> type of image:\n"
" \"nand\" for NAND image\n"
" \"sd\" for SD image\n"
+ " \"spi\" for SPI NOR image\n"
" <infile> input file, the u-boot.sb bootstream\n"
" <outfile> output file, the bootable image\n"
"\n");
@@ -456,6 +508,11 @@ static void usage(void)
"\n"
"For SD boot, these options are accepted:\n"
" -p <sector> Sector where the SGTL partition starts\n"
+ "\n"
+ "For SPI NOR boot, these options are accepted:\n"
+ " -s <size> SPI NOR sector size\n"
+ " -i <size> SPI NOR image offset (multiple of page size)\n"
+ " -c <size> Clock INDEX (see Table 12-27 in MX28 RM)\n"
);
}
@@ -577,6 +634,54 @@ err0:
return ret;
}
+static int mx28_create_spi_image(int infd, int outfd)
+{
+ int ret = -1;
+ uint32_t *buf;
+ int size;
+ off_t fsize;
+ ssize_t wr_size;
+ struct mx28_spi_config_block *cb;
+
+ fsize = lseek(infd, 0, SEEK_END);
+ lseek(infd, 0, SEEK_SET);
+ size = fsize + spi_image_offset;
+
+ buf = malloc(size);
+ if (!buf) {
+ printf("Can not allocate output buffer of %d bytes\n", size);
+ goto err0;
+ }
+
+ ret = read(infd, (uint8_t *)buf + spi_image_offset, fsize);
+ if (ret != fsize) {
+ ret = -1;
+ goto err1;
+ }
+
+ cb = (struct mx28_spi_config_block *)buf;
+
+ cb->signature = 0x4d454d53;
+ cb->boot_start_addr = spi_image_offset;
+ cb->sector_size = spi_sector_size;
+ cb->flags = 0x0;
+ cb->clock_config_size = sizeof(cb->clock_config);
+ cb->clock_config = mx28_spi_clock_config[spi_clock_idx];
+
+ wr_size = write(outfd, buf, size);
+ if (wr_size != size) {
+ ret = -1;
+ goto err1;
+ }
+
+ ret = 0;
+
+err1:
+ free(buf);
+err0:
+ return ret;
+}
+
static int parse_ops(int argc, char **argv)
{
int i;
@@ -588,7 +693,10 @@ static int parse_ops(int argc, char **argv)
PARAM_ERASE,
PARAM_PART,
PARAM_SD,
- PARAM_NAND
+ PARAM_NAND,
+ PARAM_SPI_SECT_SIZE,
+ PARAM_SPI_IMAGE_OFFSET,
+ PARAM_SPI_CLOCK_IDX
};
int type;
@@ -596,15 +704,24 @@ static int parse_ops(int argc, char **argv)
return -1;
for (i = 1; i < argc; i++) {
+ /* NAND */
if (!strncmp(argv[i], "-w", 2))
type = PARAM_WRITE;
else if (!strncmp(argv[i], "-o", 2))
type = PARAM_OOB;
else if (!strncmp(argv[i], "-e", 2))
type = PARAM_ERASE;
+ /* SD/MMC */
else if (!strncmp(argv[i], "-p", 2))
type = PARAM_PART;
- else /* SD/MMC */
+ /* SPI */
+ else if (!strncmp(argv[i], "-s", 2))
+ type = PARAM_SPI_SECT_SIZE;
+ else if (!strncmp(argv[i], "-i", 2))
+ type = PARAM_SPI_IMAGE_OFFSET;
+ else if (!strncmp(argv[i], "-c", 2))
+ type = PARAM_SPI_CLOCK_IDX;
+ else
break;
tmp = strtol(argv[++i], &end, 10);
@@ -621,9 +738,17 @@ static int parse_ops(int argc, char **argv)
nand_erasesize = tmp;
if (type == PARAM_PART)
sd_sector = tmp;
+
+ if (type == PARAM_SPI_SECT_SIZE)
+ spi_sector_size = tmp;
+ if (type == PARAM_SPI_IMAGE_OFFSET)
+ spi_image_offset = tmp;
+ if (type == PARAM_SPI_CLOCK_IDX)
+ spi_clock_idx = tmp;
}
- if (strcmp(argv[i], "sd") && strcmp(argv[i], "nand"))
+ if (strcmp(argv[i], "sd") && strcmp(argv[i], "nand") &&
+ strcmp(argv[i], "spi"))
return -1;
if (i + 3 != argc)
@@ -664,6 +789,8 @@ int main(int argc, char **argv)
ret = mx28_create_sd_image(infd, outfd);
else if (!strcmp(argv[offset], "nand"))
ret = mx28_create_nand_image(infd, outfd);
+ else if (!strcmp(argv[offset], "spi"))
+ ret = mx28_create_spi_image(infd, outfd);
close(outfd);
err2:
--
1.8.5.3
1
0